In diesem Artikel möchte ich das Thema Bootloader vorstellen. Während wir zunächst damit beginnen uns die Theorie anzueignen und verstehen möchten was überhaupt ein Bootloader ist, geht es im Zweiten Teil dieses Artikels dann auch schon ans Eingemachte: Wir werden einen Bootloader auf einen PIC-Mikrocontroller übertragen und diesen dann verwenden.

Was ist ein Bootloader?

Ein Bootloader beschreibt ein (in der Regel) kleines Programm, das sich neben der eigentlichen Benutzeranwendung auf dem Controller befindet. Als Benutzerprogramm wird das Programm bezeichnet, das ursprünglich für den Mikrocontroller entwickelt wurde.  Der Bootloader (das kleine Programm was nun also neben dem Benutzerprogramm im Mikrocontroller vorhanden ist) kommt nur relativ selten zum Vorschein. Im normalen Betrieb ist dieses Programm gewissermaßen “unsichtbar”. Es gibt eine Reihe von Mikrocontrollern die in der Lage sind, in ihren eigenen Flash-Programmspeicher zu schreiben. Im Flash-Programmspeicher befindet das Programm, das der Controller abarbeiten soll. Ein Controller, der seinen eigenen Flash beschreiben kann, kann sich also selber flashen. Natürlich geht das nicht von Zauberhand. Der Bootloader kommt hierzu zum Einsatz. Der Bootloader empfängt auf einen noch zu klärenden Weg Datensätze die zusammengesetzt das Benutzerprogramm ergeben. Diese Datensätze schreibt er an die jeweils richtigen Adressen in sein eigenes Flash. Nachdem er alle Datensätze empfangen und ins Flash geschrieben hat, hat er sich selbst programmiert.

Der Vorteil an dieser Methode ist, dass man nun ohne konventionelles Programmiergerät (z.B.: PICKit oder ICD) in der Lage ist eine neue Firmware/Programm auf den PIC zu übertragen. Jetzt kann man sich natürlich die Frage stellen wie denn dann der Bootloader auf den PIC kommt? Hierfür ist weiterhin einmalig ein Programmiergerät notwendig, das initial den  Bootloader auf dem PIC lädt. Wenn der Bootloader dann auf dem PIC vorhanden ist, ist das Programmiergerät nicht mehr zwingend erforderlich. Denkbar wäre zum Beispiel die Auslieferung eines Produktes mit bereits geladenem Bootloader und ggf. einer ersten Version eines Benutzerprogramm auf dem PIC. Wenn es dann im Laufe der Zeit zu Firmware-Updates kommt, können Kunden dieses ganz einfach vom PC aus auf den Controller übertragen ohne hierzu ein Programmiergerät besitzen zu müssen.

Wo befindet sich der Bootloader?

Wir haben bereits gelernt, dass sich der Bootloader oder das Bootloader-Programm parallel zum eigentlichen Benutzerprogramm auf dem Flash-Speicher befinden muss. Gleichzeitig soll das eigentliche Benutzerprogramm nicht vom Bootloader bei seiner Arbeit gestört werden. Grundsätzlich werden zwei Ansätze verfolgt, die in der Lage sind dieses gewünschte Verhalten zu realisieren. Die Ansätze unterscheiden sich in der Position des Bootloaders im Speicher.

  1. Bootloader am Anfang des Flash-Speichers
  2. Bootloader am Ende des Flash-Speichers

Der Nachteil der ersten Variante ist gleichzeitig der Grund weshalb ich die zweite Methode präferiere: Wenn man den Bootloader an den Start des Flash-Speichers platziert, muss dies im Benutzerprogramm berücksichtigt werden! Normalerweise würde am Anfang des Speichers das Benutzerprogramm beginnen. Dieses muss nun jedoch auf den Bereich des Flash-Speichers hinter den Bootloader verlagert werden. Auch liegen die Interrupt-Adressen im Anfangsbereich des Speichers. Folglich müssen auch diese verzweigt werden. Das führt wiederum dazu, dass sich die Länge der Ausführung eines Interrupts um zwei Befehlszyklen verlängert (aufgrund der notwendigen Sprungbefehle).

Die nachfolgende Grafik zeigt die Speicherbelegung, wie sie hingegen beim 2. Ansatz erfolgt.

Legt man den Bootloader stattdessen an das Ende des Flash-Speichers, so sind keine Änderungen am Benutzerprogramm notwendig. Die Adresse des Reset-Vektors wird lediglich auf den Start des Bootloaders “verbogen” und leitet somit den Start dessen beim Reset ein. Dies wird mit einem einfachen GOTO an Adresse 0x0000 erledigt. Und das Beste: Der GOTO Befehl muss nicht selber programmiert werden! Das PC-Tool des Bootloaders macht dies automatisch. Wenn der Bootloader nichts zu tun hat oder fertig ist, springt der Controller einfach zum Start des Flash-Speichers wo sich das Benutzerprogramm befindet und startet dieses. Die Interrupt-Vektoren bleiben wo sie sind und benötigen keine Verzweigung (keine Laufzeitverlängerung).

Bootloader für PIC16 und PIC18

Nun möchte ich damit beginnen einen Bootloader für PIC16 und PIC18 Mikrocontroller vorzustellen. Ich habe den Bootloader nicht selber entwickelt, sondern es handelt sich um einen von Microchip entwickelten Bootloader samt Anwendungssoftware für den PC. Es gibt im Internet Unmengen an verfügbaren Bootloadern, die sich in der Regel in zwei wesentlichen Aspekten unterscheiden:

  • Speicherbedarf des Bootloaders selber
  • Kompatibilität für jeweilige PIC-Typen

Es gibt bereits Bootloader die mit erstaunlich wenig Speicher auskommen. Mir geht es jedoch mehr um die einfache Anwendung und eine möglichst lange Liste an kompatiblen PIC-Typen. Was nützt mir ein winziger Bootloader, den ich jedoch nur für eine Handvoll PICs einsetzten kann?

Der Bootloader um den es in diesem Artikel geht wird unter anderem in der Application Note AN1310 beschrieben (EN). Damit das Einarbeiten etwas einfacher fällt, beschreibe ich die wesentlichen Schritte in diesem Artikel noch einmal ergänzend in deutsch. Das PC-Programm (grafische Bedienung) wird zum letztendlichen Übertragen der Firmware zum Bootloader/auf den PIC verwendet. Ich biete die beiden Downloads hier lokal von meinem Server aus an, da bei Microchip auch schon mal in die Jahre gekommene Projekte ausgegliedert werden und dann unter Umständen nicht mehr verfügbar sind. Die Gefahr besteht bei diesem Bootloader wohl vorerst nicht aber man weiß ja nie.

Der Bootloader von Microchip hat folgende Eigenschaften (wer sich noch detaillierter in die Eigenschaften einlesen möchte, kann das gerne mit Hilfe der oben verlinkten Application Note tun):

  • Speicherbedarf von weniger als 450 Befehlen
  • automatische Baudraten-Synchronisierung (bis zu 3 Mbps)
  • CRC Prüfung mit 16 Bit
  • automatische BL-Einleitung durch MCLR-Kontrolle
  • fertige (grafische) PC-Anwendung

Download

* Ich habe festgestellt, dass man Probleme beim Importieren des alten MPLAB-Projektes in die neue MPLABX IDE bekommt. Und zwar kann man zwar problemlos das Projekt importieren und auch im Anschluss kompilieren, doch die Konfiguration, die man in den Code einpflegt (MPLABX unterstützt nur noch das Setzen des Konfigurationswortes direkt im Code)  sind nicht wirksam. Das äußert sich dadurch, dass Ihr zwar problemlos eine Verbindung zum Bootloader bekommt, dieser das gewünschte HEX-File auch ohne weiteres in den Controller lädt, das Programm auf dem PIC dann aber nicht ordnungsgemäß bzw. gar nicht funktioniert! Das scheint daran zu liegen, dass in dem originalen MPLAB (8) Projekt des PIC-Bootloaders das Konfigurationswort direkt durch die IDE eingestellt wird. Ich habe daher einmal das MPLAB 8 Projekt geöffnet und die Einstellung entfernt, so dass das Konfig.-Wort wieder über den Code eingestellt werden kann. Ich empfehle Euch daher dringend dieses Projekt zu verwenden, wenn Ihr mit MPLABX arbeitet und das Projekt für euren jeweiligen Controller importiert. Bei Fragen könnt Ihr euch jederzeit über die Kommentarfunktion melden.

Hardware

Dann schauen wir uns doch als nächstes einmal an, wie die Hardware beschaffen sein muss, damit der Bootloader zum Einsatz kommen kann. Da die beliebte RS232-Schnittstelle in der ursprünglichen Form an modernen Rechnern nicht mehr anzutreffen ist muss man eine Alternative suchen. Die aktuelle und zukünftige Schnittstelle ist natürlich USB. Somit ist klar, dass auch wir über USB unsere Schaltungen mit neuer Firmware versorgen möchten. Da die USB-Spezifikation jedoch ein ganz schön dicker Brocken ist, möchten wir einen eleganten Umweg gehen. Die Firma FTDI hat diesen Umstand auch erkannt und hat entspreche Chips entwickelt, die aus einem gewöhnlichen USB-Port eine serielle Schnittstelle zaubern. Der PC sieht USB, die Controller die serielle Schnittstelle. Damit wir auch im PC die serielle Schnittstelle “sehen”, wird mit den Treibern, die zum FTDI-Chip (dem FT232RL) gehören, eine virtuelle serielle Schnittstelle emuliert. Also nochmal kurz zusammen gefasst:


PC ↔ (virtueller) COM-Port ↔ FTDI-Treiber ↔ USB ↔ FT232RL ↔ RX/TX ↔ MCU


Wir haben ja bereits gelernt, dass der Bootloader immer zum Reset des PIC aktiv ist und auf eine neue Firmware wartet, die er über die RX/TX-Leitungen des FT232RL-Chips bekommt. Wenn jedoch keine Aktivität zu erkennen ist, sprich keine neue Firmware aufgespielt werden soll, wird automatisch das Benutzerprogramm gestartet. Es gibt auch Ansätze, die das Setzen eines Jumpers oder Drücken eines Tasters zum Reset erfordern, damit der Bootloader gestartet wird. In meinen Augen ist das jedoch eher umständlich. Wenn man sich vorstellt, dass man eventuell an die Hardware gar nicht mehr dran kommt, dann sind diese Methoden sogar gänzlich ungeeignet.

Wir halten also fest, dass das automatisierte Starten des Bootloaders in Kombination mit dem Warten auf Aktivität auf der Schnittstelle bereits eine sehr elegante Variante darstellt. Nun drängt sich natürlich die Frage auf, wie man vom PC aus einen Reset am Controller auslösten kann damit man eine neue Firmware übertragen kann. Denn nur zum Reset ist der Bootloader aktiv, sprich nur zum Reset kann neue Firmware übertragen werden. Hierzu kann man einen kleinen Trick anwenden: Die serielle Schnittstelle verfügt über ein sogenanntes Hardware-Handshake. Dies wurde in früheren Zeiten verwendet um die Kommunikation zu steuern und eventuelle Überläufe zu verhindern. Heutzutage kommt dieses Verfahren jedoch kaum noch zum Einsatz. Das schöne daran ist jedoch, dass wir uns diese Ressource zu Nutze machen können um beim Controller den zwingend notwendigen Reset auszulösen.

Die RTS Leitung (request to send) wird zu Beginn einer Übertragung (PC  MCU) von Low auf High gezogen. Damit fragt der PC bei der MCU (normalerweise) nach ob diese bereit zum Empfangen von Daten ist. Die MCU würde dies mit einem Wechsel des Pegels von Low auf High des CTS-Signals (clear to send) quittieren. Diese Signale sind auch (negiert) beim FT232RL vorhanden. Wir können also RTS mit MCLR des PIC verbinden um einen Reset auszulösen und den Bootloader zu starten. Dann starten wir mit der Übertragung der neuen Firmware, die dann entsprechend vom Bootloader entgegen genommen wird.



Der gezeigte Schaltplan (Ausschnitt) zeigt die notwendige Verschaltung von RX, TX und dem RTS-Signal, das zum Auslösen des Resets am Mikrocontroller benötigt wird. Die Widerstände R1, R2 und R4 dienen lediglich zum Schutz der Ausgangstreiber im Fehlerfall und könnten rein theoretisch auch weg gelassen werden. Wichtig: Wenn euer PIC mit 3,3V betrieben wird, dann müsst ihr den FT232RL so beschalten, dass dieser auch nur 3,3V Pegel an seinen Ausgängen führt, siehe hierzu das Datenblatt des Chips oder meinen separaten Artikel zu diesem Chip.

Außerdem sollte beachtet werden, dass Ihr evtl. einen Jumper einbaut, der den FT232RL vom MCLR des PIC trennen kann. Das kann hilfreich sein, wenn man den PIC auf dem konventionellen Weg mit PICKit3 oder ähnlichem programmieren möchte. Die hohe Programmierspannung könnte andernfalls einen negativen Einfluss auf den FT232RL haben.

Software (PIC)

Ich habe es bereits erwähnt: Damit der Bootloader seine Arbeit verrichten kann, muss er natürlich erstmal in den PIC geladen werden und dazu benötigt man einmalig ein Programmiergerät (zum Beispiel der Hersteller eines jeweiligen Boards). Wenn ihr das Archiv (Download-Link oben) heruntergeladen und die Installation ausgeführt habt, dann wurde das Bootloader-Programm in das folgende Verzeichnis geladen:

C:\Microchip Solutions\Serial Bootloader AN1310 v1.05\PIC18 Bootloader

Das Programm muss nun entsprechend für euren PIC kompiliert und geflasht werden. Hierzu müsst ihr mit MPLABX ein neues Projekt erstellen und im Project Wizzard das Konvertieren eines alten MPLAB 8 Projektes auswählen, da der Bootloader noch mit MPLAB 8 programmiert wurde. Da es sich um ein Assembler-Projekt handelt wird dieser entsprechend zum Kompilieren ausgewählt. Im nächsten Schritt muss das Konfigurationswort eingestellt werden. Die nachfolgende Liste hilft bei den Einstellungen:

  • Watchdog-Timer: Disabled*
  • Extended-Instruction-Set: Disabled
  • Oscillator-Setting: Entsprechend der Hardware wählen
  • Fail-Safe-Clock-Monitor: Enabled (wenn vorhanden)
  • Low-Voltage-Programming: Disabled
  • Table-Read-Protect: Disable (wenn vorhanden)

* Kann bei den meisten PIC-Typen später im Code wieder aktiviert werden.

Bei mir am PIC18F45K22 sehen die eingepflegten Zeilen für das Konfigurationswort wie folgt aus (eingefügt im oberen Bereich der PIC18 Bootlader.asm Datei).

CONFIG FOSC = INTIO67 ; Internal oscillator block
CONFIG PLLCFG = OFF ; Oscillator used directly
CONFIG WDTEN = OFF ; Watch dog timer off
CONFIG XINST = OFF ; Extended Instruction Set off
CONFIG FCMEN = ON ; Fail-Safe Clock Monitor on
CONFIG LVP = OFF ; Single-Supply ICSP disabled
CONFIG EBTR0 = OFF ; Table Read Protection off
CONFIG EBTR1 = OFF ; ...
CONFIG EBTR2 = OFF ; ...
CONFIG EBTR3 = OFF ; ...

Wenn das Konfigurationswort richtig eingefplegt wurde, kann im Anschluss der Bootloader kompiliert und mit einem geeigneten Programmiergerät (PICKit3 oder ähnlich) in den Mikrocontroller übertragen werden.

Programm (PC)

Das Anwendungsprogramm für den PC ist relativ einfach gehalten und somit sehr übersichtlich. Der nachfolgende Screenshot zeigt das Tool, wie es beim Öffnen der EXE-Datei aussieht.

Wenn das Programm das erste mal gestartet wurde, müssen noch ein paar Einstellungen bezüglich der seriellen Schnittstelle getroffen werden. Hierzu navigiert ihr einfach in folgendes Menü: Program  Settings … und stellt hier entsprechend eurem Aufbau die Schnittstelle ein. Auf dem Screenshot des Menüs (siehe unten) ist kein COM Port ausgewählt, da zum Zeitpunkt als ich diese Anleitung geschrieben habe, kein entsprechender PIC mit FT232-Chip am PC angeschlossen war.

Wenn ihr euren PIC mit der besprochenen Hardware an den PC anschließt, sollte ein entsprechender COM-Port in der Drop-Down-Liste zur Auswahl stehen. Eine nicht all zu hohe Baudrate hilft initial eine stabile Verbindung herzustellen. Ein Wert von 19,2kbps (siehe Screenshot) ist zu Beginn eine gute Wahl. Der Bootloader im PIC erkennt automatisch die vom PC-Tool eingesetzte Baudrate. Um nun das Benutzerprogramm in den PIC zu laden, müsst ihr dieses zunächst öffnen (die HEX-Datei befindet sich i.d.R. im Unterordner /dist eures MPLABX Projektes). Im Anschluss wird die Hex-Datei im Anzeigefenster des Programms angezeigt. Jetzt muss der Bootloader im PIC aktiviert werden (Restart auslösen). Hierzu wird der rote Stopp-Button (Bootloader-Mode) gedrückt. Wenn das funktioniert hat, erscheint die Bootloader-Version und die PIC-Typen-Information in der Statusleiste. Jetzt kann der PIC ausgelesen, gelöscht, verifiziert oder beschrieben werden. Hierzu dienen die zusätzlichen vier Buttons in der Werkzeugleiste (siehe rechts neben dem Bootloader-Mode-Button).

Bei den Write Options sollte man besonders vorsichtig sein was die Einstellung der Config Bits betrifft. Bereits beim Übertragen des Bootloaders sollten durch das entsprechende Programmiergerät die Konfigurationsbits eingestellt werden, wie man es voraussichtlich für die jeweilige Anwendung benötigt. Man kann natürlich weiterhin in dem eigentlichen Benutzerprogramm die Konfigurationsbits mit den entsprechenden #pragma Anweisungen festlegen, doch sie werden keine Auswirkung haben, da der Bootloader die Bits nicht mehr ändert. Wenn man jedoch einen Haken in den Write Options unter Config Bits setzt, dann werden die Konfigurationen sehr wohl eine Auswirkung auf die Konfiguration des PIC haben. Diese Tatsache ist einerseits sehr nützlich, kann jedoch auch dazu führen, dass man sich aus dem System aussperrt, wenn man die Konfiguration so verändert, dass der Bootloader nicht mehr arbeiten kann. Generell gilt also den Haken bei Config Bits immer weglassen, es sei denn ihr wisst genau was ihr da tut 🙂


Übrigens: Wenn Ihr in MPLABX an eurem Projekt arbeitet und dieses neu compiliert wird das von dem PC-Tool des Bootloaders erkannt, so dass dieser automatisch den Controller in den Bootloader-Modus versetzt und die neue Firmware auf den PIC aufspielt. Im Anschluss wird dann der PIC wieder in den Modus “Run” versetzt. Auf diese Weise merkt Ihr quasi keinen Unterschied mehr zwischen einem echten Programmiergerät und dem Bootloader für PIC16 und PIC18  Damit dieses automatische Flashen der neuen Hex-Datei funktioniert muss diese nur einmalig mit dem Bootloader-Tool geöffnet werden.


Neue PIC-Typen

Wenn es einmal vorkommen sollte, dass euer PIC-Typ nicht vom Bootloader unterstützt wird, so gibt es die Möglichkeit die vorhandene Datenbank des Bootloaders um einen Eintrag für diesen PIC zu erweitern. Nach der Installation des Bootloader-Paketes wurde zusätzlich die kleine Anwendung “Device Database” installiert. Diese kann zum Laden einer fertigen XML-Datei verwendet werden, die die entsprechenden Parameter für euren PIC enthält. Diese können dann in die SQL-Datenbank des Bootloaders geladen werden. Zusätzlich muss die DEVICES.inc Datei des Bootloaders (später befindlich im PIC selber) entsprechend erweitert werden. Eine vollständige Liste mit den (sofort) unterstützten PIC-Typen findet Ihr in der Devices.inc Datei.

Die einfachste Methode einen neuen PIC-Typen für den Bootloader kompatibel zu machen ist es, dessen *.PIC Datei mit der Anwendung Device Database zu öffnen (sie unten Download aller *.PIC Dateien als Zip-Archiv). Das Tool extrahiert die notwendigen Informationen und bereitet sie entsprechend für ein direktes Drag & Drop in die Datenbank vor. Wenn ihr die *.PIC Datei eures PIC-Typen mit dem Tool geöffnet habt, dann sieht das Fenster wie folgt aus:

Den gesamten Code aus dem Reiter devices.sql müsst ihr nun kopieren und entsprechend in die Datei devices.sql hineinkopieren. Der alte Inhalt in dieser Datei wird zuvor gelöscht, so dass nur noch der kopierte Inhalt in der Datei steht. Speichern, schließen. Die Datenbank-Datei devices.sql findet ihr unter folgendem Pfad:

C:\Microchip Solutions\Serial Bootloader AN1310 v1.05\Device Database\devices.sql

Im Anschluss müsst Ihr die Datenbank neu erstellen. Dafür öffnet ihr die Eingabeaufforderung von Windows und navigiert in den Pfad in dem auch die devices.sql liegt. Ein kleiner Trick, der eim das ganze Navigieren durch die Ordnerstrukturen erspart: Geht einfach im Dateiexplorer wieder eine Ebene nach oben und führt einen Rechtsklick bei gedrückter Shift-Taste auf den Ordner aus, in dem ihr die Eingabeaufforderung öffnen möchtet.

Es öffnet sich ein Kontextmenü das euch unter anderem die Möglichkeit bietet die Eingabeaufforderung direkt im angewählten Verzeichnis zu öffnen 🙂 In die offene Eingabeaufforderung geht ihr nun folgenden Befehl ein um die Datenbank zu aktualisieren:

sqlite3.exe -init devices.sql -batch ..\devices.db .quit

Wenn alles geklappt hat, sollte eure Eingabeaufforderung nun so aussehen wie bei mir (siehe Screenshot) nun wurde die Datenbank des PC-Programms neu erzeugt und beinhaltet nun den neu von euch angelegten PIC-Typen.

Als letzten Schritt müssen wir nun noch die DEVICES.inc Datei des Bootloaders selber erweitern. Hierzu öffnet ihr die Datei innerhalb MPLAB Umgebung. Falls ihr es noch nicht getan habt, solltet ihr ein neues MPLAB X Projekt erzeugen und das Konvertieren eines alten MPLAB IDE 8 Projektes auswählen, da der Bootloader mit dem C18-Compiler unter MPLAB IDE 8 erzeugt wurde (siehe auch Kapitel Software (PIC) ). Das Projekt, dass ihr nun konvertieren sollt findet ihr in folgendem Verzeichnis:

C:\Microchip Solutions\Serial Bootloader AN1310 v1.05\PIC18 Bootloader

Wenn ihr den Project Wizzard abgeschlossen habt, seht ihr links im Reiter Projects den Ordner Header-Files. In diesem Ordner ist die DEVICES.inc Datei enthalten, die ihr nun öffnet. Ganz zu Beginn haben wir damit angefangen die *.PIC Datei mit dem Programm Device Database zu öffnen. Das Programm hat uns darauf hin einen gewissen “Code” ausgegeben. Nun brauchen wir den Inhalt des Reiters devices.inc, den wir nun in die Datei, die wir in MPLAB geöffnet haben, hinein kopieren. Hierbei solltet ihr auch nochmal darauf achten, dass die DEVICEID mit der ID übereinstimmt, die wir zu Beginn in die devices.sql Datei kopiert haben 😉 Wenn auch dieser Schritt erledigt ist, kann das MPLAB X Projekt (der Bootlader) kompiliert werden.

Download der *.PIC Dateien

Normalerweise sind die *.PIC Dateien bei der Installation von MPLAB IDE bereits enthalten, jedoch konnte ich die Dateien im Installationsordner von MPLABX nicht finden. Für alle, die also nur noch mit MPLAB X arbeiten und somit nicht an die entsprechenden *.PIC Dateien heran kommen, stehen diese hier als Archiv für jeweils PIC16 und PIC18 zum Download bereit.

Siehe auch

  • FTDI FT232RL – USB zu Seriell-Wandler
  • RxTx – Virtuelle COM-Schnittstelle für Java

Leave a Comment