AVR Bootloader FastBoot von Peter Dannegger
von Karsten Donat und Lars Möller
Was ist ein Bootloader?
Der Bootloader ist selbst ein kleines Programm. Es wird beim Start des Controllers zuerst ausgeführt. Damit sich das PC-Programm für das Firmware-Update melden kann, wartet der Bootloader eine gewisse Zeit (hier 0,33 Sekunden) auf ein Zeichen über die serielle Schnittstelle (UART RS232, USB). Kommt dies Zeichen, wird die neue Firmware gebrannt. Andernfalls wird das eigentliche Programm des Controllers ausgeführt.
Dem eigentlichen Anwendungsprogramm geht natürlich der Platz verloren, den der Bootloader benötigt. Da Peters Bootloader jedoch in ein 512Bytes (256 Worte!) großes Segment passt, stört das nicht weiter.
Normalerweise wird der Programmcode des Mikrocontrollers mit einem ISP-Dongle in den Flash gebrannt. Aus verschiedenen Gründen kann dies jedoch nicht möglich/ gewünscht sein:
- Geschwindigkeit: Der ISP-Dongle kann langsam sein (z. B. myAVR mit aktuellem AVRDude)
- PINs: Man braucht die PINs und will ISP abschalten (Fuses, aber Vorsicht!, danach kann man nur mit dem Bootloader oder einem AVR HV-Programmer noch an den Flash-Speicher)
- Komfort: Man möchte dem Kunden/Nutzer die Möglichkeit geben, eine neue Firmware selbst einzuspielen. In der Regel hat dieser jedoch keinen ISP-Dongle zur Hand. Eine RS232- oder USB-Schnittstelle ist aber oftmals vorhanden.
- Sicherheit: Man möchte dem Kunden nicht die Firmware in deassemblierbarer Form geben (über geänderten Bootloader kann die Datei verschlüsselt sein).
Features
- Automatische Erkennung der vom PC verwendeten Baudrate
- Ein- oder zwei-Draht Betrieb (One-Wire/Two-Wire)
- Support für viele verschiedene AVRs wie: tiny13, tiny2313, tiny25, tiny261, tiny44, tiny45, tiny461, tiny84, tiny85, tiny861, mega48, mega8, mega8515, mega8525, mega88, mega16, mega162, mega168, mega328, mega32, mega64, mega644, mega128, mega1281, mega2561.
- Passwortschutz gegen unberechtigtes Umprogrammieren (aber keine Verschlüsselung des Programms).
- Freie Software - unter GPL lizenziert (Link). Das eigentliche Anwendungsprogramm, das über den Bootloader geladen wird muß deswegen *nicht* unter der GPL stehen und dessen Quelltext auch *nicht* veröffentlicht werden (Link).
Anforderungen an das zu ladende Programm
Bei AVRs ohne "boot reset vector fuse" (BOOTRST) wie beispielsweise ATtinys und kleinen ATmegas (ATmega48) muß der erste Befehl ein RJMP sein. Für C-Programme ist das automatisch sichergestellt (und für Assembler-Programme leicht selbst sicherzustellen).
Downloads
Thread zum Bootloader: UART Bootloader ATtiny13 - ATmega644
- Version 2.1 (Forumsbeiträge):
- Ursprüngliche Version von Peter Dannegger, inkl. DOS Host-Software
- Angepasste Version für AVR-GCC-Toolchain
- Protokollbeschreibung Host <-> Target Kommunikation
- Schaltbild für One-Wire-Betrieb (RS232)
- Schaltbild für One-Wire-Betrieb (TTL-Pegel, z. B. FTDI)
- Host-Software für Version 2.1
- Linux-Host (mit One-Wire-Unterstützung), Sourcecode im GitHub
- Linux- und Mac-Host (ohne One-Wire-Unterstützung), nur mit Anmeldung
- Dev-C++ Portierung (Win64)
- Windows-Host mit GUI von leo-andres.de, alte Version
- Host-Software für Version 1.7
- Python-Script von kreatives-chaos.com
- Dev-C++ Portierung (Win32)
- Sonstiges
- Atmel AVR-Studio (um Bootloader zu assemblieren): http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725
- Ältere Version dieser Anleitung als PDF: http://www.KarstenDonat.de/AVR/Bootloader.pdf
Bootloader anpassen (Angepasste Version für AVR-GCC-Toolchain)
Die "ursprüngliche Version von Peter Dannegger" wird mit dem Assembler aus AVRStudio assembliert und die Einstellungen werden in verschiedenen Dateien des Bootloaders vorgenommen.
In der "angepassten Version für AVR-GCC-Toolchain" werden die Einstellungen in dem Makefile vorgenommen und es wird der avr-gcc-Compiler genutzt. Weitere Details stehen in der beiliegenden README-Datei.
CPU und Frequenz auswählen – Makefile
Die CPU (der Atmel auf dem der Bootloader laufen soll) wird hier ausgewählt. Im Beispiel für einen Atmega328p.
MCU = atmega328p
ATMEL_INC = m328Pdef.inc
Die passende .inc-Datei befindet sich nach der AVRStudio-Installation unter Windows im Verzeichnis "C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1117\avrassembler\include" und muss ins Hauptverzeichnis des Bootloaders kopiert werden (dort wo die Makefile liegt). Man findet die Dateien wohl auch einzeln im Netz, es ist aber zu beachten, dass es mit älteren Versionen Probleme gibt. Die Dateien von AVRStudio 6.2 funktionieren.
Hier wird die Frequenz festgelegt. 16 MHz entsprechen einem Standard-Arduino mit 5V.
F_CPU = 16000000
UART Port und Pins festlegen – Makefile
Da die verwendeten Pins für die Schnittstelle frei wählbar sind, müssen diese noch eingestellt werden.
STX_PORT: Hier den Sendeport angeben. Für die Pins des Hardware-UARTs des M8 wäre das Port D. Es müssen zwar nicht dieselben Pins sein, wenn man sie aber ohnehin als Schnittstelle nutzt, ist es sinnvoll, sie auszuwählen. Verwendet wird immer ein im Bootloader integrierter Software-UART, der auf beliebigen I/O-Pins lauschen kann.
STX_PORT = PORTD
STX = PD1
SRX_PORT = PORTD
SRX = PD0
Beispiel für gleiche Bepinnung wie Hardware-UART im ATMega 8, 48, 168, 328
Für One-Wire-Betrieb muß für TX und RX zweimal der gleiche Pin angeben werden. Beim Assemblieren wird das erkannt und One-Wire aktiviert - es ist keine weitere Änderung nötig. Hier die Beschaltung für RS232 und für TTL UART.
Wartezeit festlegen - FASTLOAD.H
Die Frequenz muss ausschließlich im Makefile eingestellt werden. die Einstellung bei XTAL in FASTLOAD.H wird ignoriert.
Um die Wartezeit auf das Firmware-Update beim Booten anzupassen:
.equ BootDelay = XTAL / 3 ; 0.33s
Bootloader anpassen (Ursprüngliche Version von Peter Dannegger)
CPU auswählen – BOOTLOAD.ASM
Die CPU (der Atmel auf dem der Bootloader laufen soll) wird durch Einkommentieren der zugehörigen Include-Files ausgewählt. Im Beispiel für einen ATtiny45.
; select the appropriate include file:
;.include "tn13def.inc"
;.include "tn2313def.inc"
;.include "tn25def.inc"
;.include "tn261def.inc"
;.include "tn44def.inc"
.include "tn45def.inc"
;.include "tn461def.inc"
;.include "m48def.inc"
;.include "tn84def.inc"
;.include "tn85def.inc"
;.include "tn861def.inc"
Dabei nicht vergessen, die bisher (per Default) ausgewählte CPU ATmega168 auszukommentieren:
;.include "m168def.inc"
UART Port und Pins festlegen – BOOTLOAD.ASM
Da die verwendeten Pins für die Schnittstelle frei wählbar sind, müssen diese noch eingestellt werden.
STX_PORT: Hier den Sendeport angeben. Für die Pins des Hardware-UARTs des M8 wäre das Port D. Es müssen zwar nicht dieselben Pins sein, wenn man sie aber ohnehin als Schnittstelle nutzt, ist es sinnvoll, sie auszuwählen. Verwendet wird immer ein im Bootloader integrierter Software-UART, der auf beliebigen I/O-Pins lauschen kann.
.equ STX_PORT = PORTD
.equ STX = PD1
.equ SRX_PORT = PORTD
.equ SRX = PD0
Beispiel für gleiche Bepinnung wie Hardware-UART im ATMega 8, 48, 168, 328
Für One-Wire-Betrieb muß für TX und RX zweimal der gleiche Pin angeben werden. Beim Assemblieren wird das erkannt und One-Wire aktiviert - es ist keine weitere Änderung nötig.
CPU-Frequenz und Wartezeit festlegen - FASTLOAD.H
Bei XTAL die benutzte Frequenz des Controllers einstellen (jungfräuliche AVRs haben oft intern 1MHz aktiviert!). Im Standard Makefile von WinAVR steht die Frequenz unter F_CPU
.equ XTAL = 8000000 ; 8MHz, not critical
Um die Wartezeit auf das Firmware-Update beim Booten anzupassen:
.equ BootDelay = XTAL / 3 ; 0.33s
Assemblieren des Bootloaders (Angepasste Version für AVR-GCC-Toolchain)
Download der richtigen Versionen
In diesem Thread findet sich die neuste Version des Bootloaders. Hier eine Version mit einigen Beispiel-Makefiles. Diese Anleitung basiert auf fastboot_build29.tar.gz.
Der Bootloader beinhaltet das Script "get_avr_arch.sh" in einer Version, die mit aktuellen avr-gcc-Versionen nicht klar kommt. Das äußert sich in folgender Fehlermeldung:
get_avr_arch.sh: Could not find an architecture in avr-gcc's internal ld command line arch=
Die neuste Version des Scriptes herunterladen und die vorhandene im Haputverzeichnis des Bootloaders ersetzen. Diese Version funktioniert z. B. mit avr-gcc 4.8.2.
Voraussetzungen unter Windows:
- Die AVR Tools müssen installiert werden.
- AVRStudio muss nicht installiert werden.
- cygwin muss in der x86 Version installiert werden, der Pfad "C:\cygwin\bin" in die Path-Systemvariable eingetragen werden und der PC neu gestartet werden.
Assemblieren
Mit folgenden Befehlen sollte der Bootloader unter Windows und Linux zu kompilieren sein:
make clean make
Ein erfolgreicher Build sollte so aussehen:
make Makefile:120: atmel_def.mak: No such file or directory ./_conv.awk m328Pdef.inc | gawk '/PAGESIZE|SIGNATURE_|SRAM_|FLASHEND|BOOT/' > atmel_def.h gawk '{ printf "%s = %s\n", $2, $3 }' atmel_def.h > atmel_def.mak avr-gcc -c -Wa,-adhlns=bootload.lst -mmcu=atmega328p -DF_CPU=16000000 -I . -I ./added -I ./converte d -I/usr/local/avr/include -ffreestanding -gstabs+ -L,-gstabs+ -DRAM_START=0x0100 -DSRAM_SIZE=2048 -DSTX_PORT=PORTD -DSTX=PD1 -DSRX_PORT=PORTD -DSRX=PD1 added/bootload.S -o bootload.o avr-gcc -c -Wa,-adhlns=stub.lst -mmcu=atmega328p -DF_CPU=16000000 -I . -I ./added -I ./converted -I /usr/local/avr/include -ffreestanding -gstabs+ -L,-gstabs+ -DRAM_START=0x0100 -DSRAM_SIZE=2048 -DST X_PORT=PORTD -DSTX=PD1 -DSRX_PORT=PORTD -DSRX=PD1 added/stub.S -o stub.o vars="$(./get_bootsection_addrs.sh 0x3fff 0x3f00 0x3e00 0x3c00 )"; \ arch="$(./get_avr_arch.sh -mmcu=atmega328p bootload.o)"; \ echo "arch=$arch";\ echo "$vars"; \ eval "$vars"; \ sed -e "s/@LOADER_START@/$LOADER_START/g" \ -e s"/@ARCH@/$arch/" \ -e s'/@RAM_START@/0x0100/g' \ -e s'/@RAM_SIZE@/2048/g' \ -e "s/@STUB_OFFSET@/$STUB_OFFSET/g" \ bootload.template.x > bootload.x; \ avr-ld -N -E -T bootload.x -Map=bootload.map \ --cref bootload.o stub.o -o bootload.elf --defsym Application=0 *** Note: set BOOTSZ fuses to the word address 0x3f00 *** arch=avr5 LOADER_START=0x7e00 STUB_OFFSET=0x1fe avr-objcopy -O ihex bootload.elf bootload.hex
Assemblieren des Bootloaders (Ursprüngliche Version von Peter Dannegger)
Da der Bootloader in Assembler geschrieben ist, kann WinAVR nicht so ohne weiteres damit umgehen. Das einfachste ist, sich das AVRStudio von Atmel herunterzuladen http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725
Im Unterverzeichnis AvrAssembler2 befindet sich der benötigte Assembler. Das Einfachste ist, sich die unter "Appnotes" benötigte Include Datei des jeweiligen Controllers (oder das komplette Verzeichnis) und die avrasm2.exe ins Verzeichnis des Bootloaders zu kopieren.
Danach wird der Assembler aufgerufen (m8.asm für ATMega 8) und der Bootloader kompiliert:
avrasm2 -fI BOOTLOAD.ASM
Es ist wichtig, dass die Includes des avrasm2 und nicht die der alten Version verwendet werden, da es sonst beim Assemblieren zu dem Fehler "fastload.h(112): error: Use of undefined or forward referenced symbol 'SRAM_START' in .org" kommt.
Das AVRStudio lässt sich unter Linux auch mit WINE installieren (die IDE des AVR Studio 4 geht allerdings nur mit ein paar Tricks aus der AppDB - ist für das Assemblieren des Bootloaders aber nicht nötig). Wenn "avrasm2.exe" und die zum AVR passende Include-Datei (beispielsweise "tn45def.inc" für ATtiny45) im gleichen Verzeichnis wie die restlichen Dateien des Bootloaders liegen, kann der Bootloader mit folgendem Befehl assembliert werden:
wine avrasm2.exe -fI BOOTLOAD.ASM
Einstellen der Fuses
Damit der Bootloader zu Beginn gestartet wird, müssen die entsprechenden Fuses gesetzt werden. Möglich ist dies u.a. mit der AVRDude GUI.
- BOOTRST muss auf 0 gestellt werden (aktiviert den Bootloader)
- BOOTSZ muss auf 256 Worte (= 512 Byte) (oder dem minimal möglichen Wert, wenn AVR nur größere Bootloader Regionen unterstützt) gestellt werden. Beispielsweise ist für den ATMega8 der Wert 10.
Bei einigen Controllern wie z. B. dem ATMega 48 wird das Flag
- Selfprogramming enabled gesetzt.
Auf dieser Website (Fusecalc) kann man sich die Fuses elegant zusammenstellen und erhält gleich die Parameter für avrdude. Eine schnelle und *sichere* Alternative zum fehlerträchtigen "Kaputtflashen" von Atmels.
Die Fuses werden mit dem vorhanden ISP Dongle in den AVR gebrannt:
avrdude -p m328p -c usbasp -P usb -e -U lfuse:w:0xff:m -U hfuse:w:0xde:m -U efuse:w:0x05:m
Beispiel für einen Arduino Pro Mini 16 MHz Qwarz 5V mit Atmega328p
Brennen des Bootloaders
Der nun erzeugte Bootloader wird mit dem vorhanden ISP Dongle in den AVR gebrannt (Intel Hex Format):
avrdude -p m8 -c avr910 -P com1 -U flash:w:"C:\Test\m8 3686400.hex":i -U flash:v:"C:\Test\m8 3686400.hex":i -y
Brennen mit AVRDude auf COM 1 und einem AVR910 kompatiblen Dongle (z. B. myAVR USB)
avrdude -p m328p -c usbasp -P usb -U flash:w:"bootload.hex":i
Brennen mit AVRDude auf USB und einem usbasp Dongle
Brennen des eigentlichen Programmes
Damit das Programm in den Controller geladen werden kann, muss es im Intel HEX Format vorliegen. Im makefile Template von WinAVR (und auch der ATMegaIDE) ist dies standardmäßig eingestellt.
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
One-Wire
Im normalen Modus werden GND, VCC, RX, TX und optional DTR verbunden. Die Daten werden getrennt über RX und TX übertragen, über DTR wird der µC neu gestartet (reset):
Die große Stärke dieses Bootloaders ist aber der One-Wire Modus (das hat nichts mit dem OneWire-Protokoll von den Dallas Temperatursensoren zu tun). Hier werden GNC, VCC und eine Datenleitung verbunden:
Das RS232-COM Signal ist invers zum standard TTL Signal. Da der Bootloader aus einer Zeit stammt, wo man noch echte COM-Schnittstellen hatte, ist er darauf ausgelegt. Möchte man nun mit einem USB FTDI Adapter flashen, fällt der Schaltplan einfacher aus. Dafür müssen RX und TX mit der FT_Prog Software von FTDI invertiert werden (Haken angehakt). Möglicherweise ist das auch bei anderen USB-Seriell-Wandlern möglich.
Nach dem Start oder Reset wartet der Bootloader den Bruchteil einer Sekunde auf den Programmierbefehl. Empfängt er diesen nicht, wird das eigentliche Programm gestartet. Im normalen Modus wird der µC per DTR-Leitung resetiert und anschließend mit dem Programm gefüttert.
Im One-Wire Modus muss man diesen Reset per Hand durchführen. Dazu wird das Flash-Tool im One-Wire Modus gestartet. Es sendet nun in schneller Folge den Programmier-Befehl bis der µC antwortet. Nun muss der Reset-Pin des µC kurz betätigt, der µC einmal vom Strom getrennt oder überhaupt erst mit Strom versorgt werden. Der Flashvorgang beginnt.
Brennen UpdateLoader GUI (Windows, empfohlen)
Sehr kompfortabel ist das Brennen mit dem UpdateLoader. Das Programm ist weitgehend selbsterklärend. Eine Anleitung gibt es hier.
Das Standard-Passwort des Bootloaders "Peda" muss im Passwort-Feld stehen. Es kann aber im Quellcode geändert werden. In den erweiterten Einstellungen kann der One-Wire-Betrieb aktiviert werden. Die Baudrate kann frei eingestellt werden, der Bootloader passt sich automatisch an.
Brennen per FBoot (DOS, alt)
Danach wird Peters Firmware-Update Tool aufgerufen (hier COM2)
fboot /C2 /Pmain.hex
hier wird die main.hex als Hauptprogramm gebrannt
Wichtig hierbei ist, dass der Dateiname der alten DOS Konvention entspricht. Also keine langen Dateinamen.
Peters Firmware-Update Tool lässt sich unter Linux leider nicht mit WINE starten, dafür aber mit DOSBOX. Der Aufruf ist dann der gleiche wie unter Windows.
Wenn noch keine Firmware im Controller ist (direkt nach dem Installieren des Bootloaders), startet der Brennvorgang automatisch. Andernfalls wartet das Programm auf den Reset des Controllers. Peters Tool arbeitet nur mit COM1 bis COM4 zusammen. Also ggf. den USB Adapter im Gerätemanager umstellen.
Die Ausgabe sieht dann wie folgt aus:
C:\fboot18>fboot18 /Ptest.hex /b9600 /c1 COM 1 at 9600 Baud: Connected (One wire) Bootloader V1.8 Target: 1E9108 Buffer: 32 Byte Size available: 1534 Byte Program test.hex: 00000 - 00073 successful CRC: o.k. Elapsed time: 1.43 seconds
Brennen per FBoot-Linux
Für Linux steht ebenfalls ein Programmiertool (aus diesem Beitrag) für die aktuelle Version 2.1 des Bootloaders für die Kommandozeile zur Verfügung, das auch den One-Wire-Betrieb unterstützt.
Es lässt sich nach dem Entpacken durch ein simples "make" übersetzen. Die Verwendung ist analog zum DOS-Tool:
./bootloader -d /dev/ttyS0 -b 115200 -p tiny45test.hex ================================================= | BOOTLOADER, Target: V2.1 | ================================================= Port : /dev/ttyS0 Baudrate: 115200 File : tiny45test.hex Reading : tiny45test.hex... File read. Size : 2717 Bytes Program device. ------------------------------------------------- Waiting for device... connected (one wire)! Bootloader : V2.1 Target : 1E9206 ATtiny45 Buffer : 64 Byte Size available: 3582 Byte CRC enabled and OK. Programming : 00000 - 00A9D Writing | ##################################### | 100% Elapsed time: 0.79 seconds, 3439 Bytes/sec. ++++++++++ Device successfully programmed! ++++++++++ ...starting application
Arduino und FastBoot
Auch in der Arduino-IDE kompilierte Programme können über FastBoot geflashed werden.
Dazu müssen zuerst die Fuses mit einem AVR Programmer (z. B. einem günstigen usbasp von ebay) an den neuen Bootloader angepasst werden. Zuerst die richtigen Fuses in "arduino\hardware\arduino\avr\boards.txt" nachgucken, per Fusecalc die Bootloadergröße anpassen und in den Atmega schreiben.
Dann muss der Bootloader selbst in den Atmega geflashed werden.
Nun wird das eigentliche Programm der Arduino-IDE durch einen Klick auf Verify kompiliert. Arduino erzeugt nun eine Projektname.cpp.hex Datei unter Windows im "C:\Users\name\AppData\Local\Temp\build*.tmp" Verzeichnis. Diese Datei kann nun mit den hier genannten Methoden z. B. über einen FTDI USB-Seriell-Wandler geflashed werden.
Bootloader-Support in ATMegaIDE 2007
Die IDE kann wahlweise mit AVRDude und einem entsprechenden ISP-Dongle oder mit dem Bootloader das Programm in den Flash brennen.
Anpassen des Programms
Um das Firmware Update komfortabler zu gestalten, kann ein Software-Reset eingebaut werden, der per RS232- bzw. USB-Schnittstelle oder Tastendruck ausgelöst wird.
Tastendruck
In der mitgelieferten Standard.h gibt es den Befehl void Reset();. Er löst mit Hilfe des Watchdog-Timers einen Hardwarereset aus. Man kann jetzt z. B. auf einen bestimmten Tastendruck (-kombination) hin diesen Reset ausführen.
RS232/USB
Alternativ kann ein entsprechender Befehl über die RS232 gesendet werden. Standardmäßig ist dies 0xFF ‚R‘.
Einstellungen in der IDE
Der Bootloader Support kann bei den Projekt-Eigenschaften eingestellt werden. Beim Brennen wird er dann automatisch benutzt.
ToDo
Komfortables Stand-Alone Firmware-Update
Basierend auf dem Code der IDE wird es im September noch ein Standalone-Programm für das Firmware-Update geben. Es wird auch ein entsprechendes Protokoll zur Versionskontrolle haben (die bisherige Soft- und viel wichtiger Hardwareversion wird überprüft). Eine Verschlüsselung der Firmware-Datei ist in Planung.
Automatisches Erzeugen des Bootloaders
Sobald ich Zeit habe kommt in die IDE auch die Möglichkeit, die Anpassungen des Bootloaders von der IDE durchführen zu lassen.
Integration von fastboot in avrdude
Scheint zu laufen, wurde aber wegen diversen Änderungen in avrdude noch nicht integriert. Eventuell erbarmt sich ja mal jemand :)