Forum: Mikrocontroller und Digitale Elektronik ATmega Bootloader - Verhalten bei Abbruch/Stromausfall


von Oz z. (ozzy)


Lesenswert?

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

von bal (Gast)


Lesenswert?

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.

von matrixstorm (Gast)


Lesenswert?

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

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

Versorge das Target per Usb, dann ist Stromausfall egal.
Falls der Rechner beim Flashen explodiert, evtl. nochmal von anderem 
Rechner aus flashen.

von Oz z. (ozzy)


Lesenswert?

Moin, danke für die Hinweise. Dann werde ich das ganze noch mal um ein 
Verify erweitern...

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

Mit avrdude als Programmiersoftware wird das Geschriebene automatisch 
zurückgelesen und überprüft.

von Oz z. (ozzy)


Lesenswert?

@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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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).

von Oz z. (ozzy)


Lesenswert?

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

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

CRC stellt die Integrität der übertragenen Daten sicher. Nur weil das 
Flashen funktioniert, heisst das noch nicht, dass die Daten korrekt 
übertragen wurden.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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).

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

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.

von Simon B. (nomis)


Lesenswert?

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

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Jay (Gast)


Lesenswert?

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.

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

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 ;)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Max (Gast)


Lesenswert?

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....

von Kan a. (Firma: Basta) (kanasta)


Lesenswert?

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.

von Jay (Gast)


Lesenswert?

Kan asta schrieb:

> Nicht zwingend.
Für das bitte etwas näher aus...

von Peter D. (peda)


Lesenswert?

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
Noch kein Account? Hier anmelden.