Warum benötigen wir ein separates Programm im selben Flash-Programmspeicher eines Mikrocontrollers, insbesondere STM32F103, das als Bootloader bezeichnet wird?
Was ist das Besondere daran, es vom Hauptanwendungsprogramm getrennt zu halten?
Macht ein Bootloader eines mikroprozessorbasierten Systems (z. B. PowerPC MPC8270) im Allgemeinen die gleiche Aufgabe wie der eines Mikrocontrollers (z. B. ARM STM32F103) oder führen sie grundlegend unterschiedliche Aufgaben aus, und dennoch werden beide als „Bootloader“ bezeichnet? ?
Ein Bootloader auf einem Mikrocontroller ist für die Aktualisierung der Hauptfirmware über einen anderen Kommunikationskanal als den Programmierkopf verantwortlich. Dies ist nützlich, um Firmware im Feld über BLE, UART, I2C, SD-Karten, USB usw. zu aktualisieren. Es wäre äußerst unpraktisch, von Kunden zu verlangen, Programmierer zu kaufen, nur um die Firmware auf ihren Geräten zu aktualisieren.
Der Grund, warum der Bootloader separat gehalten wird, ist die Zuverlässigkeit. Der Bootloader und der Anwendungscode werden in separaten Flash-Abschnitten abgelegt, sodass der Anwendungscode vom Bootloader gelöscht und neu geschrieben werden kann, ohne dass etwas am Bootloader-Code geändert wird.
Wenn der Bootloader und die Anwendung zusammengehalten würden, müsste der Bootloader-Code in den RAM kopiert werden, bevor er ausgeführt werden könnte, da jedes Firmware-Update den Bootloader-Code im Flash löschen würde. Wenn die Stromversorgung mit dem Bootloader-Code im RAM unterbrochen und der Flash gelöscht würde, würde das Gerät gemauert werden.
main()
Funktion. Beim Einschalten wird der Bootloader-Startcode ausgeführt und ruft die main()
. Das Bootloader-Programm sucht nach einem gültigen Anwendungsprogramm und springt dann zum Startcode des Anwendungsprogramms, der die main()
. Der Startcode jedes Programms initialisiert die C-Laufzeitumgebung für das jeweilige Programm (dh initialisiert Variablen, Stack usw.) und typischerweise kehrt keines der Programme main()
jemals zum Startcode zurück.main
@kkrambo Obwohl allgemein wahr, gibt es keine Anforderung (oder allgemein gültige Tatsache), dass ein Bootloader überhaupt
in C oder einer von C abgeleiteten Sprache mit einem geschrieben wird .Damit sich der Ladevorgang von Fehlern erholen kann. Angenommen, während eines Upgrades liegt ein Kommunikationsfehler vor oder die Stromversorgung wird unterbrochen. Wenn der Bootloader Teil der Anwendung wäre, die Sie aktualisieren, könnte der Benutzer es nicht erneut versuchen, ohne spezielle Hardware zum erneuten Flashen des Bootloaders zu verwenden.
Einige Mikrocontroller können keinen Code aus dem RAM ausführen. Wenn der Bootloader mit dem Rest der Software gemischt wurde, könnten Sie Ihre Software nicht wirklich aktualisieren, da Sie keine Flash-Seiten löschen können, aus denen Sie gerade ausführen. Die Problemumgehung besteht darin, den neuen Code zuerst in die zweite Hälfte des Flashs zu brennen und dann dorthin zu springen. Der neue Code kopiert sich dann in die erste Hälfte des Flashs. Der Nachteil ist natürlich, dass das Brennen von Flash normalerweise langsam ist und der Ladevorgang jetzt, da Sie es zweimal tun müssen, bis zu doppelt so lange dauern kann. Außerdem begrenzt diese Problemumgehung Ihre Anwendungsgröße auf nicht mehr als die Hälfte Ihres gesamten Flash.
Gut geschriebene Bootloader versuchen zu überprüfen, ob gültiger Code auf dem Gerät vorhanden ist, bevor sie versuchen, ihn auszuführen. Wenn der Bootloader und anderer Code vermischt wurden, wie können Sie dann sicher sein, dass Ihre Validierungsroutine funktioniert, wenn nicht der gesamte Code geladen wird?
Authentifizierung. Sichere Bootloader versuchen vor der Ausführung zu überprüfen, ob die geladene Anwendung mit einer digitalen Signatur übereinstimmt. Aber wenn der Bootloader und anderer Code gemischt wurden, dann können Sie nicht kontrollieren, was auf dem Gerät läuft, denn sobald der Benutzer neuen Code lädt, können Sie nicht kontrollieren, was beim Start passiert.
Sie sind im Allgemeinen dazu da, Ihnen zu ermöglichen, Ihr Hauptanwendungsprogramm zu aktualisieren.
Sie benötigen einen Code, der weiß, wie ein Teil des internen Flash gelöscht und neu programmiert werden kann. Dies kann nicht das Hauptprogramm sein, da er nach dem Löschen selbst nicht neu programmiert werden kann.
Der Bootloader ermöglicht es der MCU, mit etwas anderem zu kommunizieren, um ein neues Programm zu akzeptieren, zu speichern und nach einem Reset auszuführen. Wenn Sie keinen Bootloader hatten, wird ein Programmierer benötigt, um auf den Speicher zuzugreifen und das Programm zu installieren.
Zusätzlich zu den anderen richtigen Antworten zum Zulassen der Neuprogrammierung der Haupt-Firmware vom Bootloader besteht ein weiterer Vorteil des separaten Bootloaders darin, dass Sie die Aufgaben "Einmal beim Booten ausführen" logisch von dem Code trennen können, den Sie während der Laufzeit benötigen. Nachdem der Bootloader seine anfänglichen Konfigurationsaufgaben abgeschlossen hat, kann die Hauptfirmware den Bootloader mit all seinem nicht mehr benötigten Code aus dem Speicher entfernen, wodurch erheblicher RAM-Speicherplatz eingespart wird. Es ist möglich, dies auf andere Weise zu erreichen, aber die Trennung von Bootloader und Firmware macht es auf vielen Architekturen viel einfacher.
Die kurze Antwort ist, weil Software großartig ist.
Sie könnten alles, was der Bootloader tut, als "reine Hardware" haben. Aber es ist viel, viel, viel einfacher, die Aufgaben, die der Bootloader erledigt, als Software zu schreiben und dann von Hardware zu interpretieren.
Diese Aufgaben können das Einrichten der Hardware für die Ausführung der "echten" Software (z. B. auf einem Raspberry Pi (über @ErikF)) und das Vorhandensein eines Protokolls umfassen, um das "echte" Programm zu ersetzen, bevor es ausgeführt wird (überprüfen Sie einen Pin, falls vorhanden). Dieser Pin wird gesetzt und dann das echte Programm neu geflasht) oder sogar die Softwareumgebung für das "echte" Programm einrichten.
Bei weniger mikroskalierter Software, wenn Sie eine ausführbare Datei ausführen, bewegt der Anwendungslader Dinge wie das Laden von Teilen Ihrer Daten in den Speicher, repariert manchmal Adressen, richtet Argumente für Haupt- oder andere globale Dinge ein, dreht Ihre vom Betriebssystem bereitgestellten Bibliotheken hoch und springt dann zum Anfang des _main
Codes. Einige dieser Dinge können von einem Bootloader erledigt werden.
In einem Mikrocontroller könnten einige der Aufgaben, die ein Bootloader erledigt, in das Programm aufgeteilt werden. Der Compiler für Ihre Plattform könnte den "Setup"-Code automatisch in jede ausführbare Datei einfügen.
Aber es im Bootloader zu haben bedeutet, dass derselbe Compiler möglicherweise auf unterschiedlicher Hardware funktioniert, da der Bootloader den Unterschied zwischen den Plattformen "verbergen" kann.
Krönen Sie das mit der Tatsache, dass ein Flash des Hauptprogramms den Bootloader nicht gefährdet (und die Möglichkeit, das Hauptprogramm erneut zu flashen), und dass es eine ziemlich großartige Sache ist, einen nicht trivialen Bootloader zu haben.
Ein Teil der Frage, der bisher nicht beantwortet wurde, ist der Unterschied zwischen Bootloadern auf Mikrocontrollern und Mikroprozessorsystemen.
Mikrocontroller
Die meisten Mikrocontroller haben einen eingebauten ROM-Speicher, der ihren Programmcode enthält. Das Ändern dieses Codes erfordert normalerweise ein Programmiergerät, das sich mit der Programmierschnittstelle des Mikrocontrollers verbindet (z. B. ISP auf ATMega). Aber diese Programmierschnittstellen sind im Vergleich zu anderen Schnittstellen in der Regel nicht sehr komfortabel zu verwenden, da sie im gegebenen Kontext möglicherweise nicht ohne Weiteres verfügbar sind. Während beispielsweise fast jeder Computer über USB-Anschlüsse verfügt, ist die für ISP benötigte SPI-Schnittstelle viel seltener, und andere Schnittstellen wie die PID-Schnittstelle, die auf ATXMega verwendet wird, werden nur von dedizierter Programmierhardware unterstützt.
Wenn Sie beispielsweise die Software von einem normalen Computer ohne externe Hardware aktualisieren möchten, können Sie einen Bootloader verwenden, der von einer anderen Art von Schnittstelle liest (z. B. RS232, USB oder RS232 über USB wie beim Arduino), um das Gerät zu programmieren über gängige Schnittstellen.
Wenn Sie diese Funktionalität nicht benötigen, ist der Bootloader jedoch vollständig optional. Der Mikrocontroller kann seinen Code immer noch vollständig ohne den Bootloader ausführen.
Mikroprozessor
Bei einem Mikroprozessor sind die Dinge etwas anders. Während die meisten Mikroprozessoren über ein ROM verfügen, das groß genug für einen Bootloader ist, sind diese ROMs nicht annähernd groß genug, um ein vollständiges Betriebssystem aufzunehmen. Der Zweck des Bootloaders besteht also darin, Hardware zu initialisieren, nach einem bootfähigen Betriebssystem zu suchen, es zu laden und auszuführen. Der Bootloader ist also für jeden einzelnen Start von entscheidender Bedeutung.
Auf x86/x64-Systemen ist dieser Bootloader entweder das BIOS oder das UEFI (im Grunde eine neuere Version eines BIOS).
Manchmal laufen sogar mehrere Bootloader in einer Kette. Wenn Sie beispielsweise ein Dual-Boot-System mit Windows und Linux haben, erhalten Sie möglicherweise Folgendes:
In diesem Fall gab es also drei Softwareteile, die als Bootloader betrachtet werden können. Sowohl GRUB als auch der Windows-Bootloader sind hauptsächlich dazu da, dem Benutzer eine bequemere Boot-Auswahloption zu bieten, als das BIOS/UEFI ihnen bieten würde. Es ermöglicht auch das Starten mehrerer Betriebssysteme von derselben Festplatte oder sogar derselben Partition.
TLDR
Während der Bootloader in beiden Systemen ähnliche Dinge tut (dem Benutzer hilft, den zu bootenden Code auszuwählen), unterscheiden sich beide stark darin, wie sie dies erreichen und was sie genau tun.
Eine Antwort, die nicht behandelt wurde, ist die Notwendigkeit der Trennung von Bedenken in Bezug auf den Startcode.
Dies geschieht, um bestimmte Dinge einzurichten, wie:
Dies ist eine sehr grobe Annäherung an die durchgeführten Schritte, und ich beschreibe den ARM-Startvorgang, er ist für x86 und andere Architekturen wieder anders.
Der Hauptgrund bleibt jedoch derselbe: Die Zuweisung des C-Stacks muss von der Assemblierung aus erfolgen.
Emobe
Heiße Licks
Ghellquist