Was ist ein Bootloader und wie würde ich ihn entwickeln?

53

Ich habe viele Projekte getroffen, in denen ein AVR-Mikrocontroller mit einem Bootloader (wie dem Arduino) verwendet wird, aber ich verstehe das Konzept nicht sehr gut.

Wie kann ich einen Bootloader (für jeden Mikrocontroller) erstellen?

Wie wird mein Bootloader nach dem Schreiben auf den Mikrocontroller programmiert (wie jedes auf dem Flash-ROM des AVR gebrannte .hex-Programm oder eine andere Methode)?

mina_g
quelle
10
Sie haben es mit dem Bootloader- Tag versehen. Haben Sie das gelesen? Wenn ja, haben Sie die Fragen zu Arduino Bootloader , Arduino Bootloader Follow On , Arduino Bootloader , guten Tools oder Methoden zum Verständnis der Struktur von Bootloader und Arduino Bootloader-Details gelesen ? Diese Angaben beziehen sich alle auf Teile Ihrer Ausgangsfrage. Ich habe es auf das Neue reduziert.
Kevin Vermeer
Ein Artikel über die BootLoader-Entwurfsmethode: beningo.com/wp-content/uploads/images/Papers/…
yahya tawil
2
@ KevinVermeer Ich denke, seine Frage ist einfacher.
Richieqianle

Antworten:

103

Ein Bootloader ist ein Programm, das im zu programmierenden Mikrocontroller abläuft. Es empfängt neue Programminformationen extern über ein Kommunikationsmittel und schreibt diese Informationen in den Programmspeicher des Prozessors.

Dies steht im Gegensatz zu der normalen Art, das Programm in den Mikrocontroller zu bekommen, der zu diesem Zweck über spezielle Hardware in das Mikro eingebaut ist. Bei PICs ist dies eine SPI-ähnliche Schnittstelle. Wenn ich mich recht erinnere, verwenden AVRs Jtag oder zumindest einige von ihnen. In beiden Fällen ist eine externe Hardware erforderlich, die die Programmierstifte genau richtig bewegt, um die Informationen in den Programmspeicher zu schreiben. Die HEX-Datei, die den Inhalt des Programmspeichers beschreibt, stammt von einem Universalcomputer, sodass diese Hardware auf der einen Seite mit dem Computer und auf der anderen Seite mit den speziellen Programmierstiften des Mikros verbunden ist. Mein Unternehmen stellt PIC-Programmierer unter anderem als Nebentätigkeit zur Verfügung, daher bin ich mit diesem Prozess für PICs bestens vertraut.

Der wichtige Punkt der externen Programmierung über spezielle Hardware ist, dass sie unabhängig von den vorhandenen Inhalten des Programmspeichers funktioniert. Mikrocontroller beginnen mit einem gelöschten oder unbekannten Programmspeicher, sodass nur durch externe Programmierung das erste Programm in ein Mikro geschrieben werden kann.

Wenn Sie sich sicher sind, welches Programm Sie in Ihr Produkt laden möchten und Ihr Volumen hoch genug ist, können Sie den Hersteller oder einen Distributor Programmchips für Sie haben. Der Chip wird wie jeder andere Chip auf die Platine gelötet und das Gerät ist betriebsbereit. Dies kann zum Beispiel für ein Spielzeug angemessen sein. Sobald die Firmware fertig ist, ist sie ziemlich fertig und wird in großen Mengen produziert.

Wenn Ihr Volumen geringer oder wichtiger ist, erwarten Sie eine kontinuierliche Firmware-Entwicklung und Fehlerbehebungen. Sie möchten keine vorprogrammierten Chips kaufen. In diesem Fall werden leere Chips auf die Platine montiert und die Firmware muss im Rahmen des Produktionsprozesses auf den Chip geladen werden. In diesem Fall müssen die Hardware-Programmierzeilen irgendwie zur Verfügung gestellt werden. Dies kann über einen expliziten Anschluss oder über Pogo-Pin-Pads erfolgen, wenn Sie bereit sind, eine Produktionstestvorrichtung zu erstellen. Oft müssen solche Produkte trotzdem getestet und kalibriert werden, so dass die zusätzlichen Kosten für das Schreiben des Programms auf den Prozessor in der Regel minimal sind. Manchmal, wenn kleine Prozessoren verwendet werden, wird zuerst eine spezielle Firmware für den Produktionstest in den Prozessor geladen. Dies erleichtert das Testen und Kalibrieren des Geräts. Dann wird die echte Firmware geladen, nachdem bekannt ist, dass die Hardware funktioniert. In diesem Fall gibt es einige Überlegungen zum Schaltungsentwurf, um den Zugriff auf die Programmierleitungen ausreichend zu ermöglichen, damit der Programmiervorgang funktioniert, aber auch um die Schaltung nicht zu sehr zu stören. Weitere Einzelheiten hierzu finden Sie unter myIn-Circuit-Programmierung schreiben.

Soweit so gut und es wird kein Bootloader benötigt. Ziehen Sie jedoch ein Produkt mit einer relativ komplexen Firmware in Betracht, die vor Ort aktualisiert werden soll, oder lassen Sie sogar zu, dass der Endkunde ein Upgrade durchführt. Sie können nicht davon ausgehen, dass der Endkunde über ein Programmiergerät verfügt oder weiß, wie man eines richtig einsetzt, selbst wenn Sie eines zur Verfügung gestellt haben. Eigentlich macht das einer meiner Kunden. Wenn Sie ihre spezielle Feldanpassungsoption kaufen, erhalten Sie einen meiner Programmierer mit dem Produkt.

In den meisten Fällen möchten Sie jedoch, dass der Kunde ein Programm auf einem PC ausführt und die Firmware auf magische Weise aktualisiert. Hier kommt ein Bootloader ins Spiel, insbesondere wenn Ihr Produkt bereits über einen Kommunikationsanschluss verfügt, der problemlos mit einem PC wie USB, RS-232 oder Ethernet verbunden werden kann. Der Kunde führt ein PC-Programm aus, das bereits im Micro mit dem Bootloader kommuniziert. Dadurch wird die neue Binärdatei an den Bootloader gesendet, der sie in den Programmspeicher schreibt und dann den neuen Code ausführt.

Klingt einfach, ist es aber nicht, zumindest nicht, wenn dieser Prozess robust sein soll. Was ist, wenn ein Kommunikationsfehler auftritt und die neue Firmware zum Zeitpunkt des Eintreffens beim Bootloader beschädigt ist? Was ist, wenn die Stromversorgung während des Startvorgangs unterbrochen wird? Was ist, wenn der Bootloader einen Bug hat und auf sich selbst scheißt?

Ein vereinfachtes Szenario ist, dass der Bootloader immer nach dem Zurücksetzen ausgeführt wird. Es wird versucht, mit dem Host zu kommunizieren. Wenn der Host antwortet, teilt er dem Bootloader entweder mit, dass er nichts Neues hat, oder sendet ihm neuen Code. Wenn der neue Code eintrifft, wird der alte Code überschrieben. Sie fügen immer eine Prüfsumme mit hochgeladenem Code ein, damit der Bootloader erkennen kann, ob die neue App intakt ist. Wenn nicht, bleibt es im Bootloader und fordert ständig einen Upload an, bis etwas mit einer gültigen Prüfsumme in den Speicher geladen wird. Dies kann für ein Gerät akzeptabel sein, das immer verbunden ist und auf dem Host möglicherweise eine Hintergrundaufgabe ausgeführt wird, die auf Bootloader-Anforderungen reagiert. Dieses Schema eignet sich nicht für Einheiten, die weitgehend autonom sind und nur gelegentlich eine Verbindung zu einem Host-Computer herstellen.

Normalerweise ist der oben beschriebene einfache Bootloader nicht akzeptabel, da kein Fail-Safe besteht. Wenn ein neues App-Image nicht intakt empfangen wird, soll das Gerät das alte Image weiterhin ausführen und nicht tot sein, bis ein erfolgreicher Upload durchgeführt wurde. Aus diesem Grund enthält die Firmware normalerweise zwei spezielle Module, einen Uploader und einen Bootloader. Der Uploader ist Teil der Haupt-App. Im Rahmen der regelmäßigen Kommunikation mit dem Host kann ein neues App-Image hochgeladen werden. Dies erfordert einen vom Haupt-App-Image getrennten Speicher, z. B. ein externes EEPROM, oder verwendet einen größeren Prozessor, sodass die Hälfte des Programmspeicherplatzes für die Speicherung des neuen App-Image reserviert werden kann. Der Uploader schreibt nur das empfangene neue App-Image, führt es jedoch nicht aus. Wenn der Prozessor zurückgesetzt wird, was auf Befehl des Hosts nach einem Upload passieren kann, Der Bootloader läuft. Dies ist jetzt ein völlig eigenständiges Programm, das keine externe Kommunikationsfähigkeit benötigt. Es vergleicht die aktuelle und die hochgeladene App-Version, überprüft deren Prüfsummen und kopiert das neue Image in den App-Bereich, wenn sich die Versionen unterscheiden, und überprüft die neue Image-Prüfsumme. Wenn das neue Image beschädigt ist, wird die alte App einfach wie zuvor ausgeführt.

Ich habe viele Bootloader gemacht, und keiner ist derselbe. Es gibt keinen Allzweck-Bootloader, auch wenn einige der Mikrocontroller-Unternehmen dies wünschen. Jedes Gerät hat seine eigenen Anforderungen und besonderen Umstände im Umgang mit dem Host. Hier sind nur einige der Bootloader- und manchmal Uploader-Konfigurationen, die ich verwendet habe:

  1. Einfacher Bootloader. Dieses Gerät hatte eine serielle Leitung und wurde an einen Host angeschlossen und bei Bedarf eingeschaltet. Der Bootloader wurde nach dem Zurücksetzen ausgeführt und hat einige Antworten auf Upload-Anforderungen an den Host gesendet. Wenn das Upload-Programm ausgeführt wird, antwortet es und sendet ein neues App-Image. Wenn es nicht innerhalb von 500 ms antwortet, gibt der Bootloader die vorhandene App auf und führt sie aus. Um die Firmware zu aktualisieren, mussten Sie zuerst die Updater-App auf dem Host ausführen, dann die Verbindung herstellen und das Gerät einschalten.

  2. Programmspeicher-Uploader. Hier haben wir das nächstgrößere PIC verwendet, das doppelt so viel Programmspeicher hatte. Der Programmspeicher wurde grob in 49% Haupt-App, 49% neues App-Image und 2% Bootloader aufgeteilt. Der Bootloader wird nach dem Zurücksetzen ausgeführt und kopiert das neue App-Image unter den richtigen Bedingungen auf das aktuelle App-Image.

  3. Externes EEPROM-Image. Wie Nr. 2, außer dass ein externes EEPROM zum Speichern des neuen App-Images verwendet wurde. In diesem Fall wäre der Prozessor mit mehr Arbeitsspeicher auch physisch größer und in einer anderen Unterfamilie, die nicht über den von uns benötigten Peripheriemix verfügte.

  4. TCP-Bootloader. Dies war der komplexeste von allen. Ein großer PIC 18F wurde verwendet. Das letzte Viertel des Arbeitsspeichers enthielt den Bootloader, der über eine eigene vollständige Kopie eines TCP-Netzwerkstapels verfügte. Der Bootloader wurde nach dem Zurücksetzen ausgeführt und hat versucht, eine Verbindung zu einem speziellen Upload-Server an einem bekannten Port mit einer zuvor konfigurierten IP-Adresse herzustellen. Dies galt für große Installationen, bei denen immer ein dedizierter Server für das gesamte System vorhanden war. Jedes kleine Gerät meldet sich nach dem Zurücksetzen beim Upload-Server an und erhält bei Bedarf eine neue App-Kopie. Der Bootloader würde die vorhandene App mit der neuen Kopie überschreiben, sie jedoch nur ausführen, wenn die Prüfsumme überprüft wurde. Wenn nicht, kehrt es zum Upload-Server zurück und versucht es erneut.

    Da der Bootloader selbst ein komplizierter Code war, der einen vollständigen TCP-Netzwerkstapel enthielt, musste er auch vor Ort aktualisierbar sein. Die Art und Weise, wie wir das gemacht haben, war, dass der Upload-Server ihm eine spezielle App zufüttert, deren einziger Zweck es war, den Bootloader nach seiner Ausführung zu überschreiben und dann den Computer zurückzusetzen, damit der neue Bootloader ausgeführt wird, wodurch der Upload-Server den sendet aktuelles Haupt-App-Image. Technisch gesehen war ein Stromausfall in den wenigen Millisekunden, die die spezielle App benötigte, um ein neues Image über den Bootloader zu kopieren, ein nicht behebbarer Fehler. In der Praxis ist das nie passiert. Wir waren mit der sehr unwahrscheinlichen Möglichkeit einverstanden, da es sich bei diesen Geräten um Teile großer Anlagen handelte, in denen bereits Personen für die Wartung des Systems zuständig waren, was gelegentlich bedeutete, die eingebetteten Geräte aus anderen Gründen zu ersetzen.

Hoffentlich können Sie sehen, dass es eine Reihe anderer Möglichkeiten gibt, von denen jede ihre eigenen Kompromisse in Bezug auf Risiko, Geschwindigkeit, Kosten, Benutzerfreundlichkeit, Ausfallzeiten usw. aufweist.

Olin Lathrop
quelle
1
Alle AVRs mit Ausnahme der Xmega-Familie (die über eine neue 2-Draht-Schnittstelle verfügt) verwenden eine SPI-Schnittstelle, während sie zurückgesetzt bleiben. Größere haben auch JTAG, einige haben parallele Programmierung, und kleinere benötigen möglicherweise Hochspannung, wenn das Zurücksetzen als E / A neu konfiguriert wurde. Einige MCUs, wie die Parallax Propeller- und Motorola / Freescale 68HC08-Familie, haben keine zu minimale Programmierhardware, sondern Bootloader im ROM.
Yann Vernier
Es vergleicht die aktuelle und die hochgeladene App-Version, überprüft deren Prüfsummen und kopiert das neue Image in den App-Bereich, wenn sich die Versionen unterscheiden, und überprüft die neue Image-Prüfsumme. Ja, aber wenn die Stromversorgung während dieser Aktion unterbrochen wird, ist das Bild im "App-Bereich" beschädigt. Ich nehme an, es ist besser, eine Bootloader-Failsafe-App zu haben, die die neue App in das mcu-Flash schreibt, und wenn die Prüfsumme gültig ist, schreibt sie auch irgendwo "OK, um die neue App zu booten". Zu Beginn wird geprüft, ob das Booten der neuen App in
Ordnung ist. Andernfalls wird
@Erv: Wenn während des Kopierens der neuen Version auf die aktuelle die Stromversorgung ausfällt, schlägt die Prüfsumme der aktuellen Version fehl, wenn die Stromversorgung wiederhergestellt wird und der Bootloader erneut ausgeführt wird. Normalerweise setze ich das Prüfsummenwort ganz am Ende des Bildes, damit bei einem teilweisen Schreiben die Wahrscheinlichkeit eines Prüfsummenfehlers sehr hoch ist.
Olin Lathrop
Hallo. Ich kann Ihnen den Bootloader Typ 5 empfehlen - anstelle des TCP-Stacks können Sie UDP implementieren. Verwenden Sie dann TFTP, um das Update oder das native Protokoll herunterzuladen.
i486
22

Was ist das Konzept des Bootloaders?

Stellen Sie sich dieses Szenario vor: Ihr Mikrocontroller verfügt über ausreichend Speicherplatz, um mehr als 2-3 voneinander unabhängige Programme oder Anwendungen zu speichern. Angenommen, Sie möchten beim Booten Ihres Geräts möglicherweise auswählen können, welches Gerät ausgeführt werden soll. Was würden Sie also brauchen, um dies zu unterstützen? Sie benötigen ein Startprogramm, mit dem Sie beim Booten zwischen den anderen wählen können.

Wie es funktioniert?

Ein Bootloader ist dieses Programm - es ist das erste, was ausgeführt wird und kann andere Anwendungen an bestimmten Stellen im Speicher laden (entweder dauerhaft wie FLASH oder flüchtig wie RAM) und dann zu dem gewünschten Programm springen, wo es dann die Ausführung von dort übernimmt .

Wie erstelle ich einen AVR-Bootloader (oder für einen beliebigen Mikrocontroller)?

Ich habe noch nie einen Bootloader erstellt, aber ich denke, so würde ich vorgehen: Schreiben Sie ein Firmware-Programm so, wie Sie es normalerweise tun würden - stellen Sie jedoch sicher, dass es in einem Bereich abgelegt ist, in dem es immer als Erstes ausgeführt wird Das Gerät bootet. Nebenbei bemerkt, einige der Funktionen, die ich von diesem kleinen Programm erwarten würde: Die Möglichkeit, ein neues Programm an eine verfügbare Stelle im Speicher hochzuladen, ein zuvor hochgeladenes Programm zu löschen und das auszuführende Programm auszuwählen (wenn mehr als vorhanden ist) one) und haben eine Art Speicherdatenstruktur (erweiterbare Sprungtabelle?), um sich zu erinnern, wo sich die anderen Programme befinden, und zu ihnen zu springen. Die Interaktion kann über UART erfolgen, wobei ein sehr einfaches Terminalmenü angezeigt wird und die Möglichkeit besteht, Firmware über denselben Kanal hochzuladen.

Wie wird es auf den Mikrocontroller programmiert (wie jedes Hex-Programm, das auf dem Flash-ROM des AVR oder einer anderen Methode gebrannt wurde)?

Wenn es sich um einen vollständig leeren Chip ohne vorhandenen Bootloader handelt, der sich selbst aktualisieren kann, müssen Sie auf FLASH brennen, so wie Sie es beschrieben haben, und zwar unter Verwendung der dafür erforderlichen Technik (ICSP im Fall von AVR).

Dies ist keineswegs umfassend, was "Bootloader" sind. Abhängig davon, was Sie von einem System oder von dem System, für das sie entwickelt wurden, wollen, können Sie eines so entwerfen, dass es Inhalte an einen bestimmten Speicherort im RAM anstelle von FLASH hochlädt und die Ausführung an einem beliebigen Speicherort beginnt. Oder Sie möchten ein Betriebssystem, mit dem Sie auswählen können, welches Betriebssystem beim Booten Ihres PCs geladen werden soll (siehe beispielsweise grub ). Bootloader für 8-Bit-Mikrocontroller sind in der Regel sehr einfach.

Ein Hinweis zu Arduino: Dieser Bootloader verwaltet nur ein Programm AFAIK, er übernimmt auch die serielle Schnittstelle, um das Hochladen der Firmware und andere Dinge zu verwalten .

Jon L
quelle
Zu Ihrer Information, die Antwort wurde geschrieben, um die ursprünglichen Aufzählungspunkte zu adressieren, die jetzt entfernt wurden.
Jon L
3

Das Konzept eines "Boot" -Laders ähnelt dem Konzept des "Ansaugens" einer Pumpe. Mit anderen Worten, Sie benötigen "etwas", das ein Programm an eine bestimmte Adresse lädt und dann das Programm an dieser bestimmten Adresse ausführt. Das ist der Bootloader. Im einfachsten Fall "erscheint" der Bootloader an der von der CPU festgelegten Startadresse (höchstwahrscheinlich Null), lädt das Programm in das erforderliche Speichersegment, überträgt die Steuerung darauf und "verschwindet". Das Erscheinen und Verschwinden wird durch "externe" Hardware gesteuert. Eine mögliche Implementierung wäre die Verwendung eines ROM, der über ein "Hardware" -Reset aktiviert und mit einem "Software" -Reset deaktiviert wird. Der Lader im ROM kann so einfach oder so komplex sein, wie es erforderlich ist. und muss in der binären Form geschrieben werden, die die jeweilige CPU versteht. Wenn der vom ROM verwendete Adressraum nicht benötigt wird, ist keine Deaktivierung des ROM erforderlich. Offensichtlich könnten EEPROM, ePROM, Flash-PROM usw. anstelle des ROM verwendet werden.

Guill
quelle