Servus! Es geht um das Thema AVR (in meinem Fall ein atmega16) und Bootloader. Ich möchte meinen MC in Zukunft über UART mithilfe eines Bootloaders flashen. Zu diesem Zweck gibt es ja schon so einiges im Netz (angeschaut habe ich mir Peter's Bootloader, und MegaLoad). Ich würde aber meinen Bootloader sehr gerne selber schreiben (nur so lernt man was), und suche dazu einige anfängertaugliche Informationen. Im Manual steht zwar schon einiges, aber eben nicht anfängertauglich. Gibt es so etwas wie ein Bootloader-Tutorial? Und vorallem, wie's mit AVR-GCC geht? Danke! lg, JaM
Sers JaM, Du scheinst genauso ein Optimist wie ich zu sein ... Ich habe es mittlerweile Drann gegeben ... Vorstellen könnte ich mir das so: ATMega wird initialisiert und beginnt bei 0x0 zu arbeiten, ein paar Sekunden auf bestimmtes Command vom UART warten falls da was kommt, Daten in den EEPROM Schreiben (nach dem Loader natürlich ;-) ) ... Falls nix kommt, an adresse des geflashten codes springen ... Aber ob Du da mit Plain C weit kommst weiß ich nicht ... Lg Christian
Sers Christian, naja, es sieht so aus, dass ich schon ein wenig über die Funktionsweise des Bootloaders weiß. Wie er angesprungen wird, das er den Reset nach 0x0000 vornimmt etc. Was ich eben noch nicht verstanden habe, ist die Sache mit dem Paging, ein gewisser Z-Pointer? Allgemein, der Zugriff auf den Prog-Flash, und die ganzen Register, die damit auch involviert sind. Natürlich werden die alle schön brav im Manual aufgelistet, aber da wird man einfach mit Infos überrollt, ich hab mein Problem damit, ganz grob zu erkennen, was wie eingestellt werden muss. lg, JaM
Hallo JaM, ich bin im Moment auf dem selben Ast gelandet - für mein Projekt muss ich das wohl oder übel machen, denn ich habe beim Programmieren über SPI beim ATmega32 gewisse Probleme mit meiner Peripherie (außerdem ist das viel sexier, wenn man einen Bootloader hat). Ich habe mir mal die AppNotes 109 und 911 runtergeladen. Der Vorteil der 911er Appnote ist, dass man die PC-Seite schon praktischerweise erschlagen hat. In der 109er AppNote ist das mit den Seiten und SPM, LPM ganz gut beschrieben. Dazu gibt's dann noch einen IAR-Quellcode. Ich habe keinen IAR und habe deswegen alle auf gcc portiert (also lauter eigene Funktionen). Das Problem ist, dass es jetzt nicht funktioniert ;-). Lesen kann ich mittlerweile vom AVR mit dem AVROSP (AppNote 911). Nur schreiben kann ich noch nicht. Es dürfte eigentlich keinen prinzipiellen Unterschied machen, oob man den ATmeag32 oder ATmega16 verwendet. Wir könnten uns also bei Bedarf mal austauschen (Quälcode :-), Verständnis usw.) MfG, Daniel
Das versuche ich auch seit einer ganzen Weile, allerdings komplett in Asm. Mein Ziel ist es, einen Mega88 ueber BT updaten zu koennen. Bei allen BLs, die ich bisher getestet habe, ist das genaue Timing so problematisch, dass die Verzoegerungen, die bei der Uebertragung von BT entstehen, einfach zu gross sind und das ganze nicht funktioniert. Mein groesstes Problem sind diese ganzen Teile, in die der Flash geteilt ist, zB RWW und NRWW. Das kann ich mir im Datenblatt 10mal durchlesen. Ich versteh nicht, was das ueberhaupt bewirken soll und gleich gar nicht, wozu es gut sein soll. MfG
Guck doch mal unter: http://lists.gnu.org/archive/html/avr-gcc-list/2003-08/msg00265.html Es ist ein X-Modem-Bootloader (Das X-Modem-Protokoll kann selbst Hyperterminal, was bei Windows inklusive ist.) Zum Verstehen des Bootloaders braucht man aber auch Hintergrundwissen... Michael
@Daniel: Ich steh gerade aufm Schlauch: Wo kann ich diese AppNotes runterladen? Und Stichwort Sexier: Auf jeden Fall, ein Bootloader ist einfach das non-plus-ultra... :D @André: Gerade das mit dem RWW und NRWW verstehe ich auch nicht... wenn sich da mal ein "Wissender" zu äußern könnte... lg, JaM
Nachtrag: Hab die AppNotes auf der atmel-Seite doch noch gefunden... :) lg, JaM
"Bei allen BLs, die ich bisher getestet habe, ist das genaue Timing so problematisch, dass die Verzoegerungen, die bei der Uebertragung von BT entstehen, einfach zu gross sind und das ganze nicht funktioniert." Wie kommst Du denn darauf ??? Die SPM-Instruktionen sind zeitgeschützt, d.h. sie müssen innerhalb 4 Zyklen nach Laden von SPMCSR erfolgen. Ansonsten gibt es nicht die geringsten Timing-Einschränkungen, Du kannst auch nur ein Byte pro Tag senden, wenns Dir denn Spaß macht. Das einzige, was taktabhängig ist, ist die Baudrateneinstellung bei Verwendung der UART. Ich habe meinen Bootloader auch nur anhand des Datenblattes geschrieben, da sind doch sogar Beispiele drin. Besser als im Datenblatt kann ichs auch nicht erklären. Das mit dem RWW und NRWW bedeutet nur, das die CPU bei Beschreiben des Bootloaderbereichs anhält, sonst nicht. Wird der Bootloaderbereich nicht voll ausgenutzt und soll zusätzlich beschreibbar sein, d.h. nicht LARGEBOOTSTART, dann muß man das Protokoll so definieren, das während des Löschens bzw. Schreibens keine neuen Daten gesendet werden. Peter
"Die SPM-Instruktionen sind zeitgeschützt, d.h. sie müssen innerhalb 4 Zyklen nach Laden von SPMCSR erfolgen." Darum gehts es nicht. Eher darum, dass ich keine Flusskontrolle am BTmodul verwende und dadurch der Puffer ueberlaeuft. Anschliessend ist die BT Verbindung leider erstmal weg. D.h. ich muessen ein sinnvolles Protokoll basteln, das dafuer sorgt, dass eben nicht zu viel gesendet wird. Um nun nicht einen fertigen Loader soweit umzubasteln, bis er gar nix mehr macht, hatte ich vor einen komplett eigenen zu schreiben :) MfG
"Eher darum, dass ich keine Flusskontrolle am BTmodul verwende und dadurch der Puffer ueberlaeuft." Na und warum machst Du es dann nicht ? Ohne Flußkontrolle geht es eben nicht, so einfach ist das. Z.B. mein Bootloader geht davon aus, daß der Mega mindestens 512 Byte SRAM Puffer hat, d.h. er wartet nach 512 Byte einfach auf das O.K. für die nächsten 512 Byte. Peter
Ich lese gerade die AppNotes zum Thema, das bringt mich weiter! Danke Daniel! lg, JaM
"Na und warum machst Du es dann nicht" Weil der Rest der Applikation das nicht zulaesst. Die Flusskontrolle ist nicht in der FW des BT moduls enthalten, da sie aufgrund der VM auf dem Modul natuerlich auch Zeit braucht um zu laufen (SW auf der VM ist so schon langsam...). Und diese Zeit ist schlicht und ergreifend nicht da. MfG
"Weil der Rest der Applikation das nicht zulaesst." Nun, dann gibt es nur eine Möglichkeit: - Der Bereich über LARGEBOOTSTART ist tabu, d.h. kann nicht beschrieben werden. - Die Baudrate ist so langsam zu wählen, daß das Füllen des SRAM-Puffers mit der nächsten Page länger dauert, als das Löschen und Schreiben der vorherigen Page. Nur dann geht es auch ohne Flußkontrolle. Peter
P.S.: Was ist VM ? Flußkontrolle heißt nicht, daß etwas länger dauert, sondern ganz im Gegenteil ! Man muß nicht garantierte Maximalzeiten abwarten, sondern macht schon dann weiter, wenn die Gegenseite wirklich bereit ist. Peter
VM = Virtual Machine. Laeuft neben dem eigentlichen BT Stack auf dem BTmodul und ermoeglicht dem Benutzer eigene Programme in den Flash des Moduls zu laden. Leider ist das ganze nur ein Interpreter und so natuerlich besonders schnell..... ;) Leider haette ich dann aber das Problem, dass die Flusskontrolle nicht erwuenscht ist, wenn das eigentliche Programm auf dem AVR laeuft. Alles etwas ungewoehnlich *g An der Zeit zum Flashen solls nicht mangeln, es geht lediglich darum, dass das Geraet am Ende wartbar ist. MfG
frage: wenn sich z.b. nur ein byte innerhalb einer page des flashs geändert hat, kann ich dann nur dieses byte neu schreiben? oder muss ich trotzdem (so hab ich es verstanden) die ganze page erasen und neu schreiben? bei dieser frage geht es mir um eine art "schonung" des flashs... lg, JaM
Das Flash kann nur Seitenweise beschrieben werden. Theoretisch (ausprobiert habe ich das noch nicht) sollte es möglich sein, nachträglich Bits zu löschen, also z.B. aus einem $C6 ein $C4 zu machen. Setzen lassen sich die Bits im Flash aber ausschließlich durch den Erase-Befehl.
noch ne frage: wie bekomme ich denn den code in die bootsection? in asm wahrscheinlich mit dem .org befehl, aber wie geht's mit avr-gcc? lg, JaM
Hallo JaM, wie man den Code komplett dahin bekommt habe ich mich auch etwas länger gefragt. Bei der avr-libc-Dokumentation ist (ich weiß nicht mehr genau wo) beschrieben, wie man die gesamte .text-section in der Gegend umherschiebt (ist eine Linker-Option). Ich kann heute abend mal mein Makefile zum Bootloader anschauen, denn ich habe im Moment die exakte Syntax nicht im Kopf. MfG, Daniel.
ich habs gerade eben selber mit dem --section-start kommando hinbekommen. allerdings muss ich den bootloader-code jetzt immer in die hexdatei rein copy-n-pasten, die als app-code auf den avr drauf soll. das ist natürlich ungünstig. gibt's ne möglichkeit, den bootloader zu flashen, und dann diesen flash zu sperren, so dass mir ein neues hex-file (benutzte pony) den bootloader am ende nicht mit 0x00 überschreibt? und irgendwie gefällt mir das alles nicht... z.b. brauch mein bootloader doch keine interrupt-vektor-tabelle, oder? kann ich dem compiler irgendwie erklären, er soll das bitte weglassen? lg, JaM ps. aber immerhin, es geht voran...
> brauch mein > bootloader doch keine interrupt-vektor-tabelle, oder? Willkommen im Club :-p
Hallo Freunde, das mit der Interrupt-Vektortabelle ist mir auch schon aufgestoßen. Nach einiger Recherche hier im Forum ist mir allerdings aufgefallen, sie lieber einfach zu ignorieren (so viel Platzt benötigt die ja auch wieder nicht). Zumindest vertraten die Leute, die sich mit sowas auskennen diese Meinung (Jörg Wunsch, so weit ich mich erinnere). Ich glaube wir sollten, wenn wir es irgendwann mal schaffen einen Bootloader zu schreiben, unsere Erfahrungen damit schriftlich niederlegen und der Nachwelt so ein Feld erschließen, das nicht so leicht zu beackern ist wie ein Wechselblinker oder ein elektronischer Würfel. Ich weiß, dass es genug Bootloader gibt, die alles viel besser können und viel schöner machen - aber vom benutzen lernt man nix, sonst bräuchten die meisten hier sich garnicht erst mit dem Microcontroller als Hobby zu beschäftigen. MfG, Daniel.
"allerdings muss ich den bootloader-code jetzt immer in die hexdatei rein copy-n-pasten, die als app-code auf den avr drauf soll." ??? Ich versteh nur Bahnhof. Der Bootloader wird doch nach jedem Reset angesprungen und wartet dann darauf, daß die Applikation programmiert wird. D.h. mit einem SPI-Programmer wird einmalig der Bootloader reingebrannt und die Bootloaderstartfuse gesetzt, mehr nicht. Die Applikation enthält nur die Applikation und wird über den Bootloader reingebrannt, denn dazu hat man ihn ja extra gemacht. Natürlich sollte der Bootloader jeden Versuch, sich selbst zu zerstören, abweisen ! Z.B. wenn die Applikation mal versehentlich zu groß geworden ist. Peter
@Daniel: "...unsere Erfahrungen damit schriftlich niederlegen und der Nachwelt so ein Feld erschließen...": absolut! dabei ist das mit dem bootloader doch gar nicht so schlimm, wie man am anfang denkt. die informationen zu dem thema sind nur sehr weit gestreut und wenig in zusammengefasster form auffindbar. zum thema int-tabelle: ja, wirklich stören tut sie ja nicht, der jmp am anfang überspringt den "müll" eben, wie üblich, nur dass die tabelle im "bootsector" einfach unnütz ist (außer man möchte ints im bootloader nutzen). dabei wäre es ganz einfach, das teil "rauszuschneiden" (quasi manuell im hex-file), nur das dann die adress-angaben im code nicht mehr stimmen. ich muss ehrlich sagen, je länger ich jetzt mit avr-gcc arbeite, desto unsympathischer wird mir die hochsprachen-sache. da weiss man eigentlich ganz genau, was man will, kanns dem compiler aber nicht beibringen. da ist noch was anderes, was mich stört:
1 | asm ("jmp 0x0000" ::); |
2 | 38da: 0c 94 00 00 jmp 0x0 |
3 | }
|
4 | 38de: 80 e0 ldi r24, 0x00 ; 0 |
5 | 38e0: 90 e0 ldi r25, 0x00 ; 0 |
6 | 38e2: 0c 94 73 1c jmp 0x38e6 |
7 | |
8 | 000038e6 <_exit>: |
9 | 38e6: ff cf rjmp .-2 ; 0x38e6 |
das ist das ende des bootloader-codes, man sieht schön den finalen "jmp 0x0". doch was kommt danach? der müll riecht doch gewaltig nach dem "int main ()"-overhead, den eine MCU doch eh nie verwendet. so etwas nervt mich. code, der nie ausgeführt wird... der compiler soll sich was schämen. lg, JaM
@Peter: Da hast du natürlich Recht, ich habe vergessen zu erwähnen, dass mein "Bootloader" im Moment noch gar keinen Code lädt, d.h. er sagt nur "Hallo, bin da!" und startet die App. D.h. ich lade auch den App-Code über den SPI-Programmer, und dabei wird natürlich immer der Bootloader mit 0x0 überschrieben. Daher habe ich ihn einfach in das app-hex-file rein-gepastet, ganz billig, damit ponyprog den code mitflasht. ist ansich kein echtes problem, es nervt nur... im prinzip ging es mir darum, wie man dem spi-programmer tool sagen kann, es soll die bootsection nicht anrühren... wie gesagt, nicht wichtig. lg, JaM
@ Michael: ich hab mir jetzt den xnutboot bootloader (der mit dem x-modem protokoll) angeschaut, das war auch ein guter tipp! dort wird im makefile -Ttext=(adr) als linkeroption verwendet (um die startadresse der section .text festzulegen) , das kommt genau aufs gleiche raus, wie --section-start=.text=(adr). also die frage, wie man den bootloader dahin bekommt, wo man ihn haben möchte, wäre geklärt. und so sieht das ende von main() in xnutboot.c aus:
1 | /*
|
2 | * Will jump into the loaded code.
|
3 | */
|
4 | asm volatile ("jmp 0"); |
5 | |
6 | /*
|
7 | * Never return to stop GCC to include a reference to the exit
|
8 | code.
|
9 | * Actually we will never reach this point, but the compiler
|
10 | doesn't
|
11 | * understand the assembly statement above.
|
12 | */
|
13 | for (;;); |
14 | }
|
der kommentar vor for (;;); erklärt genau das, was ich am compiler bemängelt hatte. damit wäre auch das geklärt (mit dem trick spart man den exit() code, das sind n paar bytes). jetzt kommt für meine wenigkeit die zweite phase: lerne, wie man per code flasht! :D lg, JaM
Hallo, eine freudige Nachricht - nach langer Programmiertätigkeit am gestrigen Abend, funktioniert mein Bootloader ! Man kann nun mit dem AVROSP Code in die Applikations-Sektion schreiben und verifizieren und eben alles tun, was die AppNote 109 so beschreibt. Das Lesen aus dem Flash hatte ja schon funktionert, aber beim Schreiben schmierte immer der Bootloader ab (das war zumindest meine Meinung). Ich habe festgestellt, dass in meinem inline-assembly rund um das SPM ein Problem auftrat. Siehe dazu auch meinen Thread im GCC-Forum : http://www.mikrocontroller.net/forum/read-2-215045.html#new Jetzt funktioniert aber alles und ich habe die Funktion auch schon durch programmieren des µC mit einem Testprogramm und einer Verifikation mit Ponyprog (incl. Seriell-Adapter) überprüft. Jetzt kommt noch ein bißchen Code-Kosmetik und ich kann mich vielleicht einer kleinen Dokumentation und/oder meinem eigentlichen Projekt wieder zuwenden. Bei Fragen stehe ich weiter gerne zur Verfügung. MfG, Daniel.
>so etwas nervt mich. code, der nie ausgeführt wird... der compiler >soll sich was schämen. Es steht Dir frei, den GCC oder auch das ganze WinAVR-Paket zu meiden und einen "anständigen" Compiler zu kaufen! Ansonsten: modifiziere den GCC doch einfach in der Weise, wie Du ihn gerne hättest und stelle die Resultate der GCC-Gemeinde zu Verfügung. Dann kannst Du den noobs von Compilerbauern mal so richtig Zeigen, wo der Hammer hängt. Sorry, aber das "gemotze" über den GCC weil irgendwas nicht so funktioniert, wie manche sich das ausdenken, nervt.
@Daniel: soweit ganz interessant, doch wie ging's denn schlussendlich weiter?
Ja Olivier, welche Frage hast Du nun genau ? ;-) MfG, Daniel.
Mit der "kleinen Dokumentation" :) Inzwischen habe ich den folgenden Thread gefunden: http://www.mikrocontroller.net/forum/read-4-183976.html Und bin mit dem dortigen Code ganz gut zurecht gekommen....
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.