Hallo, ist es möglich aus dem laufenden Programm heraus in die Bootloader-Sektion zu springen? Die Idee ist, dass ich über die serielle Schnittstelle ein commando schicke, der ATMega in seinen Bootloader springt und ich dann einfach den flash neu beschreiben kann. Im Moment ist es so, dass in der Bootloader-Sektion eine Taste überprüft wird. Ist diese gedrückt, wird der Bootloader aktiv. Selbst wenn ich in den Bootloader-Sektion spring, dann wird immernoch überprüft, ob die Taste gedrückt ist. Das soll aber dann in diesem Fall übersprungen werden. Im Prinzip ist das ja dann sowas wie ein Reset. Habe mir auch überlegt, z.B. im EEPROM ein flag zu setzen und dann einen Reset auszulösen. Wenn bei einem Neustart das flag gesetzt ist, startet der Bootloader ansonsten das Hauptprogramm. Hat jemand eine Idee, wie man sowas realisieren könnte?
das müsste gehen, hast du denn den Bootloader Code? Da braucht man dann die Einsprungadresse die die Tastenabfrage umgeht. Wenn es C oder Assembler ist kann man ein Label setzen und sieht die Adresse dann in der Map die vom Linker generiert wird.
Per EEProm wird einfacher sein. In den Bootloader Sprinngen sollte je nach dem kein Thema sein (Problem ist nur die Adresse zu adressieren, es kann sein, dass du mehrmals Sprinngen musst) Das einzige, was ich nur nicht weiss ist, ob du den Flash Programmieren kannst, ohne einen Reset zu geben.
Du kannst auch "einfach" den Controller in den watchdog schicken und im Bootloader dann die letzte Reset-Quelle feststellen.
Meines Erachtens ist es sicherer, den Bootloader nach dem Prozessorreset immer per default aufzurufen und wenn eine gewisse Zeit nichts passiert auf der Programmierschnittstelle, dann in´s Hauptprogramm zu springen. Ansonsten hast Du ein schwerwiegendes Problem, wenn Dein Hauptprogramm neu geflasht wird, irgendetwas dabei schiefgeht, der Bootloader das Hauptprogramm startet und dieses dann nicht läuft und somit nie wieder den Bootloader aufrufen kann. Also Bootloader als Quasi-Hauptprogramm nach jedem Reset starten, dann, wenn keine Daten kommen, weiter in´s Hauptprogramm. Das kostet kaum Zeit und ist extrem sicher, wenn der Bootloader kugelsicher programmiert wurde. Der ATMega bietet für diese Anwendung extra bestimmte Fuses und LockBits an.
Nach dem Prozessorreset wird der Bootloader immer aufgerufen. Wenn dann eine Taste gedrückt ist, kann man den µC flashen. Nun will ich zusätzlich die Möglichkeit schaffen, direkt aus einem Windowsprogramm zu flashen. Dazu will ich einen Befehl per RS232 an den µC schicken, damit er in den Bootloader springt. Dann darf natürlich nicht die Taste abefragt werden. Also muss entweder der Bootloader wissen warum (Reset oder commando) er gestartet wurde, ober ich muss, wie schon erwähnt, die Tastenabfrage überspringen. Habe dazu, wie von JojoS vorgeschlagen, ein Label an die entsprechende Stelle gesetzt. Wie bekomme ich aber nun die Adresse von dem Label? Ich habe mit die .lss datei angesehen, da war die Adresse 1f888. Kommt das hin? Nun wollte ich einfach per Funktion im meinem Hauptprogramm zu dieser Adresse springen. Ist doch ok so, oder?
Nee, das mach mal nicht. Setze in Deinem laufenden Programm ein Flag an eine genau spezifizierte Adresse im SRAM oder in einem Register und löse einen Watchdog-Reset aus. Nur dann kannst Du sicher sein, daß Dein Bootloader auch ganz bestimmt anläuft. Dieser kontrolliert dann das Flag und gibt für die W....s-Software das Flashing frei.
>>spezifizierte Adresse im SRAM oder in einem Register
Bleibt der Zustand des Flags während eines Software-Reset sicher
erhalten? Ich würde sagen ja, aber weiss das jemand?
Wenn der Zustand des Flags nach einem Hardware-Reset (Brown-Out,
Einschalten) nicht definiert ist, kann das aber schiefgehen.
Sven
Bei einem Software-Reset bleiben die Flags erhalten. Bei einem Hardware Reset nach dem Einschalten sind sie undefiniert. Der Watchdog hingegen verändert das SRAM nicht, wenn der Controller einmal läuft. Du kannst ja mehrere Bytes mit definiertem Bitmuster füllen, um ganz sicher zu gehen...
die Adresse müsste man durch 2 Teilen, der Speicher wird doch Wortweise addressiert, war das nicht so? Dann kommt man auf 0xFC44, das passt nur wenn das ein Mega128 ist. Jetzt fehlt nur noch der Sprung zu dieser absoluten Adresse.
Direktes Springen in den Bootloader halte ich für - sorry - grob fahrlässig, da keines der I/O Register dann initialisiert ist und man von keinen definierten Zuständen ausgehen kann. Es sei denn, der Bootloader kontrolliert das alles und fängt es entsprechend ab. Auf jeden Fall sollte in der ersten Zeile des Bootloaders ein "cli" stehen, damit nicht ein gerade auflaufender Interrupt der Bootloader gleich wieder abschießt.
warum und was ist nicht initialisiert? Der Bootloader macht doch nichts besonderes und es ist alles initialisiert weil das Hauptprogramm schon lief. Das die Interrupts gesperrt werden müssen ist richtig. Nur nach dem Flashen würde ich einen Reset anspringen damit bei einem C-Programm z.B. der Stack wieder sauber ist und der return nicht in unbekanntem Code (weil ja neu geladen) landet.
Nehmen wir mal an, der Controller startet, dann läuft er zuerst in den Bootloader. Alles paßt. Alle I/O Register (auch die vom USART z.B) haben die erwarteten Werte. Das Hauptprogramm wird angesprungen. Dort wird alles Mögliche abgearbeitet und auch Register verändert. Nun wird auf Befehl hin wieder in den Bootloader gesprungen. Dieser findet jetzt aber plötzlich alles anders vor. Klar, man kann nun eine komplette Init im Bootloader machen, und ebenso eine im Hauptprogramm, aber ist das nicht doppelter Aufwand? Was ist an einem gezielten Reset, der den Bootloader startet, so verkehrt?
"warum und was ist nicht initialisiert? Der Bootloader macht doch nichts besonderes und es ist alles initialisiert weil das Hauptprogramm schon lief." Juhu, ich nehme also die Init-Routinen von Word und rufe dann die Funktonsroutinen von Excel auf !!! Der PC wird mir aber was husten und bestenfalls nen Bluescreen machen. Programme sind nur in sich funktionsfähig. Ich kann nicht 2 halbe Hex-Files zusammwursteln und erwarten, daß dann überhaupt noch irgendwas funktioniert. Bootloader und Hauptprogramm, sind 2 völlig verschiedene Programme, die nichts voneinander wissen. Peter
vielleicht ist das so wenn der Bootloader sehr komplex ist. Aber ich habe einen einfachen seriellen Bootloader und der initialisiert sich beim Start selber. Die 'lästige' Technik mit zusätzlichem Bootloader Button habe ich auch, deshalb die gleiche Idee wie sie hier vorgeschlagen wurde. Aber prinzipiell meinen wir ja schon das gleiche, es ist doch nur die Frage wie man in den Bootloader kommt. Natürlich an die Stelle vor der nötigen Initialisierung, und warum soll man da nicht einfach hinspringen?
Der Bootloader steht fest an einer Stelle im Speicher, dafür ist es ja der Bootloader. Den betrachte ich also mal als eine Firmware die aus dem Hauptprogramm nutzen kann. Erste Bedingung war ja das man den Code kennen sollte damit man den Einsprung richtig setzen kann. 'Gefährlich' ist nur dafür ein Konstante zu nehmen wenn man den Bootloader doch mal ändert. Dann wäre ein Export der Adresse und ein Import im Linker des Hauptprograms sicherer. Mit irgendeinem unbekannten Bootloader würde ich das auch nicht machen.
Bootloader und Hauptprogramm benutzen Variablen und diese verteilt der Linker irgendwo rein zufällig im SRAM. Ruft das Hauptprogramm den Bootloader auf, sind die Variablen völlig falsch initialisiert. Der Bootloader muß also den SRAM völlig neu initialisieren, daran fürt kein Weg vorbei. Und der Bootloader darf nicht mehr zum Hauptprotgramm zurückkehren, da er ja dessen Variablen zerstört hat. In der Regel hat er ja auch das Hauptprogramm selber zerstört. Er darf also nur an den Eintrittspunkt des Hauptprogramms (0x0000) springen, damit dieses sich wieder neu initialisieren kann. Eine völlig andere Sache sind API-Calls, die das Hauptprogramm benutzen kann und die wieder zurückkehren. Diese API-Calls müssen in Assembler geschrieben sein, damit sie keinen SRAM benutzen, sondern nur den Stack und zerstörbare Register (Scratchpadregister). API-Calls macht man vorzugsweise auf die letzte Adresse des Flash, da diese ja für jedes Derivat fest steht. Peter
Also, nach dem flashen soll natürlich eine Reset ausgelöst werden. Aber trotzdem scheint ja diese Methode nicht optimal zu sein. Wie könnte man es denn besser lösen? Mit dem Watchdog eine Reset auslösen und dann einfach im Bootloader die Resetquelle abfragen habe ich mir auch schon überlegt. Im Moment habe ich noch keine Watchdog im Programm. Das Feature werde ich aber vielleicht hinzufügen und dann habe ich ein Problem. Und wie sieht es mit dem Flag im EEPROM aus? Kann man im Prinzip mit zwei Programmen die gleiche Stelle im EEPROM adressieren?
Ich würds einfach so machen, wie in meinem Bootloader: Nach jedem Reset wird zuerst in den Bootloader gesprungen und der wartet 200ms, ob das richtige Paßwort reinkommt. Wenn nicht, dann springt er zur Anwendung. Um nun aus der Anwendung den Bootloader zu starten, kriegt die ein Kommando, mit dem der Watchdogreset ausgelöst wird. Danach sendet der PC sofort das Paßwort in einer Schleife, bis er eine Antwort bekommt. Peter
@Peter Stimmt eigentlich. Das wird die beste Lösung sein. Jetzt fehlt mir ja nur noch der richtige bootloader :-) Benutzte zu Testzwecken gerade den von mthomas. Leider bekomme ich den nur mit AVRProg zum laufen, aber nicht mit avrdude und avrosp. Deine Bootloader habe ich mir auch schonmal angeschaut. Aber damals war gelaube ich das Problem, dass er mit dem ATMega128 nicht richtig funktioniert hat. Kann das sein? Wie sieht es denn da mittlerweile aus?
Der Mega128 überschreitet die 64kB-Grenze und braucht daher 3Byte-Adressen. Da ich aber auch nicht annähernd so extrem viel Flash brauche, habe ich mich nicht näher mit dem Mega128 beschäftigt. Mir ist rätselhaft, was man mit nem Mega128 bloß anfangen kann. Für Entwicklungszwecke habe ich mir mal einen großen Mega32 gegönnt, benutze aber eigentlich nur den Mega8. Peter
Naja, ich bin bei mir knapp an der 64kB-Grenze. Gut, wenn ich beim Kompilieren Optimierungen einschalte wird es auch weniger. Respekt, wenn du in der Regel mit nem AtMega8 auskommst. Wieviele Zeilen C-code haben dann deine Programme so? Wäre es denn arg schwer, den bootloader so umzuschreiben, dass man auch den kompletten AtMega128 flashen kann?
"Benutzte zu Testzwecken gerade den von mthomas. Leider bekomme ich den nur mit AVRProg zum laufen, aber nicht mit avrdude und avrosp." Ist nicht nur von mir, auch wenn man den Urspung im Butterfly-Bootloader kaum mehr sieht. Inzwischen sind auch von anderen viele Verbesserungen und Ereiterungen eingeflossen - siehe readme-Datei. avrosp habe ich nie ausprobiert. Aber mit avrdude funktioniert "mein" AVRprog compatible-Bootloader. Man muss den Bootloader nur den ISP Device-Type senden lassen und nicht dem BOOT Device-Type. AVRprog unterscheidet diese, avrdude in der Version 5.1 aus WinAVR 4/06 scheint noch auf Angabe des ISP-Typen zu bestehen. Flash/EEprom read/write funktioneren bei AVRprog auch mit der ISP Angabe. Im Bootloader-Quellcode gibt es dafuer eine Konfigurationsmoeglichkeit, vgl. readme-Datei / main.c #define DEVTYPE. (Fehler ist moeglicherweise inzwischen behoben, nicht mehr auf aktuellem Stand, habe mich aus der Mithilfe bei der avrdude-Entwicklung vor einiger Zeit zurueckgezogen) Meine "test-batch":
1 | @echo off |
2 | rem Use avrdude as programming-software with the AVRProg compatible |
3 | bootloader |
4 | rem Martin Thomas, 2006 |
5 | |
6 | rem Verfiy that the bootloader is configured with #define DEVTYPE |
7 | DEVTYPE_ISP |
8 | rem since it seems that avrdude does not work with "Boot" |
9 | device-types and needs |
10 | rem ISP device-types (at least in version 5.1 as in WinAVR 4/06) |
11 | |
12 | set HEXFILE=cansniffer.hex |
13 | set PROGRAMMER=avr109 |
14 | set PORT=com2 |
15 | set BAUD=19200 |
16 | set PART=atmega32 |
17 | |
18 | rem * disable safemode - bootloader can not "restore" fuses anyway |
19 | set DIS_SAVE=-u |
20 | |
21 | avrdude %DIS_SAVE% -p %PART% -P %PORT% -c %PROGRAMMER% -b %BAUD% -v -U |
22 | flash:w:%HEXFILE% |
23 | |
24 | rem pause |
Martin Thomas
@Andreas, "Respekt, wenn du in der Regel mit nem AtMega8 auskommst. Wieviele Zeilen C-code haben dann deine Programme so?" Naja, ich benutze noch Textdisplays (VFD), und da kann man alle Ausgaben in ASCII machen, d.h. man braucht keinen großen Flash für irgendwelche Bildchen und Animationen. Mein größtes Projekt ist etwa 10.000 Zeilen und 30 c-Files groß, inclusive aller defines in den h-Files. Ich bin der dritte, der daran arbeitet, ist also nicht besonders optimal geschrieben. Es hat mich auch zum c-Fan gemacht, da ich Sachen ändern und hinzufügen konnte ohne das ganze Programm zu kennen. Der erste Entwickler hat da sowas wie ein OS entwickelt, d.h. es wird zuerst erkannt, welche Module drinstecken, dann wird in einer Liste gesucht, ob diese Konfiguration gültig ist und dann werden die gerätespezifischen Module im SRAM installiert. Es ist daher relativ viel SRAM nötig (8kB) und inzwischen 10 verschiedene Konfigurationen möglich, die als Daten im Flash stehen. Insgesamt werden also etwa 40kB benötigt. Es ist ein 8051-Projekt, größere Projekte mache ich immer auf dem 8051, da er 4 Interruptprioritäten hat. Ich mag es, wenn man die einzelnen Module möglichst unabhängig und mit wenigen Nebenwirkungen programmieren kann. Und da sind Prioritäten äußerst bequem, da langsame Interrupts keinerlei Rücksicht auf schnelle Interrupts nehmen müssen. Mit den AVRs mache ich nur kleinere Sachen wegen der nur einen Priorität. Obwohl einmal habe ich ne 2. Priorität mit nem freien Timer einbauen müssen, wegen ner Software-PCM. Peter
ich habe den Ansatz mit dem Sprung in den Bootloader weiterverfolgt und dabei einen Thread im gcc Forum gefunden: http://www.mikrocontroller.net/forum/read-2-416971.html da ich das auch mit gcc mache und Ergebnisse nicht allgemeingültig sind poste ich meine Lösung in den gcc Thread.
@Martin Ich werde das ganze nochmal genau testen. Falls das Problem auch weiterhin noch besteht, werde ich mal einen extra thread aufmachen @Peter Hätte mich auch gewundet, wenn 10.000 codezeilen in eine AtMega8 passend würden :-) Besteht denn die Möglichkeit, Deinen bootloader auf den AtMega128 zu trimmen? @JojoS Ich werden mit das ganze nochmal genauer anschauen. Wobei mir der Vorschlag von Peter auch sehr gefällt.
@Martin, "Hätte mich auch gewundet, wenn 10.000 codezeilen in eine AtMega8 passend würden :-)" Hat ja auch niemand behauptet. 40kB ist aber noch meilenweit von 128kB entfernt. Peter
@Peter Ich wollte damit nur sagen, dass ich mir schon gedacht habe, dass du auch programme schreibst, die nicht in einen Atmega8 passen. Will ja nicht nerven, aber ist es möglich mit wenig aufwand deinen bootloader für den atmeaga128 umzuschreiben?
Autor: Peter Dannegger (PeDa) Datum: 25.09.2006 10:11 "@Martin ..." Ich habe das schon richtig verstanden. Andreas war der "Verwunderte". - Ich kenne den PBOOT-code nicht wirklich, aber die erforderlichen Erweiterung fuer groessere Flash-Speicher kann man sich wahrscheinlich relativ einfach aus "meinem" Bootloader abschauen - es sind nur ein paar Zeilen. http://www.siwawi.arubi.uni-kl.de/avr_projects/#avrprog_boot Martin Thomas
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.