Hallo, ich möchte meinen AT89C51ED2 innerhalb der Applikation neu flashen können. Der µC kommuniziert über die serielle Schnittstelle mit einem Host Controller (spezifisches RS485 Protokoll). Mit dem Atmel Bootloader habe ich bereits in meiner Applikation neu flashen können. Das Problem dabei ist, dass ich nicht die vordefinierten RS232 Strings für den Atmel Bootloader verwenden kann sondern die APIs per meiner RS485 Kommunikation aufrufen muss (Da noch andere Busteilnehmer an dem RS485 Bus liegen, die die Befehle für den Atmel bootloader missinterpretieren würden). Also muss ich einen eigenen Bootloader schreiben, der wie die Applikation über RS485 kommuniziert. Oder kann es ein und die selbe Routine sein? Wie organisiert man so etwas? Gruss JAN
Hi, wie es beim AT89C51 geht, weiß ich nicht im Detail, habe genau das gleiche jedoch gerade für einen M16C gemacht. Ich hab den fabrikmäßig gelieferten Bootloader drin gelassen. Im letzten Segment vor der Interrupt Vektor Tabelle liegt ein konventionelles C-Programm (mein Bootloader - 2kB), welcher über Ethernet die Haupt-Applikation flashen kann bzw. eine vorhandene Haupt-Applikation startet, falls vorhanden. Ich hab nur die Startfunktionen beider Programme fest locatet, sodass sich beide Programme gegenseitig starten können. So gibt es auch kein Problem mit der in beiden Programmen unterschiedlichen Interruptvektortabelle. Vorteil dieser Lösung: Fabrikmäßig geflashter Bootloader bleibt drin Meinen eigenen Bootloader kann ich wie gewohnt entwickeln und debuggen
Hi Danny, danke für die Antwort. Genau so brauche ich es auch. Das mit der Interruptvektortabelle ist wohl die Lösung- Ich hatte mich schon gefragt wie ich in meiner Applikation und in dem Bootloader jeweils auf einen seriellen Interrupt regieren soll. Und ob sich die beiden Interrupt Programme behindern... Gruss JAN
Du kannst Dir einen eigenen Bootloader schreiben. Allerdings ist bei den Atmel/NXP 8051 nicht vorgesehen, direkt die Bootfunktionen zu implementieren. Dein Bootloader ruft den API-Call an die Adresse 0xFFF0 des Factory-Bootloaders auf. Die API-Beschreibung findest Du in den Application notes. Damit ist es möglich, daß neuere 8051 nen anderen Flashalgorithmus haben können, aber der API-Call bleibt gleich. Du kannst allerdings in Deinem Bootloader keine Interrupts verwenden. Ist aber auch nicht nötig, da ein Bootloader ja nur eine Aufgabe zu erfüllen hat. Du mußt eh ein Protokoll benutzen, da ja während des API-Call kein anderer Code ausgeführt werden kann. Bei den NXP P89C668 dauert der API-Call zum Löschen einer Bank 10s, d.h. während 10s dürfen keine neuen Daten an den Bootloader gesendet werden. Peter
Hallo Peter, eines versteh ich nicht: Warum kann mein Bootloader keine Interrups verarbeiten? Ich bin doch darauf angewiesen, Daten vom UART zu übernehmen und das läuft normalerweise im Interrupt. Soll der Bootloader in einer Schleife laufen und die Daten vom UART pollen (Protokoll-Frame und die jeweils 128 Byte Flash-daten?) Bin dankbar für jede weiter Erläuterung. Ansonsten wünsche ich ein schönes Weihnachtsfest! JAN
Jan Schwinkendorf wrote: > eines versteh ich nicht: Warum kann mein Bootloader keine Interrups > verarbeiten? Du kannst nur den Resetvektor verschieben, die Interruptvektoren bleiben immer unten in der Applikation. > Ich bin doch darauf angewiesen, Daten vom UART zu > übernehmen und das läuft normalerweise im Interrupt. Läßt sich auch wunderschön im Polling machen. Einfach die Interruptroutine als normale Unterfunktion schreiben und überall da aufrufen, wo es etwas länger dauert (Schleifen). Und das Protokoll so festlegen, daß während eines API-Calls keine neuen Daten eintreffen können bzw. max ein Byte. Peter
>Du kannst nur den Resetvektor verschieben, die Interruptvektoren bleiben >immer unten in der Applikation. Er könnte die Interrupt-Vektoren doch zweimal schreiben: 1. durch den Bootloader --> Alle notwendigen Vektoren zeigen auf ISRs, die im Bootloader implementiert sind. 2. durch seine Haupt-Applikation --> Ab dann werden alle Interrupts von ISRs in seiner Haupt-Applikation bearbeitet.
>eines versteh ich nicht: Warum kann mein Bootloader keine Interrups >verarbeiten? ich allerdings auch nicht...?
Danny wrote:
> ich allerdings auch nicht...?
Wie wärs einfach mal mit Nachdenken?
Wenn der Bootloader bei jedem Einschaltreset die 1.Page überschreibt,
dann wartet, ob neue Daten geschrieben werden sollen oder nicht, dann
wieder die Page der Applikation zurückschreibt, bist Du ruckzuck am Ende
der Schreibzyklen des Flash angelangt.
Peter
Der Bootloader kann prüfen, ob ein zu startendes Programm da ist. Wenn keins da ist, wartet er auf Daten, die er dann in den Flash brennt. Wenn eins da ist, startet er es. Wo wird da bei jedem Einschalten eine Page überschrieben???
Danny wrote: > Der Bootloader kann prüfen, ob ein zu startendes Programm da ist. > Wenn keins da ist, wartet er auf Daten, die er dann in den Flash > brennt. > Wenn eins da ist, startet er es. > > Wo wird da bei jedem Einschalten eine Page überschrieben??? Wie soll er dann prüfen ob er was updaten soll? Genau, er braucht den UART-Interrupt, um auf die Bootloaderaufrufe zu prüfen. Oder soll er das im Polling machen? Wozu aber dann die Interrupts, wenn er eh pollt? Oder soll er irgendwann von Polling auf Interrupt umschalten? Sowas ist ja noch schlimmer, ein halb Polling halb Interrupt Programm. Ich versuche den Bootloader möglichst klein und einfach zu halten, nicht möglichst kompliziert und umständlich. Peter
>Wie soll er dann prüfen ob er was updaten soll? Er könnte prüfen, ob die Adresse der Einsprungfunktion in das Haupt-Programm != 0xffffff ist. Bei einem jungfräulichen System ist der Flash normalerweise auf 0xff initialisiert - bis auf den Teil, in dem der Bootloader liegt natürlich. --> Bootloader wartet darauf, ein Haupt-Programm flashen zu können. Falls die Haupt-Applikation bereits existiert, also ein Software-Update gemacht werdne soll, kann der Bootloader als erstes die Einsprungfunktion in das Haupt-Programm == 0xffffff setzen und diese am Ende des Update-Vorgangs wenn alles fehlerfrei durchgelaufen ist, auf den korrekten Wert setzen. So sind auch Update-Abbrüche nahezu fool-proof. >Oder soll er irgendwann von Polling auf Interrupt umschalten? Ob Polling oder Interrupt kann man ohne die Problemstellung zu kennen, nicht diskutieren. Beides geht, jedoch (@Peda: ich stimme zu) nicht gemischt, das ist mit hoher Wahrscheinlichkeit Unfug. Ich habe es bei meiner Aufgabenstellung so gelöst, dass der Interrupt-Vektor zuerst auf eine ISR im Bootloader zeigt und später (falls eine Haupt-Applikation gestartet werden konnte) auf eine andere ISR, die zur Haupt-Applikation gehört. Das bedeutet, dass sowohl Bootloader alsauch Haupt-Applikation jeweils die Interrupt-Vektortabelle schreiben. Für meine Anwendungsfälle funktioniert das Konzept und sowas ähnliches wollte auch Jan Schwinkendorf.
Danny wrote: > Falls die Haupt-Applikation bereits existiert, also ein Software-Update > gemacht werdne soll, kann der Bootloader als erstes die > Einsprungfunktion in das Haupt-Programm == 0xffffff setzen und diese am > Ende des Update-Vorgangs > wenn alles fehlerfrei durchgelaufen ist, auf den korrekten Wert setzen. > > So sind auch Update-Abbrüche nahezu fool-proof. Das Wörtchen "nahezu" gefällt mir nicht. Mein Bootloader macht überhaupt keine Annahmen über die Applikation und schreibt auch nicht zusätzlich drin herum. Er wartet immer eine bestimmte Zeit auf eine Startsequenz und wenn er diese erkennt, geht er in den Bootloadermodus. Ansonsten startet er nach einem Timeout die Applikation. Er initialisiert also jedesmal die UART im Polling Modus, prüft auf die Startsequenz ohne irgendwas an der Applikation zu ändern. Er verbraucht somit auch nur einen einzigen Flash-Schreibzyklus bei einem Update. Auf genau die gleiche Weise arbeitet bei uns auch ein CAN-Bootloader (AT89C51CC03). Der Bootloader kann auch über ein Watchdogreset aus der Applikation gestartet werden. Peter
>Das Wörtchen "nahezu" gefällt mir nicht. Ich erkläre mal "nahezu": Also, wie gesagt, als letztes wird die Einsprungfunktion von 0xffffff auf den richtigen Wert gesetzt. Dieser Wert liegt natürlich in einer Page, die bei mir 256 Byte groß ist. Wenn jetzt beim Programmieren der letzten Page bspw. die Spannung wegreißt, wird diese Page nicht korrekt geschrieben - ggf. ist sogar der Wert der Einsprungfunktion nicht mehr 0xffffff und zeigt dennoch nicht auf die Einsprungfunktion, somit würde der Bootloader beim nächsten Start auf != 0xffffff prüfen und ins Nirwana verzweigen. Um auch dieses letzte Bischen abzusichern gibt es diverse Strategien. Die, die ich kenne arbeiten mit redundanten Haupt-Applikationen im Flash bzw. Prüfsummen - mag sein, dass es noch andere gibt... Für meine Aufgabe ist die Einschränkung, die ich mir selbst auferlegt habe, ok. Das System kann in jedem Fall reanimiert werden, auch wenn "nahezu" eintritt. Im "nahezu"-Fall muss eben der Fabrik-Bootloader genutzt werden. >Der Bootloader kann auch über ein Watchdogreset aus der Applikation >gestartet werden. Ich starte ich ihn per jmp-Befehl bei Bedarf direkt aus der Haupt-Applikation, wenn ein Software-Update angefordert ist. Die Haupt-Applikation kann sich also (so wie bei euch auch, denke ich) selbst updaten.
Nachtrag: >Er initialisiert also jedesmal die UART im Polling Modus, prüft auf die >Startsequenz ohne irgendwas an der Applikation zu ändern. ist beim meinem Konzept genau so. Bootloader initialisiert (im Falle eines Updates) lediglich die Interrupt-Vektor-Tabelle so wie er es braucht. Das ist für mein Verständnis keine Änderung an der Haupt-Applikation. Die hat ja ihren eigenen Code, um die Tabelle so zu initialisieren, wie sie es braucht. >Er verbraucht somit auch nur einen einzigen Flash-Schreibzyklus bei >einem Update. ist bei meinem Konzept genau so ...mag sein, ich habe irgendwo weiter oben ungenau formuliert
Danny wrote: > Um auch dieses letzte Bischen abzusichern gibt es diverse Strategien. > Die, die ich kenne arbeiten mit redundanten Haupt-Applikationen im Flash > bzw. Prüfsummen - mag sein, dass es noch andere gibt... Warum denn so kompliziert? Meinem Bootloader ist es völlig wurscht, was die Applikationn für nen Unsinn anstellt. Er startet immer nach einem Reset (Bootvektor zeigt auf den Bootloader). D.h. hat man sich mal verflasht, kann eben nicht mehr die Applikation den Bootloader aufrufen, sondern man schaltet das Gerät kurz mal aus. > Das System kann in jedem Fall reanimiert werden, auch wenn "nahezu" > eintritt. Im "nahezu"-Fall muss eben der Fabrik-Bootloader genutzt > werden. Blöd nur, wenn der ein anderes Protokoll hat. Ich bin mir ziemlich sicher, daß Flip nicht über unseren Ethernet-CAN-Umsetzer geht. Es gibt auch Kunden mit 2 linken Händen, die sollten besser nicht das Gerät öffnen, um den PSEN-Jumper zu stecken. Wir haben auch Hochspannung im Gerät. Der Kunde muß also das Gerät einschicken. > Ich starte ich ihn per jmp-Befehl bei Bedarf direkt aus der > Haupt-Applikation, wenn ein Software-Update angefordert ist. Und was, wenn mal ein neuer Bootloader mit anderer Startadresse nötig ist oder verschiedene Derivate mit anderer Flashgröße? Die 16ms Verzögerung durch den Watchdog ziehe ich daher vor. > Die Haupt-Applikation kann sich also (so wie bei euch auch, denke ich) > selbst updaten. Ja, entweder per Watchdogreset oder bei Fehlschlag durch Einschaltreset. Ich finde 100% besser als "nahezu". Peter
>D.h. hat man sich mal verflasht, kann eben nicht mehr die Applikation >den Bootloader aufrufen, sondern man schaltet das Gerät kurz mal aus. Ja ist bei mir auch so - bis auf das Scharfschalten der Haupt-Applikation durch Schreiben der Page, in der die Adresse der Einsprungfunktion liegt. Die Lücke nehme ich in Kauf. >Blöd nur, wenn der ein anderes Protokoll hat. Du hast recht, er hat ein anderes Protokoll und sogar ein anderes Übertragungsmedium. Wo es keine Anforderung gibt, ist auch kein Geld, demzufolge auch keine Lösung. >Ich bin mir ziemlich sicher, daß Flip nicht über unseren >Ethernet-CAN-Umsetzer geht. ??? >Und was, wenn mal ein neuer Bootloader mit anderer Startadresse nötig >ist oder verschiedene Derivate mit anderer Flashgröße? Dann wird der Bootloader mit anderen Einstellungen neu kompiliert. Was ist aber, wenn ich die Startadresse der Hauptapplikation ändern muss? Dann stehen wir wieder vor dem von dir genannten Problem - nur auf der anderen Seite. >Ja, entweder per Watchdogreset oder bei Fehlschlag durch Einschaltreset. >Ich finde 100% besser als "nahezu". Der Bootloader kann auf viele Arten gestartet werden, du hast recht. Das trägt jedoch nicht zur Lösung des Kernproblems bei. >Warum denn so kompliziert? Was ich in zuvor geschrieben habe, ist eher eine Diskussion zu konkreten Anforderungen und den daraus resultierenden Lösungen. Wirklich spannend und nicht so sehr projektabhängig ist eher folgende Fragestellung. Die Herausforderung bei jedem Update-Prozess ist das Scharfschalten der Haupt-Applikation nach dem Flashen. Also: Folgende Zustände gibt es: 1. Applikation wird geflasht (App ist also unbrauchbar) 2. Applikation Flashen ist beendet 3. Applikation wird aktiviert (letzter Block wird geflasht, Flag wird gesetzt...) 4. Applikation ist aktiviert (ist also brauchbar) Bei 1. und 2. kann unterbrochen werden, Leitungsausfall, Spannungsausfall, ... Für 3. muss Nichtunterbrechbarkeit sichergestellt werden (siehe mein Posting von 27.12.2007 15:08), unabhängig davon wie der Bootloader gestartet wird, oder wie er seine Daten bekommt. Ich habe in meinem Update-Prozess die Lücke zu 3 bewußt in Kauf genommen.
Danny wrote: > Was ist aber, wenn ich die Startadresse der Hauptapplikation ändern > muss? Ich mags einfach, d.h. die Applikation fängt immer bei 0x0000 an. Dann brauch ich mich nicht mit den Linkereinstellungen zu verrenken. Außerdem sind die Interruptvektoren fest ab 0x0003. Man müßte dann dort extra LJMPs eintragen, wenn die Applikation woanders ist. Wozu also all diese Umstände? > Folgende Zustände gibt es: > 1. > Applikation wird geflasht (App ist also unbrauchbar) > 2. > Applikation Flashen ist beendet > 3. > Applikation wird aktiviert (letzter Block wird geflasht, Flag wird > gesetzt...) > 4. > Applikation ist aktiviert (ist also brauchbar) > > Bei 1. und 2. kann unterbrochen werden, Leitungsausfall, > Spannungsausfall, ... > Für 3. muss Nichtunterbrechbarkeit sichergestellt werden (siehe mein > Posting von 27.12.2007 15:08), unabhängig davon wie der Bootloader > gestartet wird, oder wie er seine Daten bekommt. Nö, bei meinem Bootloader gibt es keine speziellen Zustände. Er wird in jedem Fall aufgerufen. Es muß also nirgends Nichtunterbrechbarkeit sichergestellt werden. Du hast immer einen nächsten Versuch, bis der Download geklappt hat. Die Applikation muß auch nirgends scharf geschaltet werden (wozu auch). Der CAN-Bootloader macht zusätzlich noch nen CRC-Check, d.h. bei fehlerhaftem Download verbleibt er einfach im Bootloader. Peter
>Der CAN-Bootloader macht zusätzlich noch nen CRC-Check Also doch ;) ... ...siehe dein Beitrag 27.12.2007 16:24 "Warum denn so kompliziert?" dein Beitrag legt nahe, dass du ohne CRC auskommst. Hab mich ernsthaft gefragt, wie du das Zauberstück ohne CRC aufführen willst. ;) >bei fehlerhaftem Download verbleibt er einfach im Bootloader. Wenn diese Anforderung vom Kunden akzeptiert ist - ok. Ich kenne Projekte, in denen gefordert war, dass das Device bei fehl- geschlagenem Flashen nie ohne Applikation hinterlassen werden darf... somit steigt der Aufwand erheblich. PS: Schön, dass man hier auch diskutieren kann, ohne dass es zu verbalen Entgleisungen kommt. Ist in diesem Forum ja nicht alltäglich!
Moin ich bin eigentlich der Meinung, dass eine ungültige, nicht vollständige Applikation nicht gestartet werden sollte. Wer weiss was für Schäden durch fehlerhafte Port initallisierungen, ... angerichtet werden können. Weiter kann ja auch die Update Prozedur selber fehlerhaft sein. Es kann ein Update an den Benutzer als erfolgreich gemeldet werden obwohl er fehlerhaft war. In diesem fall wird eine Unvollständig geflashte Applickation ausgeführt, die teilweise funktioniert, Der Fehler tritt unter umständen nicht gleich auf. Im aktuellen Projekt, können wir es uns nicht leisten bei einem FW Update Service Fälle zu generieren. Daher gehen wir dort den weg der Redundanten FW. Wir haben einen kleinen Booter, der nur die Aufgabe hat das Aktuell gültige FW Image zu ermitteln und zu starten. Dies geschieht durch die Auswertung eines Informationsblockes am anfang des Images. Dort sind Informationen wie Image grösse, ValidFlag, Image Counter, Erstellungsdatum, Versionsinfos Hinterlegt. Sollte kein gültiges Image gefunden werden, wird ein sogenanter Valid Marker im Flasch gelöscht und der Controller somit in den Facktory default zurückversetzt. Dadurch wird dann der Booter des Prozessorherstellers angewiesen sich eine neue FW zu besorgen. Bei uns über USB. Die Flasch applikation bringt jedes FW Image selber mit ( ist bei uns besser so, da das FW Image aus dem Dateisystem gezogen wird ) Für ein anderes Projekt hab ich mal einen Booter schreiben dürfen, der über ein spezielles RS232 Protokoll. Die ISRs habe ich damals durch bedingte sprünge Verteilt, hatte den nachteil, das ein sprung mehr nötig war. Der Booter hatte einen grundlegenden Protokollhändler, der in der Lage war im Fehlerfalle eine neue FW anzufordern. Die Fläsh Applikation lag damals mit im Booter. Und zu dem Thema FLIP Tools, bin ich mitlerweile auch geheilt. Für die Version 2.xx gabs ja noch ein Programierinterface, mit dem man sich eigene Updater erstellen konnte. Die 3.xx benötigt ja mitlerweile ein installiertes JRE 1.5 oder höher. Somit für uns nicht mehr verwendbar. Die API der Version 2.x hat hin und wieder Programierfehler gemeldet obwohl die FW gültig war. Nicht gerade toll, wenn das draussen beim Kunden passiert und der dann anruft. gruss
Danny wrote: >>bei fehlerhaftem Download verbleibt er einfach im Bootloader. > Wenn diese Anforderung vom Kunden akzeptiert ist - ok. > Ich kenne Projekte, in denen gefordert war, dass das Device bei fehl- > geschlagenem Flashen nie ohne Applikation hinterlassen werden darf... > somit steigt der Aufwand erheblich. Ja, die Anforderungen können unterschiedlich sein. Das Updaten ist bei uns eine Servicefunktion, d.h. das Gerät ist dabei nicht in Betrieb. Ein unvollständig geflashtes Programm könnte also auch ohne CRC keinen Schaden anrichten. Das Update muß bei Problemen wiederholt werden, bis das Verify ein O.K. meldet. Mir ging es vor allem darum, daß der Bootloader immer funktioniert, d.h. man sich nicht versehentlich aussperren kann. Peter
Peter Dannegger schrieb: > Mir ging es vor allem darum, daß der Bootloader immer funktioniert, d.h. > man sich nicht versehentlich aussperren kann. Sorry, dass ich den alten Thread ausgrabe aber ich denke mein Problem passt hier am Besten rein. Ich stehe gerade auch vor dem Problem, einen Bootloader für ein 8051 Derivat mit internem Flash zu implementieren und das auch möglichst so, dass ich micht nicht aussperren kann. Lösen wollte ich es eigentlich so wie von Peter vorgeschlagen. Bootloader im unteren Bereich des Speichers, dann das Hauptprogramm. Damit der Bootloader immer beim Start ausgeführt wird muss an Adresse 0x0000 ein LJMP an die richtige Einsprungadresse in den Bootloader stehen. Den Flash kann ich als 512 Byte Page löschen. Die Einsprungadresse wird also mit gelöscht, wenn ich die Interruptvectoren ändern will. Geht in diesem Moment was schief, steht dort ein 0xFFFFFF. Also nichts mit Bulletproof. Habe ich da irgendwo einen einen Denkfehler? Ideen, wie man das Problem lösen könnte? Ich könnte die Interruptvectoren über eine zusätzliche Tabelle umlegen und so generell die erste Page vor dem Überschreiben schützen. Sind dann halt zwei Sprünge nach dem Interrupt zur ISR. Was anderes fällt mir momentan nicht ein. Gruß Steffen
Steffen schrieb: > Lösen wollte ich es eigentlich so wie von Peter vorgeschlagen. > Bootloader im unteren Bereich des Speichers, dann das Hauptprogramm. > Damit der Bootloader immer beim Start ausgeführt wird muss an Adresse > 0x0000 ein LJMP an die richtige Einsprungadresse in den Bootloader > stehen. Nö, der Bootloader steht bei mir ganz hinten unter dem Factory-Bootloader. Die Applikation soll sich ja um nichts extra kümmern müssen. Zumindest bei den NXP und Atmel 8051 kann man den Bootvektor auf was anderes als 0x0000 einstellen. An 0x0000 steht also ganz normal die Applikation und auch die Interruptvektoren werden nicht umgeleitet. Peter
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.