Bootloader

Ein Bootloader ist ein Programmteil, der nach dem Start eines Mikrocontrollers ausgeführt werden kann und die Firmware einer Anwendung lädt, startet oder aktualisiert. Bei Mikrocontrollern liegt er meist in einem eigenen Bereich des Flash-Speichers. Nach einem Reset entscheidet der Bootloader, ob eine vorhandene Anwendung gestartet wird oder ob ein Update-Vorgang beginnen soll.

Was bedeutet ist ein Bootloader?

Ein Bootloader ist Code, der vor der eigentlichen Anwendungsfirmware ausgeführt wird. Seine Aufgabe besteht darin, eine Anwendung im Programmspeicher zu verwalten. Dazu kann er neue Firmware empfangen, den Flash-Speicher beschreiben, eine vorhandene Anwendung prüfen und anschließend in diese Anwendung springen.

Bei Arm-Cortex-M-Systemen folgt die Ausführung typischerweise einer festen Startlogik. Nach der Boot-ROM-Phase wird Code an einer definierten Adresse im Programmspeicher ausgeführt. Liegt der Bootloader an der Flash-Basisadresse, wird er nach dem Reset zuerst gestartet. Die Anwendungsfirmware liegt dann an einer anderen Flash-Adresse.

Bootloader und Anwendung werden meist als getrennte Firmware-Projekte gebaut. Dadurch entstehen zwei ausführbare Images mit eigenen Linker-Einstellungen. Die Anwendung muss nicht zwingend wissen, dass ein Bootloader vorhanden ist.

Wie funktioniert ein Bootloader?

Ein Bootloader durchläuft nach dem Start meist mehrere Prüfschritte. Zuerst stellt er fest, ob ein Update angefordert wurde. Eine solche Bedingung kann über einen GPIO-Pegel, einen Eintrag im nichtflüchtigen Speicher, eine RAM-Variable oder einen anderen anwendungsspezifischen Mechanismus abgebildet werden.

Wenn kein Update angefordert wurde, prüft der Bootloader häufig, ob die vorhandene Anwendung ausführbar ist. Dafür kann eine CRC über den Speicherbereich der Anwendung verwendet werden. Die berechnete Prüfsumme wird mit einem zuvor abgelegten Wert verglichen. Schlägt diese Prüfung fehl, sollte der Bootloader die Anwendung nicht starten, da der Flash-Inhalt unvollständig oder beschädigt sein kann.

Wenn ein Update ausgeführt wird, empfängt der Bootloader neue Firmware über einen festgelegten Kanal. Das kann zum Beispiel eine USB-Verbindung, eine Netzwerkschnittstelle oder eine andere Kommunikationsschnittstelle sein. Einige Mikrocontroller stellen dafür Schnittstellen wie In-System Programming oder In-Application Programming bereit. Das konkrete Löschen und Schreiben des Flash-Speichers hängt vom Mikrocontroller ab.

Nach erfolgreichem Update oder bestandener Prüfung startet der Bootloader die Anwendung. Bei Arm-Cortex-M-Systemen umfasst dieser Übergang mehrere Schritte:

  • aktivierte Interrupts im NVIC deaktivieren,
  • noch ausstehende Interrupts löschen,
  • verwendete Peripherie in einen geeigneten Zustand zurücksetzen,
  • SysTick deaktivieren, falls er vom Bootloader genutzt wurde,
  • gegebenenfalls Fault-Handler deaktivieren,
  • den Main Stack Pointer auf den Wert aus der Vektortabelle der Anwendung setzen,
  • die Adresse der Vektortabelle der Anwendung in das VTOR-Register schreiben,
  • den Reset-Vektor der Anwendung laden und dorthin springen.

Die Vektortabelle der Anwendung enthält bei Cortex-M-Systemen am Anfang den Startwert des Main Stack Pointer und danach den Reset-Vektor. Deshalb wird beim Sprung nicht einfach die Startadresse der Anwendung wie eine normale Funktion aufgerufen. Der Bootloader muss die Startbedingungen der Anwendung so herstellen, dass sie nicht von Zuständen des Bootloaders abhängt.

Wo wird ein Bootloader verwendet?

Bootloader werden in Mikrocontroller-Systemen eingesetzt, deren Firmware nach der Auslieferung aktualisiert werden soll. Das betrifft Geräte, die im Feld betrieben werden und bei denen ein Update über eine vorhandene Schnittstelle erfolgen muss.

Ein Bootloader kann genutzt werden, wenn der vorinstallierte Bootloader eines Mikrocontrollers nicht zum System passt. Gründe können eine nicht zugängliche Schnittstelle, ein ungeeigneter Update-Auslöser oder eine nicht passende Speicherorganisation sein. Auch eigene Anforderungen an Prüfschritte, Update-Markierungen oder den Ablauf des Firmware-Wechsels können einen eigenen Bootloader erforderlich machen.

Typische Einsatzkontexte sind Systeme mit separater Anwendungsfirmware, Flash-Speicher mit festen Löschgrößen und Update-Kanälen, die nicht vom Hersteller-Bootloader abgedeckt werden.

Eigenschaften

Ein Bootloader benötigt einen fest reservierten Speicherbereich. Wenn der Bootloader am Anfang des Programmspeichers liegt, wird er nach einem Reset zuerst ausgeführt. Die Anwendung beginnt dann an einer höheren Adresse.

Die Speicheraufteilung muss zur Löschstruktur des Flash-Speichers passen. Flash-Speicher ist in Pages, Sectors, Blocks oder Banks gegliedert. Die kleinste löschbare Einheit legt fest, wie Bootloader und Anwendung getrennt werden müssen. Bootloader und Anwendung sollten nicht in derselben löschbaren Einheit liegen, weil das Löschen eines Anwendungsteils sonst auch Bootloader-Code entfernen könnte.

Die Linker-Konfigurationen von Bootloader und Anwendung müssen zueinander passen. Der Bootloader erhält einen Flash-Bereich, der für ihn reserviert ist. Die Anwendung erhält eine Startadresse außerhalb dieses Bereichs. Für beide Firmware-Images werden getrennte Linker-Dateien oder getrennte Linker-Einstellungen verwendet.

Ein Bootloader benötigt außerdem eine Update-Bedingung. Ein GPIO-Pin kann beim Reset abgefragt werden. Alternativ kann die Anwendung vor einem Software-Reset einen Marker in Flash, EEPROM oder in einem gemeinsam definierten RAM-Bereich setzen. Der Bootloader liest diesen Marker nach dem Neustart und wechselt dann in den Update-Modus. Wenn ein nichtflüchtiger Marker verwendet wird, sollte er beim Eintritt in den Update-Modus wieder gelöscht werden, damit ein späterer Neustart ohne neues Update nicht dauerhaft im Update-Modus bleibt.

Abgrenzung zu verwandten Begriffen

Boot-ROM als Gegensatz zum Bootloader ist fest im Mikrocontroller oder Systemchip vorhanden und wird vor dem Bootloader ausgeführt. Sie enthält herstellerspezifischen Startcode. Ein Bootloader im Flash-Speicher kann dagegen Teil der eigenen Firmware sein und an die eigene Speicheraufteilung und die eigenen Update-Abläufe angepasst werden.

Die Anwendungsfirmware enthält die eigentliche Gerätefunktion. Sie kann unabhängig vom Bootloader gebaut werden. Der Bootloader startet diese Anwendung, nachdem er Prüfung und Update-Entscheidung abgeschlossen hat.

In-System Programming bezeichnet eine Möglichkeit, Programmspeicher über eine Programmierschnittstelle zu beschreiben. In-Application Programming bezeichnet Mechanismen, mit denen Code aus der laufenden Firmware heraus Flash-Inhalte ändern kann. Ein Bootloader kann solche Mechanismen nutzen, ist aber selbst der Programmteil, der den Update-Ablauf steuert.

Ein Linker-Skript ist kein Bootloader. Es beschreibt, welche Speicherbereiche ein Firmware-Image verwenden darf. Für ein System mit Bootloader legt das Linker-Skript der Anwendung fest, dass deren Code nicht an der Flash-Basisadresse des Bootloaders beginnt.

Zurück zum Glossar