Forum: Mikrocontroller und Digitale Elektronik wie findet ein Flashloader die Prüfsumme?


von eagle user (Gast)


Lesenswert?

Ein uC-Programm sollte vor dem Flashen, nach dem Flashen, nach einem 
Download zwecks Update und nach einem Reset mittels CRC überprüft werden 
(jedenfalls auf einem STM32, der CRC32 in Hardware kann). Dazu muss ein 
Programm auf dem PC das hex-File manipulieren. Alle beteiligten 
Programme müssen sich einig sein, auf welcher Adresse diese Prüfsumme 
steht. Aber nur das uC-Programm selbst kann die auf "natürliche" Art 
ansprechen.

Eine feste Adresse für diverse kleine und große uC wäre nett. Das Ende 
des Flash ist zwar relativ fest, aber dann muss das Image immer die 
volle Größe haben. Am Ende des Programms ist mir viel zu kompliziert. 
Kurz hinter der Vektor Tabelle wäre ein guter Platz und in C leicht 
hinschreibbar. Große STM32 brauchen aber bis zu 2048 Byte für die 
Tabelle, dann liegt die Prüfsumme bei kleinen M0 mitten im nutzbaren 
Flash.

Eine feste Adresse kommt nicht in Frage. Also muss das PC-Programm 
anhand der Daten im hex-File erkennen können, wo es die Prüfsumme hin 
schreiben soll. Dafür braucht man eine feste Adresse...

Mein Plan: im ersten Wort der Vektor Tabelle steht der Stack Pointer. 
Ich lege den Stack immer an den Anfang des RAM und die Größe ist ja 
sowieso willkürlich. Also kann ich in den Bits 3 und 4 (evt. 5) vier 
(acht) verschiedene Plätze für die Prüfsumme kodieren. Als Feigling 
lasse ich Bit 0, 1 und 2 immer auf Null (der Stack ist im Betrieb 8-Byte 
aligned). Praktischerweise stehen diese Bits im allerersten Byte vom 
Image.

Was könnte möglicherweise schief gehen?

von Joe F. (easylife)


Lesenswert?

Wozu benötigt der uC eine abgespeicherte Prüfsumme?
Angenommen, dein uC stellte (z.B. beim booten) eine fehlerhafte 
Prüfsumme fest, was soll dann passieren?

Wenn du sowieso den PC hast, um die Prüfsumme bei den o.g. Gelegenheiten 
zu verifizieren, dann reicht es ja, dass der uC die Prüfsumme berechnen 
und an den PC kommunizieren kann.
Der PC kann die Prüfsumme anhand des HEX files ebenfalls errechnen, und 
prüfen ob beide CRCs identisch sind.
Wenn nicht -> nochmal flashen/updaten etc.

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

eagle user schrieb:
> und nach einem Reset mittels CRC überprüft werden

Das bedeutet, das möglicherweise defekte Programm muss sich selbst 
prüfen?

Wie soll es das können, wenn es defekt ist?

von Steffen R. (steffen_rose)


Lesenswert?

Da das Image jeweils für einen bestimmten Prozessor ist, könnte sie auch 
an einer für den jeweiligen Prozessor günstigen Stelle liegen.

Den beteiligten Programmen müßte man dann natürlich mitteilen für 
welchen Prozessor das Image ist. Zumal auch nicht festzustehen scheint, 
ob auf allen Systemen das gleiche Prüfverfahren zum Einsatz kommt.

Ich habe auch schon gesehen, dass ein freier Eintrag in der Vectortable 
genutzt wird.

von Nop (Gast)


Lesenswert?

eagle user schrieb:

> Eine feste Adresse für diverse kleine und große uC wäre nett.

Mach das doch mit einem generischen Header, in dem Du per ifdefs die 
Adresse je nach Controller definierst.

> Mein Plan: im ersten Wort der Vektor Tabelle steht der Stack Pointer.
> Ich lege den Stack immer an den Anfang des RAM

Da wrd ich nochmal drüber nachdenken, denn der Stack ist absteigend. 
Legst Du also den Stackpointer auf den Beginn des RAM, dann bekommst Du 
bei der ersten Nutzung des Stacks direkt einen Hardfault.

von Nop (Gast)


Lesenswert?

Rufus Τ. F. schrieb:

> Wie soll es das können, wenn es defekt ist?

Es ist theoretisch denkbar, daß es gerade so beschädigt ist, daß es 
trotzdem als OK hochläuft. Beispielsweise, indem die Bits so kippen, daß 
die Prüfroutine übersprungen wird. Das ist aber extrem unwahrscheinlich.

Wenn Änderungen im Code sind, wird das wahrscheinlich einen Absturz 
geben. Dann merkt man, daß etwas verkehrt ist. Viel schlimmer ist es, 
wenn z.B. der Datenbereich beschädigt ist und das Programm zwar läuft, 
aber verkehrt. Diesen Fall erkennt man mittels Püfung der Firmware.

von Peter D. (peda)


Lesenswert?

eagle user schrieb:
> Das Ende
> des Flash ist zwar relativ fest, aber dann muss das Image immer die
> volle Größe haben.

Nö, z.B. Intel-Hex kann auch Lücken haben.
Man muß nur bei der CRC-Berechnung festlegen, daß Lücken dem gelöschten 
Flash (0xFF) entsprechen.

von Nop (Gast)


Lesenswert?

Joe F. schrieb:

> Angenommen, dein uC stellte (z.B. beim booten) eine fehlerhafte
> Prüfsumme fest, was soll dann passieren?

Er sollte z.B. in einer Endlosschleife bleiben und auf jeden Fall nicht 
beginnen, die angeschlossene Anwendung zu steuern. Eine ausgefallene 
Steuerung erkennt man nämlich einfacher als eine fehlerhafte, zumal bei 
vernünftigem Systemdesign auch die Sicherheit profitiert.

von Harry L. (mysth)


Lesenswert?

Man könnte die Position ja "markieren".
Sinngemäß etwa so:
1
const struct checksum {
2
  char marker[] = "/My/Check/sum/";
3
  uint32_t crc32sum = 0;
4
};

Dann kann man im .bin/.hex nach "/My/Check/sum/" suchen und unmittelbar 
darauf folgt die Checksum.

: Bearbeitet durch User
von Joe F. (easylife)


Lesenswert?

Nop schrieb:
> Joe F. schrieb:
>
>> Angenommen, dein uC stellte (z.B. beim booten) eine fehlerhafte
>> Prüfsumme fest, was soll dann passieren?
>
> Er sollte z.B. in einer Endlosschleife bleiben
(...)

Könntest du die Beantwortung dieser Frage bitte dem TO überlassen?

von Nop (Gast)


Lesenswert?

Joe F. schrieb:

> Könntest du die Beantwortung dieser Frage bitte dem TO überlassen?

Das ist hier ein Forum und kein Zweiergespräch per PN oder Email.

von Joe F. (easylife)


Lesenswert?

Harry L. schrieb:
> Dann kann man im .bin/.hex nach "/My/Check/sum/" suchen und unmittelbar
> darauf folgt die Checksum.

Das Problem einer Checksumme im Image ist, sobald man die Checksumme ins 
Image schreibt, stimmt die Checksumme nicht mehr, da die Checksumme das 
Image verändert hat...

von Joe F. (easylife)


Lesenswert?

Nop schrieb:
> Das ist hier ein Forum und kein Zweiergespräch per PN oder Email.

Darum geht es nicht. Ich möchte nur gerne vom TO erfahren, was in dem 
Fall passieren soll anstatt wilder Spekulationen.

von Harry L. (mysth)


Lesenswert?

Joe F. schrieb:
> Das Problem einer Checksumme im Image ist, sobald man die Checksumme ins
> Image schreibt, stimmt die Checksumme nicht mehr, da die Checksumme das
> Image verändert hat...

JA, da war ich wohl ein wenig voreilig ;)

War ein spontaner Gedanke....mea Culpa.

von Nop (Gast)


Lesenswert?

Joe F. schrieb:

> Das Problem einer Checksumme im Image ist, sobald man die Checksumme ins
> Image schreibt, stimmt die Checksumme nicht mehr, da die Checksumme das
> Image verändert hat...

Man kann die x Bytes der Prüfsumme auch beim Berechnen überspringen, 
wenn man rausbekommen hat, wo sie ist, und sie nur nach der Berechnung 
als erwarteten Wert heranziehen. Ob man sie dazu am Anfang, in der Mitte 
oder am Ende speichert, ist egal.

von Hannibal H. Hirnfurz (Gast)


Lesenswert?

Nop schrieb:
> Er sollte z.B. in einer Endlosschleife bleiben und auf jeden Fall nicht
> beginnen, die angeschlossene Anwendung zu steuern.

Wenn das Programm beschädigt ist, ist doch nicht nur das Erkennen einer 
solchen Beschädigung, sondern auch die Reaktion darauf undefiniert ("auf 
jeden Fall")?

von Nop (Gast)


Lesenswert?

Hannibal H. Hirnfurz schrieb:

> Wenn das Programm beschädigt ist, ist doch nicht nur das Erkennen einer
> solchen Beschädigung, sondern auch die Reaktion darauf undefiniert ("auf
> jeden Fall")?

Das ist die Theoretiker-Falle: wenn eine Lösung nicht 100.00% 
wasserdicht ist, dann ist es dasselbe wie wie eine 0%-Lösung.

von Nuger (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> eagle user schrieb:
>> und nach einem Reset mittels CRC überprüft werden
>
> Das bedeutet, das möglicherweise defekte Programm muss sich selbst
> prüfen?
>
> Wie soll es das können, wenn es defekt ist?

Indem man die vorherige Version auf dem µC belässt und diese die Prüfung 
übernimmt. Erst wenn diese erfolgreich erfolgt ist wird der neu 
Bootloader gestartet damit er die andere Firmware startet, schlägt dies 
fehl bzw. kommt es zu Problemen setzt man wieder auf die alte Firmware. 
Natürlich muss man dann mehr Speicher im EEPROM einplanen als bei 
einfachen Lösungen die direkt überschreiben - aber gerade wenn man viele 
Systeme hat die über z.B. über Funk angebunden sind gilt safety first - 
mehrere Tausend Systeme neu zu flashen ist schlichtweg finanziell nicht 
rentabel. Ein µC mit >=2x so viel Speicher ist oftmals kein Problem.

von Nuger (Gast)


Lesenswert?

Was ich noch ganz vergessen habe: Man muss unterschiedliche CRC Polynome 
benutzen bei den einzelnen Prüfungen. Ansonsten können Bitfehler trotz 
mehrmaliger Prüfung durchrutschen.

von Gerd E. (robberknight)


Lesenswert?

Rufus Τ. F. schrieb:
> eagle user schrieb:
>> und nach einem Reset mittels CRC überprüft werden
>
> Das bedeutet, das möglicherweise defekte Programm muss sich selbst
> prüfen?
>
> Wie soll es das können, wenn es defekt ist?

Es könnte z.B. auch sein, daß ein Bootloader die CRC prüft und im Falle 
eines Fehlers dann das defekte Hauptprogramm nicht startet, sondern nur 
im Bootloader-Modus auf ein neues, Prüfsumm-korrektes Programm wartet.

von Gerd E. (robberknight)


Lesenswert?

Nuger schrieb:
> Was ich noch ganz vergessen habe: Man muss unterschiedliche CRC Polynome
> benutzen bei den einzelnen Prüfungen. Ansonsten können Bitfehler trotz
> mehrmaliger Prüfung durchrutschen.

Desto komplexer der Prüfsummen-Algo, desto unwahrscheinlicher wird das. 
Wenn es nicht aufs letzte Byte oder die letzte µs ankommt nehme ich 
normal MD5 statt irgendeinem CRC32.

Im Gegensatz zu CRC32 ist mir bei MD5 noch nie eine Kollision bei meinen 
Firmwares aufgetreten, auch wenn sie natürlich theoretisch möglich wäre.

von temp (Gast)


Lesenswert?

Die Forderung von ganz oben ist nicht nur hypothetisch sondern sehr 
real:
Nennt sich Sicherheitsnorm IEC 60335.

http://www.all-electronics.de/hausgeraete-sicherer-machen/

Die Hersteller der gängigen Controller bieten meistens auch Libs und 
Samplecode für diesen Selbstcheck an. Da gehört der Flash auch dazu.

von Stefan F. (Gast)


Lesenswert?

Der µC könnte beim ersten Start eine Prüfsumme erstellen und in 
irgendeinem nicht flüchtigen Speicher ablegen. Bei allen folgenden 
Starts kann er anhand der Prüfsumme ungewollte Veränderungen am Programm 
erkennen.

Ich finde dieses Verfahren einfacher, als wenn die Prüfsumme von außen 
vorgegeben wird.

Ein Schutz gegen Manipulation ist das aber nicht, denn das manipulierte 
Programm könnte natürlich auch einen manipulierten (oder gar 
unwirksamen) Prüfalgorithmus enthalten.

von Gerd E. (robberknight)


Lesenswert?

Stefan U. schrieb:
> Der µC könnte beim ersten Start eine Prüfsumme erstellen und in
> irgendeinem nicht flüchtigen Speicher ablegen. Bei allen folgenden
> Starts kann er anhand der Prüfsumme ungewollte Veränderungen am Programm
> erkennen.

Das überzeugt mich nicht.

Denn damit erkennst Du keinerlei Übertragungsfehler auf den µC. Einmal 
die JTAG-Pins nicht richtig aufgesetzt, der Testpunkt etwas oxidiert 
etc. und schon wackelt einmal ein Bit. Das dürfte erfahrungsgemäß viel 
öfters auftreten, als daß bei einem ursprünglich korrekt geflashtem µC 
nach einigen Jahren mal ein Bit kippt.

von Stefan F. (Gast)


Lesenswert?

Wenn du eine Prüfsumme an eine variable Adresse im Programmspeicher 
ablegen willst, kannst du eine eindeutige Markierung davor stellen. Zum 
Beispiel "CodeChkSum:xxxx".

Eine so markierte Stelle kann man leicht finden. Du musst dann natürlich 
sicherstellen, dass der String nicht auch noch woanders vor kommt.

von Johannes O. (jojo_2)


Lesenswert?

Stefan U. schrieb:
> Der µC könnte beim ersten Start eine Prüfsumme erstellen und in
> irgendeinem nicht flüchtigen Speicher ablegen. Bei allen folgenden
> Starts kann er anhand der Prüfsumme ungewollte Veränderungen am Programm
> erkennen.

Das würde ich nicht so umsetzen. Eine permanent defekte Speicherzelle 
würde damit nicht auffallen und das Programm zeigt dennoch 
Fehlverhalten.


Gerd E. schrieb:
> Es könnte z.B. auch sein, daß ein Bootloader die CRC prüft und im Falle
> eines Fehlers dann das defekte Hauptprogramm nicht startet, sondern nur
> im Bootloader-Modus auf ein neues, Prüfsumm-korrektes Programm wartet.

So kenne ich das auch. Oftmals sogar mit zwei Images, falls es der 
Speicherplatz zulässt. Dann darf auch beim Update was schieflaufen und 
die Kiste startet dennoch.

Ich entscheide mich lieber dafür, NICHTS zu tun, als ein Programm 
auszuführen dass dann unter Umständen IRGENDWAS macht. Allein schon von 
der Zuverlässigkeit und Sicherheit her ist sowas zwingend notwendig in 
vielen Anwendungen.


Und wie der Loader die Prüfsumme findet: Man sagt es ihm. Beim STM32 
würde ichs so lösen:
- Der Loader hat hardcoded das Ende des Flashs drinstehen. Das ist 
spätestens beim Linken bekannt, da im Linkerskript die Speicherbereiche 
drinstehen. Linker-Konstanten kann man in C verwenden, so kommt die Info 
in den Loader.
- Am Ende des Flashs steht ein Struct. Dieses Struct enthält:
  * Startadresse des Images (ggf. optional)
  * Größe des Images (Größe = 0 => kein Image vorhanden)
  * Prüfsumme des Images
- Fertig.

Ob dazwischen (also zwischen Image und Flashende) "Löcher" sind ist 
egal. Die Struktur am Ende des Flashs wird nicht explizit ins Image 
geschrieben sondern beim Update bzw. bei der Fertigung erstellt.
Ach ja: Beim Update wird auch die Prüfsumme übertragen und mit den 
empfangenen Daten verglichen.

So ähnlich habe ich das bereits mal umgesetzt.

: Bearbeitet durch User
von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Gerd E. schrieb:
> Denn damit erkennst Du keinerlei Übertragungsfehler auf den µC. Einmal
> die JTAG-Pins nicht richtig aufgesetzt, der Testpunkt etwas oxidiert
> etc. und schon wackelt einmal ein Bit. Das dürfte erfahrungsgemäß viel
> öfters auftreten, als daß bei einem ursprünglich korrekt geflashtem µC
> nach einigen Jahren mal ein Bit kippt.

Wenn Du den Flash-Inhalt über JTAG schreibst, kannst Du ihn auch über 
JTAG validieren.

von eagle user (Gast)


Lesenswert?

Joe F. schrieb:
> Wozu benötigt der uC eine abgespeicherte Prüfsumme?

z.B. um bei einem Update das neue Image vorher und nach dem Flashen zu 
testen. Ich finde, eine vom Image getrennte Prüfsumme ist noch 
umständlicher. Die Prüfsumme ist auch nur ein Wort in einem Header mit 
Name, Version, Zeitstempel, Seriennr. und einer Angabe, zu welcher 
Hardware das Programm gehört.

> Angenommen, dein uC stellte (z.B. beim booten) eine fehlerhafte
> Prüfsumme fest, was soll dann passieren?

Rufus Τ. F. schrieb:
> eagle user schrieb:
>> und nach einem Reset mittels CRC überprüft werden
>
> Das bedeutet, das möglicherweise defekte Programm muss sich selbst
> prüfen?

Ein kleiner Teil des Programms muss sich selbst prüfen. Wenn das nicht 
klappt: Endlosschleife + Watchdog. Normal wird anschließend das 
eigentliche Programm geprüft. Bis dahin wird fast keine Hardware 
initialisiert. Wenn das Programm groß genug ist, ist es nochmal 
unterteilt. Die Teile werden getrennt geprüft und sind in gewissen 
Grenzen getrennt lauffähig.


Steffen R. schrieb:
> Da das Image jeweils für einen bestimmten Prozessor ist, könnte
> sie auch
> an einer für den jeweiligen Prozessor günstigen Stelle liegen.
>
> Den beteiligten Programmen müßte man dann natürlich mitteilen für
> welchen Prozessor das Image ist.
Genau das ist mein Problem :)

> Zumal auch nicht festzustehen scheint, ob auf allen Systemen
> das gleiche Prüfverfahren zum Einsatz kommt.
Doch, das ist der Plan.

> Ich habe auch schon gesehen, dass ein freier Eintrag in der Vectortable
> genutzt wird.
So war es bis gestern und jetzt fürchte ich mich, dass genau der Eintrag 
beim nächsten Chip nicht mehr frei ist. Den Stack-Pointer-Eintrag wird 
man wohl eher nicht ändern.


Nop schrieb:
> eagle user schrieb:
>> Mein Plan: im ersten Wort der Vektor Tabelle steht der Stack Pointer.
>> Ich lege den Stack immer an den Anfang des RAM
>
> Da wrd ich nochmal drüber nachdenken, denn der Stack ist absteigend.
> Legst Du also den Stackpointer auf den Beginn des RAM, dann bekommst Du
> bei der ersten Nutzung des Stacks direkt einen Hardfault.
Ach menno, den Stack, nicht den Stackpointer. Den Hardfault gibt's dann, 
wenn der Stack überläuft. Und das ist so dermaßen angenehm, ich weiß 
garnicht, wie man früher ohne ausgekommen ist.


Harry L. schrieb:
> Joe F. schrieb:
>> Das Problem einer Checksumme im Image ist, sobald man die Checksumme ins
>> Image schreibt, stimmt die Checksumme nicht mehr, da die Checksumme das
>> Image verändert hat...
>
> JA, da war ich wohl ein wenig voreilig ;)
>
> War ein spontaner Gedanke....mea Culpa.
Das ist doch das kleinste Problem, die spontanen Gedanken sind hinterher 
oft die besten.


Nuger schrieb:
> Was ich noch ganz vergessen habe: Man muss unterschiedliche CRC
> Polynome
> benutzen bei den einzelnen Prüfungen. Ansonsten können Bitfehler trotz
> mehrmaliger Prüfung durchrutschen.
Naja, dann müsste man aber auch jeden einzelnen Maschinenbefehl prüfen. 
Soviel Sicherheit brauche ich zum Glück nicht.


Stefan U. schrieb:
> Ein Schutz gegen Manipulation ist das aber nicht, denn das manipulierte
> Programm könnte natürlich auch einen manipulierten (oder gar
> unwirksamen) Prüfalgorithmus enthalten.
Ich glaube, das war schon geklärt, dass ein Schutz gegen Manipulation 
mit normalen uC garnicht möglich ist.


Johannes O. schrieb:
> Und wie der Loader die Prüfsumme findet: Man sagt es ihm. Beim STM32
> würde ichs so lösen:
> - Der Loader hat hardcoded das Ende des Flashs drinstehen. Das ist
> spätestens beim Linken bekannt, da im Linkerskript die Speicherbereiche
> drinstehen. Linker-Konstanten kann man in C verwenden, so kommt die Info
> in den Loader.
OK, aber das gilt nicht für die PC-Programme. Die müssen die Metadaten 
im Hex-File "finden". Und gerade die sollen ja universell sein.

von Roland P. (pram)


Lesenswert?

Joe F. schrieb:
>
> Das Problem einer Checksumme im Image ist, sobald man die Checksumme ins
> Image schreibt, stimmt die Checksumme nicht mehr, da die Checksumme das
> Image verändert hat...

Dann ist es ja ganz einfach (sofern man xor verwendet) definiert man 
einfach, dass alle bytes des Flashes in der XOR Summe 0 ergeben müssen.

Bei CRC32 musss man halt so lange Bits kippen, bis 0 raus kommt. Bei 
komplexeren Algorithmen wie MD5/SHA... hat mam aber schlechte Karten

VG Roland

von Andreas M. (amesser)


Lesenswert?

eagle user schrieb:
> Ein uC-Programm sollte vor dem Flashen, nach dem Flashen, nach einem
> Download zwecks Update und nach einem Reset mittels CRC überprüft werden
> (jedenfalls auf einem STM32, der CRC32 in Hardware kann). Dazu muss ein
> Programm auf dem PC das hex-File manipulieren. Alle beteiligten
> Programme müssen sich einig sein, auf welcher Adresse diese Prüfsumme
> steht. Aber nur das uC-Programm selbst kann die auf "natürliche" Art
> ansprechen.

Was genau heist vor und nach dem flashen? wie wird geflasht? JTAG? Im 
Flash abgelegter Bootloader? Wenn Bootloader, der wird ja wohl wissen, 
wo die Vectortabelle des jeweiligen Chips aufhört. Wenn JTAG, wozu 
brauchts da eine Checksumme, ich kann nach dem Flashen per JTAG ja wohl 
Problemlos eine Verifikation mit der Originaldatei anstellen

Was bedeutet Download? Wir da ein extra Stück Code gestartet? Die 
Firmware kann sich ja nicht selbst überschreiben.

Nach dem Reset die CRC von sich selbst zu berechnen ist simpel.

Ein bischen mehr Details zu den Anwendungsfällen wären schon nett.

> volle Größe haben. Am Ende des Programms ist mir viel zu kompliziert.

Drei Zeilen im Linkerscript?

> Kurz hinter der Vektor Tabelle wäre ein guter Platz und in C leicht
> hinschreibbar. Große STM32 brauchen aber bis zu 2048 Byte für die
> Tabelle, dann liegt die Prüfsumme bei kleinen M0 mitten im nutzbaren
> Flash.
>
> Eine feste Adresse kommt nicht in Frage. Also muss das PC-Programm
> anhand der Daten im hex-File erkennen können, wo es die Prüfsumme hin
> schreiben soll. Dafür braucht man eine feste Adresse...

An das Ende der Firmware? Ansonsten nutzt man für sowas normalerweise 
eine Info Struktur irgendwo in der Firmware. Da kann man auch noch mehr 
Informationen hinterlegen. z.B. für den Bootloader, falls es einen gibt.

>
> Mein Plan: im ersten Wort der Vektor Tabelle steht der Stack Pointer.
> Ich lege den Stack immer an den Anfang des RAM und die Größe ist ja
> sowieso willkürlich. Also kann ich in den Bits 3 und 4 (evt. 5) vier
> (acht) verschiedene Plätze für die Prüfsumme kodieren. Als Feigling
> lasse ich Bit 0, 1 und 2 immer auf Null (der Stack ist im Betrieb 8-Byte
> aligned). Praktischerweise stehen diese Bits im allerersten Byte vom
> Image.

Viel zu kompliziert und keiner verstehts. Dann besser ein Cookie in der 
Firmware was die Software Suchen kann. Die Firmware auf dem 
Mikrocontroller weis eh wo alles steht.

von Stefan F. (Gast)


Lesenswert?

>> Der µC könnte beim ersten Start eine Prüfsumme erstellen und in
>> irgendeinem nicht flüchtigen Speicher ablegen.

> Eine permanent defekte Speicherzelle würde damit nicht auffallen
> und das Programm zeigt dennoch Fehlverhalten.

> Das überzeugt mich nicht.
> Denn damit erkennst Du keinerlei Übertragungsfehler auf den µC.

Eine permanent defekte Zelle sowie Übertragungsfehler würden schon 
während des Flashens auffallen, denn natürlich verifiziert man danach 
nochmal.

Es ging doch darum, festzustellen, ob das Programm später im Betrieb 
(unabsichtlich) kaputt gegangen ist.

Die von mir empfohlene Methode wurde in den 90er Jahren von eine Zeit 
lang von vielen Virenscannern verwendet, bis man sich bewusst wurde, 
dass das nicht gegen gezielte Manipulation hilft.

von Nuger (Gast)


Lesenswert?

eagle user schrieb:
> Nuger schrieb:
>> Was ich noch ganz vergessen habe: Man muss unterschiedliche CRC
>> Polynome
>> benutzen bei den einzelnen Prüfungen. Ansonsten können Bitfehler trotz
>> mehrmaliger Prüfung durchrutschen.
> Naja, dann müsste man aber auch jeden einzelnen Maschinenbefehl prüfen.
> Soviel Sicherheit brauche ich zum Glück nicht.

Kostet nichts und schadet nicht. Wenn du durch einen derart absurden 
Fehler 1000 Geräte von Hand flashen musst sind das leichtsam >2000€ an 
Kosten, da stelle ich lieber sicher dass so ein Fehler von vornherein 
nicht passieren kann. Gerade wenn die Tags fest verbaut sind wird das 
erst richtig lustig, da tanzt dein Kunde dann.

von eagle user (Gast)


Lesenswert?

Roland P. schrieb:
> Joe F. schrieb:
>>
>> Das Problem einer Checksumme im Image ist, sobald man die Checksumme ins
>> Image schreibt, stimmt die Checksumme nicht mehr, da die Checksumme das
>> Image verändert hat...
>
> Dann ist es ja ganz einfach (sofern man xor verwendet) definiert man
> einfach, dass alle bytes des Flashes in der XOR Summe 0 ergeben müssen.
>
> Bei CRC32 musss man halt so lange Bits kippen, bis 0 raus kommt. Bei
> komplexeren Algorithmen wie MD5/SHA... hat mam aber schlechte Karten

viel einfacher: man verwendet die CRC-Hardware des STM32 und 
überspringt bei der Berechnung das eine CRC-Wort, auch wenn es mitten 
drin steht.


Andreas M. schrieb:
> Was genau heist vor und nach dem flashen? wie wird geflasht? JTAG? Im
> Flash abgelegter Bootloader?
Z.B. lädt ein Bootloader von irgendwo her ein Update ins RAM. Das muss 
auf jeden Fall geprüft werden. Dann flasht er und prüft das Ergebnis. 
Später prüft er nach einem Reset das Anwendungsprogramm und startet es 
oder wartet auf ein Update.

> Wenn Bootloader, der wird ja wohl wissen, wo die Vectortabelle des
> jeweiligen Chips aufhört. Wenn JTAG, wozu brauchts da eine Checksumme,
> ich kann nach dem Flashen per JTAG ja wohl Problemlos eine
> Verifikation mit der Originaldatei anstellen
Beim ersten Mal wird mit dem eingebauten UART-Bootloader geflasht. Damit 
dauert ein Verify ziemlich lange, der uC selbst kann das viel schneller.

> Was bedeutet Download? Wir da ein extra Stück Code gestartet? Die
> Firmware kann sich ja nicht selbst überschreiben.
Das Anwendungsprogramm geht auf Standby, lädt das neue Image vom 
USB-Stick oder aus dem Internet ins RAM und startet einen Flashloader, 
Der prüft das Image und überschreibt das Anwendungsprogramm. Wenn der uC 
kein Dual Bank Flash hat, kopiert er sich vorher ins RAM.
>
> Nach dem Reset die CRC von sich selbst zu berechnen ist simpel.
>
> Ein bischen mehr Details zu den Anwendungsfällen wären schon nett.
Eigentlich möchte ich eine möglichst universelle Lösung, besonders, was 
die Programme auf dem PC angeht. Die sollen mindestens mit STM32L030 bis 
STM32L476 funktionieren. Zusätzlich soll ein Update über möglichst viele 
Wege möglich sein.

>> volle Größe haben. Am Ende des Programms ist mir viel zu kompliziert.
>
> Drei Zeilen im Linkerscript?
vielleicht, aber am Anfang kann es nicht komplizierter sein.

> Ansonsten nutzt man für sowas normalerweise
> eine Info Struktur irgendwo in der Firmware. Da kann man auch noch mehr
> Informationen hinterlegen. z.B. für den Bootloader, falls es einen gibt.
... und Infos im Klartext für Menschen, die einen hexdump machen. Genau 
so wird es gemacht. Diese Info Struktur hat hier ca. 80 Byte. Die Frage 
ist nur, wie findet man die? Externe Programme haben eben nur die 
hex-Datei und müssen erstmal diese Info lesen, bevor sie wissen, zu 
welchem Chip die Datei gehört und wo die Info steht...

> Viel zu kompliziert und keiner verstehts.
Das bin ich gewohnt ;)
> Dann besser ein Cookie in der Firmware was die Software Suchen kann.
> Die Firmware auf dem Mikrocontroller weis eh wo alles steht.

OK, überredet. "Suchen" heißt ja nicht Byte für Byte, es kommen ja nur 
wenige Adressen in Frage. Man braucht nicht einmal ein extra Cookie, die 
Struktur der Info ist ja konstant und bekannt. Und mit den Info-Daten 
sind jede Menge Plausibilitätschecks möglich, das sollte reichen.

von Chris (Gast)


Lesenswert?

Hi,

ich habe mir dazu auch schonmal Gedanken gemacht. Ich würde ein 
Info-Struct nach der Vectortabelle platzieren. Wenn man es davor 
platziert geht evtl. eine ganze Flash Page dafür drauf, da die Tabelle 
je nach Controller ein bestimmtes Alignment braucht.
Am Ende des Flash geht auch eine ganze Page drauf.

Hat jemand eine Idee, wie man das Verfahren kombinieren kann mit einer 
EEPROM Emulation im Flash bzw. mit sich zur Laufzeit ändernden Daten?
Diese würde ich gerne in eine eigene Section legen hinter der 
Applikation.
Sie sollten nicht zusammen mit der Applikation vor dem Start geprüft 
werden,  da sie sich ja ändern können. (Fürs Prüfen der Daten ist dann 
die Applikation verantwortlich)
D.h. irgendwie muss man die Länge der Firmware ohne die Daten Section 
ermitteln.

Dazu eine Idee?

Lg
Chris

von eagle user (Gast)


Lesenswert?

Chris schrieb:
> Hi,
>
> ich habe mir dazu auch schonmal Gedanken gemacht. Ich würde ein
> Info-Struct nach der Vectortabelle platzieren. Wenn man es davor
> platziert geht evtl. eine ganze Flash Page dafür drauf, da die Tabelle
> je nach Controller ein bestimmtes Alignment braucht.

Außerdem funktioniert es nicht, weil mindestens der Reset Vector auf 0x4 
gebraucht wird. Na gut, der könnte auch am Anfang der Info-Struct 
stehen. Direkt hinter der Vector Table scheint mir der natürlichste 
Platz zu sein.

> Am Ende des Flash geht auch eine ganze Page drauf.
nicht unbedingt, aber man muss sich sehr gut im Linker Script auskennen.

> Hat jemand eine Idee, wie man das Verfahren kombinieren kann mit einer
> EEPROM Emulation im Flash bzw. mit sich zur Laufzeit ändernden Daten?
> Diese würde ich gerne in eine eigene Section legen hinter der
> Applikation.
> D.h. irgendwie muss man die Länge der Firmware ohne die Daten Section
> ermitteln.

Mal angenommen, man braucht kein C++ und mal angenommen, man kommt mit 
dieser Flash-Belegung aus, mit dem EEPROM auf den höchsten Adressen:
 * vector table mit info struct
 * text (das eigentliche Programm)
 * (anonymer Bereich mit Daten zur RAM-Initialisierung)
 * (eine Lücke bis zum nächsten Flash Sektor)
 * EEPROM Emulation
Für das EEPROM braucht man im Linker Script eine eigene section. Damit 
die auf einer bestimmten Adresse landet, braucht man einen Eintrag im 
Abschnitt memory{}.

Wenn man am Ende der text section ein Symbol definiert, hat man die 
erste Adresse der Init-Daten. Jetzt muss man nur noch die Größe des 
Datenbereichs addieren und bekommt die erste Adresse, die nicht mehr 
geprüft werden muss (wenn man bei 0x08000000 anfängt). Wahrscheinlich 
gibt es dieses Symbol schon, weil es von der crt0 gebraucht wird, ebenso 
wie die Anzahl der Datenbytes.

Adresse plus Datenbytes kann man statisch in die init struct eintragen, 
dann weiß jeder, wieviel geprüft werden muss.

von Steffen R. (steffen_rose)


Lesenswert?

eagle user schrieb:
> OK, aber das gilt nicht für die PC-Programme. Die müssen die Metadaten
> im Hex-File "finden". Und gerade die sollen ja universell sein.

Speziell bei solchen universellen Lösungen kommt ein weiteres Problem 
hinzu. Man muss absichern, dass das Image auch wirklich für das 
jeweilige Gerät ist.

Ich spreche das nur an, weil ja genau an dem Merkmal, welches die Geräte 
zur Validierung nutzen auch die PC Programme das Image erkennen können.

von Steffen R. (steffen_rose)


Lesenswert?

eagle user schrieb:
>> Was bedeutet Download? Wir da ein extra Stück Code gestartet? Die
>> Firmware kann sich ja nicht selbst überschreiben.
> Das Anwendungsprogramm geht auf Standby, lädt das neue Image vom
> USB-Stick oder aus dem Internet ins RAM und startet einen Flashloader,
> Der prüft das Image und überschreibt das Anwendungsprogramm. Wenn der uC
> kein Dual Bank Flash hat, kopiert er sich vorher ins RAM.

Die Programme haben maximal RAM Größe? Häufig ist der Flash doch um 
einiges größer.

eagle user schrieb:
>> Ansonsten nutzt man für sowas normalerweise
>> eine Info Struktur irgendwo in der Firmware. Da kann man auch noch mehr
>> Informationen hinterlegen. z.B. für den Bootloader, falls es einen gibt.
> ... und Infos im Klartext für Menschen, die einen hexdump machen. Genau
> so wird es gemacht. Diese Info Struktur hat hier ca. 80 Byte. Die Frage
> ist nur, wie findet man die? Externe Programme haben eben nur die
> hex-Datei und müssen erstmal diese Info lesen, bevor sie wissen, zu
> welchem Chip die Datei gehört und wo die Info steht...

Wie findet ihr die bisher? Im Hexdump können es auch deine Kollegen 
nicht sehen. Im Allgemeinen sind die Klartextinformationen im Binärfile.
Da du die Programme für deine Spezial-Allgemeinlösung eh selbst 
programmieren oder anpassen mußt ist mir unklar, warum du nicht den 
einfacheren Weg gehst und passende Optionen einfügst.
"passend" heißt hier nicht unbedingt Prozessor, könnte auch die Adresse 
sein. Dann brauchst du die Programme nicht mit jedem weiteren Gerät neu 
anzufassen. Und vielleicht wird's ja auch mal eine andere 
Prozessorfamilie?

von eagle user (Gast)


Lesenswert?

Steffen R. schrieb:
> eagle user schrieb:
>>> Was bedeutet Download? Wir da ein extra Stück Code gestartet? Die
>>> Firmware kann sich ja nicht selbst überschreiben.
>> Das Anwendungsprogramm geht auf Standby, lädt das neue Image vom
>> USB-Stick oder aus dem Internet ins RAM und startet einen Flashloader,
>> Der prüft das Image und überschreibt das Anwendungsprogramm. Wenn der uC
>> kein Dual Bank Flash hat, kopiert er sich vorher ins RAM.
>
> Die Programme haben maximal RAM Größe? Häufig ist der Flash doch um
> einiges größer?

Der STM32F205 hat z.B. 128KB RAM und 128KB Flash-Sektoren. Die komplette 
Anwendung ist sowieso in ca. 6 Teile ("Programme") unterteilt. Da 
funktioniert das auf ganz natürlich Art und Weise. Neuere Chips haben 
kleinere Flash-Segmente und mindestens 64 + 16KB RAM, da darf ein 
Programm-Teil eben nur 64KB groß sein. Und: je kleiner, umso besser 
funktioniert ein CRC.

> eagle user schrieb:
>>> Ansonsten nutzt man für sowas normalerweise
>>> eine Info Struktur irgendwo in der Firmware. Da kann man auch noch mehr
>>> Informationen hinterlegen. z.B. für den Bootloader, falls es einen gibt.
>> ... und Infos im Klartext für Menschen, die einen hexdump machen. Genau
>> so wird es gemacht. Diese Info Struktur hat hier ca. 80 Byte. Die Frage
>> ist nur, wie findet man die? Externe Programme haben eben nur die
>> hex-Datei und müssen erstmal diese Info lesen, bevor sie wissen, zu
>> welchem Chip die Datei gehört und wo die Info steht...
>
> Wie findet ihr die bisher?
> Im Hexdump können es auch deine Kollegen nicht sehen.
> Im Allgemeinen sind die Klartextinformationen im Binärfile.
Sind sie auch, mit (sinngemäß) "hexdump -C programm.elf" konnten/können 
Menschen das finden. Programmen musste man es extra per 
Kommandozeile/Mausclick sagen. Ich finde es schöner, wenn alles in einer 
Datei steht. Evt. behält man den Mausclick bei und das Programm 
vergleicht den Wunsch mit der Wirklichkeit in der Datei und im Chip.

> Da du die Programme für deine Spezial-Allgemeinlösung eh selbst
> programmieren oder anpassen mußt ist mir unklar, warum du nicht den
> einfacheren Weg gehst und passende Optionen einfügst.
> "passend" heißt hier nicht unbedingt Prozessor, könnte auch die Adresse
> sein. Dann brauchst du die Programme nicht mit jedem weiteren Gerät neu
> anzufassen.
Brauche ich auch nicht. Erstmal stehen alle benötigten Adressen in der 
Datei und zusätzlich das, was man beim STM32 als Product ID auslesen 
kann. Diese Daten kommen aus einer "imageheader.c".

> Und vielleicht wird's ja auch mal eine andere Prozessorfamilie?
Dann ändert sich ja auf jeden Fall die Flash-Methode, evt. muss ich der 
Hardware sogar einen JTAG-Stecker spendieren, dann kommt es auf solche 
Kleinigkeiten auch nicht mehr an...

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.