Mittlerweile sind neue Versionen der Entwicklungswerkzeuge verfügbar. Hier die Projektdateien
neuen Versionen:
Bootloader-Projekt für AVR-Studio
6
Uploader-Projekt für Visual-Studio 2010
Uploader-Binary
------------------------
Nach den
Problemen mit dem Farbsensor wurde
deutlich, dass ein Firmware-Update für einen unterstützenden Prozessor (z.B. für Sensorfunktionen)
unumgänglich ist. Weil es häufig. nicht möglich ist, den Prozessor zum Update "frei
zu legen", muss der Firmware-Update im eingebauten Zustand möglich sein. Bei Applikationen für
einen LEGO Mindstorms NXT steht dazu eigentlich nur das I²C-Interface zur Verfügung. Diese
Schnittstelle wird sowieso zum Datenaustausch mit dem NXT genutzt.
Schwierigkeit 1: Von Hause
aus unterstützt der ATtiny keinen Bootloader, wie dies z.B. die ATmega-Prozessoren tun.
Schwierigkeit
2: Trotzt intensiver Bemühung von Google war kein passender Code zu finden.
Also: selbermachen!
So geht's:
Funktionsweise Chip-Vorbereitung Debugging-Adapter
Details zum Adapter Bootloader
Details zum Startup-Code
Details zum I²C-Register Uploader Anforderungen
an zu ladende Programme
Funktionsweise:Das Ganze besteht aus zwei Programm-Komponenten:
Einem Bootloader auf dem µC, der Kommandos eines Steuerporgramms
(Uploader) entgegen nimmt und in der Lage ist, den Flash-Speicher des Prozessors zu beschreiben.
Einem Uploader auf dem PC, der den Bootloader ansteuert. Statt eines
PC können auch andere Geräte, z.B. die NXT-Kontrolleinheit, genutzt werden.
Uploader und Bootloader arbeiten Hand in Hand. Der Uploader ist ein PC-Programm, das per I²C
mit dem Bootloader kommuniziert. Der Uploader hat die I²C-Master-Funktion, der Bootloader
ist der I²C-Slave.
Aktivierung des Bootloaders:
Dem µC muss mitgeteilt werden, ob er der Bootloader aktiv sein soll oder ob das reguläre
Programm auszuführen ist.
Der Bootloader wird auf Grund
externer Signalzustände nach einem Reset aktiv. Als "externe Signalzustände" eignen sich
nur die I²C-Signalleitungen. Die Beschaltung der anderen Prozessor-Pins ist ungewiss.
Der Ruhezustand der I²C-Signalleitungen ist High. Nur bei der Datenübertragung gibt
es Low-Pegel. Es bietet sich an, den Bootloader über Low-Pegel an den Signalleitungen beim
Reset zu aktivieren. Liegen High-Pegel an -das ist der "normale" Zustand- wird das reguläre
Programm aktiv.
Zwischen regulärem Programm und Bootloader kann also hin und her geschaltet
werden, indem ein Reset mit entsprechenden Pegeln auf den I²C-Signalleitungen ausgelöst
wird. Dies geht durch Power-On-Reset oder über den Reset-Pin.
Speicheraufteilung (Flash):Der Bootloader teilt sich
mit dem eigentlichen Programm den gleichen Flash-Speicher. Die üblichen C-Compiler legen den
Code in den niedrigen Programmspeicher-Adressen ab. Also gehört der Bootloader in die hohen
Adressen.
In der Version 1.0 beginnt der Bootloader-Code an der Adresse 0x0c80, nimmt also
ein knappes Viertel des Speichers ein (896 Bytes). Ein Großteil des Flash wird von den
I²C-Slave-Funktionen eingenommen. Diese stehen aber auch den regulären Programmen und können
dort eingespart werden. Netto werden etwa 530 Byte benötigt.
Der ATtiny kennt es
keine geschützten Speicherbereiche. Beim Upload muss also darauf geachtet werden, dass der Bootloader-Code
nicht überschrieben wird. Es wurden jedoch keine Speicherschutzfunktionen im Bottoloader-Code
implemtiert, um Speicherplatz auf dem Chip zu sparen. Es wird auf die korrekte Arbeitsweise des
Uploaders vertraut.
Speicheraufteilung (SRAM):
Der I²C-Slave benötigt acht Byte SRAM. Diese werden am Anfang der ".data"-Section reserviert.
Näheres bei der Erläuterung des Startup-Codes weiter unten.
Funktionen:Um den Speicherbedarf auf dem Chip so gering
wie möglich zu halten, ist der Funktionsumfang sehr spartanisch ausgefallen. Im Endeffekt kann
man nur Informationen über den Chip auslesen, eine Page flashen und auslesen. Was braucht
man mehr?
Chip-Vorbereitung:
Damit das Flashen funktioniert, muss die Bereitschaft des ATtiny seinen eigenen Speicher zu beschreiben über
das Setzen der Fuse "SELFPRGEN" hergestellt werden. Mir Ponyprog sieht das so aus:
Debugging-Adapter:Zum
Debuggen habe ich einen eigenen Adpater gebaut, der über einen seriellen Port betrieben wird.
Da kann man die Übetragung auch mal anhalten und genauer nachschauen (
Details).
Die zugehörige PC-Softare kann auch Clock-Stretching.
Bootloader:Hier der
Code zum Download.
Kein normales C-Programm:Der Boorloader-Code kann
nicht an die für C üblichen Stellen im Speicher platziert werden. Die sind für das
"reguläre" Nutz-Programm reserviert. Ebenfalls ist normale Startsequenz eines C-Programms bei
einem Bootloader nicht brauchbar.
Bei "normalen" C-Programmen werden Standardbibliotheken
eingebunden, die die Speicheraufteilung regeln und Startsequenzen zur Verfügung stellen. Die Startsequenzen übernehmen
so wichtige Dinge wie Stack- und Variablen-Initialisierung.
Man muss also durch eigenen Code
sicherstellen, dass der Bootloader in den richtigen Stellen landet und dass die üblichen
C-Startsequenzen nicht vom Linker eingebunden werden. Deshalb kann man den Code also nicht "einfach
so" übersetzen. Das Rar-Archiv enthält deshalb neben den eigentlichen Quell-Dateien
auch die Projekt-Dateien für das AVR-Studio. Die Projekt-Dateien enthalten alle Steuerparamter
für das korrekte Compilieren und Linken (im Verzeichnis "default" gibt es auch eine vom AVR-Studio
generierte "makefile"). Anzupassen wären eventuell die Include-Parameter. Sie zeigen auf das
ensprechende gcc-Verzeichnis.
StartUp:Der Startup-Code
muss in Assembler entwickelt werden. C lässt keine expliziten Positionierungen im
Speicher zu.
Details zum StartUp-Code
Boorloader-Code:Der eigentliche Bootloader ist
in C geschrieben. Zunächt wird geprüft, ob der Bootloader aktiv sein soll. Danach erfolgt
die Initialisierung der Variablen und des I²C-Slave. Ist dies geschehen, verbleibt der Code
in einer Endlosschleife. Hier wird lediglich asynchron geprüft, ob ein Kommando eingetroffen
ist. Ist dies der Fall, wird in eine Funktion zur Ausführung des selben gesprungen.
Kommunikation:Die I²C-Geräte-Adresse ist im
Code auf 0x00 eingestellt. Dies kann bei Bedarf natürlich geändert werden.
Die Kommunikation
mit dem Uploader findet über ein sogenanntes I²C-Register statt. An definierten Stellen
dieses Registers werden Daten in vereinbarter Form abgelegt. Vor jeder Lese- oder Schreibsequenz
wird ein Index-Wert übertragen. Mit diesem Index wird festgelegt, an welcher Stelle die nächste
Lese- oder Schreiboperation beginnen soll.
Das Schreiben von festgelegten Codes an definierte
Stellen wird als Kommando interpretiert. Der Bootloader fragt diese Stellen in einer Endlosschliefe
regelmäßig ab.
I²C-Register:Das
Register ist insgesamt 96 Byte groß. Die letzten 64 Byte dienen als Seitenpuffer für das
Lesen und Schreiben von Flash-Pages. In ersten 32 Byte werden Prozessor-Informationen bereitgestellt
und dienen zur Steuerung der Kommandoausführung.
Details
zum I²C-RegisterI²C-Slave:Die
Funktionen des I²C-Slave sind
hier beschrieben.
Weitere Einzelheiten:...können dem dokumentierten
Code entnommen werden.
Datei
|
Funktion
|
Main.S |
Startup-Code |
Bootloader.c |
Code des Bootloader |
I2CSlave.c |
Code des I²C-Slave |
I2CSlave.h |
Pin-Belegung |
Interface.S |
Erzeugt "Interface.o" mit der Adresse der I²C-Slave-Initialisierungsroutine
|
Interface.h |
Prototypen der Event-Handler und der I²C-Slave-Initialisierungsroutine |
Bootloader.aps |
Projekt-Datei des AVR-Studio |
default (Ordner) |
Ergebnis des Build-Laufs |
Hinweis: Die Dateien "Interface.S" (eigentlich "Interface.o") und "Interface.h" dienen dazu,
den geladenen Nutz-Programmen den Zugriff auf den I²C-Slave zu ermöglichen (s.u.).
Uploader:Der Uploader ist in
Visual Basic 2008 geschrieben. Aktuell wird nur das selbstgebaute RS232toI2C-Interface untestützt.
Wer ein eigenes Interface einbinden möchte, mag sich die Interface-Definition "I2CUploader"
im Projekt "I2CBus" ansehen. Das hier erwähnte
I2C-Modul
ist nur bei einem Prozessor-Takt von 16 MHz geignet (kein Clock-Stretching).
Hier der
Code zum Download. Das
compilierte Programm kann
einfach in ein Verzeichnis kopiert und das Programm "Uploader.exe" gestartet werden.
So sieht
es aus:
Anforderungen an zu ladende
Programme:Beim Schreiben von Programmen, die mit Hilfe des Bootloader geladen werden sollen,
ist folgendes zu beachten:
- Das compilierte Programm muss im Intel-Hex-Format vorliegen (".hex"-Datei).
- Der Uploader prüft, ob der Power-On-Reset zur Adresse 0x001e springt (Anweisung
rjmp .+28, Hex-Code: 0x0ec0). Ist dies nicht der
Fall, wird die .hex-Datei nicht geladen. Mit avr-gcc compilierte Programme beginnen eigentlich
immer den richtigen Anweisung. Zu 0x001e springt der Bootloader, wenn er erkennt, dass er nicht
aktiv sein soll.
- Die Interrupts "USI_START" und "USI_OVERFLOW" sind für den I²C-Slave reserviert
und stehen nicht für eigene Zwecke für Verfügung.
- Der Uploader stellt sicher, dass die Interrupt-Vektoren für "POWER_ON", "USI_START"
und "USI_OVERFLOW" nicht überschrieben werden.
Wenn der I²C-Slave des Bootloader genutzt werden soll, müssen folgende Bedingungen
erfüllt sein:
- Die ersten acht Byte des SRAM-Bereichs sind für den Bootloader reserviert (siehe
auch StartUp-Code). Diese müssen beim Linken geschützt werden. Der entsprechende Linker-Schalter
ist: "-section-start=.data=0x800068".
- Es muss die Datei "I2CInterface.o" eingebunden werden. Sie stellt die Adresse der Funktion
"I2C_Initialize" zur Verfügung.
- Die Funktion "I2C_Initialize" muss aufgerufen werden. Hierdurch werden dem Treiber die Geräte-Adresse
und die Adressen der Eventhandler-Routinen mitgeteilt.
- Die Interrupts müssen freigegeben werden (sei()).
- Code für die Eventhandler ist zu schreiben.