Moin, ich möchte nach Inspiration des Artikels hier über Bootloader gerne einen eigenen Bootloader für mein Projekt programmieren. Unterschiede sind z.B. dass die Daten über I2C übertragen werden sollen und nicht im I-HEX- sondern BIN-Format (Speicher sparen). Nun überlege ich aber, wie ich dieses Flashen sicher mache gegenüber Abbrüchen durch einen einfachen Verbindungsabbruch oder Stromausfall. Bei ersterem würde ja der Watchdog helfen, der dann den Speicher wieder leer macht, aber was macht man bei Stromausfall? Ich hatte überlegt am Ende des ROMS für den flashenden Teil eine "Variable" anzulegen die am Anfang gelöscht wird und erst nach dem erfolgreichen Flashen geschrieben wird. Auf die würde der Bootloader dann gucken, damit keine fehlerhafte/unvollständige Version beim nächsten Mal ausgeführt wird. Macht das Sinn, und wie würde ich der Variable eine feste Adresse im ROM zuweisen? Bei Assembler wüsste ich das ja noch, aber bei C? Oder dann über inline-Assembler? Vielen Dank für Eure Antworten Ozzy
Der Bootloader muss beim "Hochfahren" ein Flag überprüfen. Anhand diesem kann er erkennen, ob eine gültige Applikation im Speicher liegt, zu der er springen darf. Du kannst eine Variable z.B. über Linkersections an eine feste Adresse mappen. Einfacher ist aber, du benutzt das EEPROM, da kannst du direkt die Adressen frei wählen und im Programm hardcoden.
Das Problem ist, zumindest wie es es bemerkt habe: Wenn bei einem Schreibvorgang die Spannung einbricht, ist nicht garantiert, welche Adresse(n) letzlich noch geschrieben wird/werden. Es kann also passieren, das das Schreiben des Flags wieder andere Daten inkonsistent macht - besonders dann, wenn Sie auf der gleichen Speicherseite liegen. Ansonsten kann ich nur raten, den Bootloaderbereich vor normalen "Ueberschreiben" zu schuetzen - entweder durch Lockbits, oder falls er "aenderbar" bleiben soll, durch ein "SPM-Interface". Letzteres ist im neuen USBaspLoader (https://github.com/baerwolf/USBaspLoader) in "firmware/spminterface.h" implementiert. Der normale Anwendungsbereich muss und wird in der Regel durch einen nachfolgenden "Verify" ueberprueft werden. Der bootloader startet den Anwendungsbereich nur, z.B. wenn dessen HASH stimmt... MfG
Versorge das Target per Usb, dann ist Stromausfall egal. Falls der Rechner beim Flashen explodiert, evtl. nochmal von anderem Rechner aus flashen.
Moin, danke für die Hinweise. Dann werde ich das ganze noch mal um ein Verify erweitern...
Mit avrdude als Programmiersoftware wird das Geschriebene automatisch zurückgelesen und überprüft.
@Kan asta: ja, das Problem ist nur, dass das Setup weder über USB noch einen PC verfügt. Hier flasht ein Controller einen anderen. Deshalb muss ich das selber machen. MfG, Ozzy
Oz zy schrieb: > Ich hatte überlegt am Ende des ROMS für den flashenden Teil eine > "Variable" anzulegen Wenn du stattdessen gleich eine CRC-16 benutzt, machst du das, was alle für die Absicherung derartiger Aktionen benutzen (sofern sie nicht noch kryptografische Echtheitsbestätigungen brauchen).
Naja, ich dachte ich beschreibe dieses Feld mit einem definierten Wert (z.B. 0x42), wenn das Flashen funktioniert hat. So kann beim nächsten Start überprüft werden, ob sich eine korrekte Version im Speicher befindet. Das ist doch unabhänig von der CRC... Oder reden wir aneinander vorbei? MfG, Ozzy
CRC stellt die Integrität der übertragenen Daten sicher. Nur weil das Flashen funktioniert, heisst das noch nicht, dass die Daten korrekt übertragen wurden.
Kan asta schrieb: > CRC stellt die Integrität der übertragenen Daten sicher. Nur weil das > Flashen funktioniert, heisst das noch nicht, dass die Daten korrekt > übertragen wurden. Und wenn man die CRC als letztes mitflasht, kann man damit nicht nur die Integrität der Datenübertragung (die die Vollständigkeit einschließt) prüfen, sondern auch die Integrität des Programms im Flash. Damit lässt sich der Flash-Inhalt nicht nur direkt nach dem Flashen verifizieren, sondern auch zu einem beliebigen späteren Zeitpunkt. Natürlich muss man sich noch irgendwo die Länge merken, über die die CRC gebildet wird. Eine Möglichkeit dafür wäre es, direkt nach der CRC ein Flagbyte 0 zu speichern. Der Bootloader liest jetzt von oben nach unten, bis er das Flagbyte findet. Dann kann er von Adresse 0 bis Flagbyte - 1 die CRC bilden, diese muss das gewünschte Resultat ergeben (normalerweise 0 für die gängigen Algorithmen).
Jörg Wunsch schrieb: Eine Möglichkeit dafür wäre es, direkt > nach der CRC ein Flagbyte 0 zu speichern. Wie willst du sicherstellen, dass dein Flagbyte nicht im Binärcode vorkommt? Entweder ist die Länge des Codes fest und bekannt, oder sie wird an einer festen Adresse abgelegt.
Kan asta schrieb: > Wie willst du sicherstellen, dass dein Flagbyte nicht im Binärcode > vorkommt? Jörg schlug vor von "oben nach unten" zu lesen. Da der nicht beschriebene Speicherbereich auf 0xff steht, ist das 0x00 Flag-Byte das erste Null-Byte bei dieser Lesereihenfolge. Viele Grüße, Simon
Simon Budig schrieb: > Jörg schlug vor von "oben nach unten" zu lesen. Da der nicht > beschriebene Speicherbereich auf 0xff steht, ist das 0x00 Flag-Byte das > erste Null-Byte bei dieser Lesereihenfolge. Ist diese Annahme denn immer gegeben? Was ist, wenn ich z.B. ein kleineres über ein gößeres Programm schreibe?
Kan asta schrieb: > Ist diese Annahme denn immer gegeben? Was ist, wenn ich z.B. ein > kleineres über ein gößeres Programm schreibe? Dann musst du halt vorher alles löschen. Länge in einer festen Adresse ablegen geht zwar, ist aber relativ schwierig zu bewerkstelligen.
Hallo zusammen! Bevor ich die CRC suche kann ich genauso gut die CRC in die letzten Bytes des Flashs schreiben. Beim Generieren der Datei, die ich zum Flashen benutze, weiss ich, welche MCU ich verwende. Dadurch weiss ich auch wie gross der Flash ist, welche Bereiche vom Programm belegt sind und welche leer, und kann somit die CRC berechnen und in die Datei einbinden. Der Bootloader kann dann beim Starten die CRC über den gesamten (nicht Bootloader)Bereich durchführen und wenn dabei 0 raus kommt ist alles gut und das Programm kann gestartet werden. Andernfalls wird auf ein neues Programm gewartet. Wenn ein neues Programm übertragen werden soll wird zu erst der komplette Flash gelöscht. Dadurch ist der gesamte Speicherbereich in einem definierten Zustand (0xFF). Damit ist gewährleistet, dass später die CRC stimmt. CU, Jay P.S.: @kan asta: Im Prinzip kann man davon ausgehen. Man könnte da jetzt was zusammen reimen aber eigentlich passt das so, da man am Anfang den gesamten Flash löscht. Zusamengereimt: Wenn man am Anfang der Übertragung ein Kommando hat, welches die Grösse des belegten Flashs mitteilt kann man darauf verzichten den gesamten Flash zu löschen und nur die benötigten Pages löschen. Dann wäre es möglich, wenn das erste Programm ziemlich gross und das neue Programm ganz klein ist, dass noch Reste im Flash verbleiben. Aber wie schon gesagt macht man sowas eigentlich nicht.
Jay schrieb: > Dann wäre es möglich, wenn das erste Programm ziemlich gross > und das neue Programm ganz klein ist, dass noch Reste im Flash > verbleiben. Aber wie schon gesagt macht man sowas eigentlich nicht. Aus meiner Sicht existieren schon Bootloader, die den Flash seitenweise beschreiben. Ich halte die EEProm-Alternative für die Beste: dort kann man eine feste Adresse für Codelänge und CRC nutzen. Und man verkleinert den nutzbaren Flashbereich nicht ;)
Jay schrieb: > Bevor ich die CRC suche kann ich genauso gut die CRC in die letzten > Bytes des Flashs schreiben. Wenn du die Berechnung immer auf die ganze Flashgröße anwendest, geht das natürlich (und den Rest mit 0xff füllst). Dann hast du eine implizite Länge, das spart das explizite Notieren der Länge.
Bei den wenigsten Anwendung macht es was aus wen nder µC ein paar Sekunden am Anfang braucht bis er loslegt und das hardcoden der CRC ans Ende des Flashs spart den "Suchcode" im engen Bootloader-Bereich ein (Der CRC-Gen muss eh bei beiden rein). Und beim flashen sind die milllisekunden die das löschen der extra pages braucht auch unerheblich....
Max schrieb: > Und beim flashen sind die > milllisekunden die das löschen der extra pages braucht auch > unerheblich.... Das stimmt wohl. Max schrieb: > (Der CRC-Gen muss eh bei beiden rein). Nicht zwingend.
Oz zy schrieb: > Bei ersterem würde ja der Watchdog helfen, der dann den Speicher wieder > leer macht Nein. Der Watchdog soll nur Hänger lösen, die man bei der Programmierung "vergessen" hat, zu berücksichtigen. Ist die Fehlerursache aber bekannt, kann man sie gezielt lösen. Auch macht der Watchdog keinen "Speicher leer", sondern löst ein CPU-Reset aus. Die CPU vergißt also völlig ihren Kontext und fängt nochmal neu an. Liegt dann der Fehler immer noch vor, landet man in einer Endlosschleife von Watchdog-Resets.
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.