Forum: Mikrocontroller und Digitale Elektronik ST-Link Utility: Was kann beim lesen/schreiben schiefgehen?


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,

ich habe vor einiger Zeit einen binären Software-Stand aus einem selbst 
programmierten STM32F446RE "gesichert" (zu den Anführungszeichen 
später). Ich wollte sichergehen, dass ich die Firmware-Version, die seit 
Monaten zuverlässig läuft, jederzeit wieder zurückspielen können würde.

Dazu habe ich mit dem ST-Link-Utility und meinem ST-Link V2/isol den 
Speicher ausgelesen und als Intel/Hex gespeichert. 
Speicher-/Ausleseschutz habe ich nicht implementiert.

Jetzt wollte ich heute morgen den alten Stand wieder zurückspielen - 
aber es geht nichts. Das ist eine blöde Fehlerbeschreibung, aber mehr 
sehe ich gerade auch nicht. Das Display bleibt leer und das "Core Panel" 
im ST-Link-Utility sagt mir "Unable to run application" und ich sehe 
gerade auch nicht, wo ich mit der Fehlersuche anfangen soll.

Ich bin sicher, dass das HEX wirklich von exakt dieser Hardware stammt. 
Ein anderes HEX-File lässt sich problemlos flashen und funktioniert wie 
erwartet.

Die "gesicherte" Hex-Datei ist auch gefühlt ein wenig zu klein und ich 
finde auch keine Revisions-Strings darin. Die alte Hex-Datei noch einmal 
zu retten ist also erst einmal illusorisch. Es bleibt also erst einmal 
nur sicherzustellen, dass das Problem nie wieder passiert und evtl. das 
alte HEX im Versionsverwaltungssystem wiederzufinden.

Deswegen zwei Fragen:

a) Was kann beim Auslesen eines nicht-schreibgeschützten STM32 mit dem 
ST-Link Utility schiefgehen und wie kann ich sicherstellen, dass nichts 
schiefgegangen ist?

b) Wenn ich eine HEX-Datei flashe und wieder auslese, unterscheiden sich 
die Dateien binär. Es wird also wohl eine andere Kodierung verwendet. 
Die geschriebenen HEX-Datei haben 32 Nibbles Nutzlänge, die gelesenen 
64. Kann ich diese Formate mit irgendeinem fertigen Werkzeug ineinander 
konvertieren, um einen Binärvergleich auf den Dateianfang machen zu 
können, oder ist das hoffnungslos?

Nachtrag: Die zweite Frage hat sich soeben erledigt und damit das 
größere Problem. Ich war schlau genug, die Revisionsnummer, die beim 
Start angezeigt wird, als Dateinamen zu nutzen.

: Bearbeitet durch User
von Thomas Z. (usbman)


Lesenswert?

Wir hatten das hier erst vor kurzem. Ich benutze hex2bin um den 
Vergleich auf binär Ebene zu machen. Du kannst ja vermutlich nicht die 
Recordlänge beim zurücklesen einstellen.

https://sourceforge.net/projects/hex2bin/

Beitrag "Problem,ATmeg1284p brennen auslesen und erneut das neue hex-File in einen andern ATmega1284p brennen"

von A. B. (Gast)


Lesenswert?

Walter T. schrieb:
> a)
Ganz schlechte Idee ... Dazu müsste man den gesamten Flash inkl. 
OTP-Bereich und Option-Bytes auslesen. Die kann man aber NICHT mehr 
einfach zurückschreiben. Man sichert die Sourcen, Entwicklungsumgebung 
und die erzeugten Hex-Dateien.
Wer das nicht macht, hat früher oder später halt ein Problem -> Selbst 
schuld.

> b)
Mit objcopy nach 'binary' ... Oder nach srec mit '--srec-len=...', die 
S1/2/3-Formate haben den Vorteil, dass stets die komplette absolute 
Adresse drin steht, was bei Intel-HEX nicht der Fall ist.

von Walter T. (nicolas)


Lesenswert?

Thomas Z. schrieb:
> https://sourceforge.net/projects/hex2bin/

A. B. schrieb:
> Mit objcopy nach 'binary' ... Oder nach srec mit '--srec-len=...', die
> S1/2/3-Formate haben den Vorteil, dass stets die komplette absolute
> Adresse drin steht

Danke für den Hinweis. Damit lässt sich zumindest prüfen, ob ich mich 
bei der Revisionsnummer nicht vertippt habe.

Dass mit dem Anfang des HEX-Files (bei dem ja wahrscheinlich das Ende 
fehlt) auch dem Anfang des Binärfiles vorhanden ist, bleibt wohl nur zu 
hoffen. Wenn ich das richtig verstanden habe, müssen bei HEX ja die 
Blöcke nicht aufsteigend vorhanden sein.

A. B. schrieb:
> Dazu müsste man den gesamten Flash inkl.
> OTP-Bereich und Option-Bytes auslesen. Die kann man aber NICHT mehr
> einfach zurückschreiben.

Option Bytes und OTP nutze ich momentan nicht. Die Einschränkung sollte 
man also im Hinterkopf behalten, spielt aber momentan wohl keine Rolle.

: Bearbeitet durch User
von Axel S. (a-za-z0-9)


Lesenswert?

Walter T. schrieb:
> a) Was kann beim Auslesen eines nicht-schreibgeschützten STM32 mit dem
> ST-Link Utility schiefgehen

Eigentlich nicht. Aber der Teufel ist ein Eichhörnchen ...

> und wie kann ich sicherstellen, dass nichts
> schiefgegangen ist?

Wie bei jedem Backup. Man versucht, es sofort zu restoren.
Am besten auf ein blankes Target.

> b) Wenn ich eine HEX-Datei flashe und wieder auslese, unterscheiden sich
> die Dateien binär. Es wird also wohl eine andere Kodierung verwendet.

Kodierung ist der falsche Begriff. Recordlänge würde passen. Aber auch 
dann gibt es natürlich noch Möglichkeiten, wie z.B. die Startadresse 
verschieden zu nehmen. Und zu guter Letzt gibt es auch die Möglichkeit, 
daß der Intel-Hex Schreiber Blödsinn macht, z.B. die Prüfsumme falsch 
berechnet (hatten wir letztens erst).

von Walter T. (nicolas)


Lesenswert?

Axel S. schrieb:
> Eigentlich nicht. Aber der Teufel ist ein Eichhörnchen ...

Okay, Eichhörnchen gehören zu den Dingen, die ich in der Werkstatt 
ausschließen kann. Die Viecher sind zumindest hier in der Gegend scheu.

Einen Wackelkontakt kann ich nicht 100%ig ausschließen. Nur zu 99%, weil 
ich das selbe Kabel jetzt seit 2 Jahren nutze. (Auf der USB-Seite sieht 
es etwas schlechter aus. Mein alter Laptop hatte eine wacklige 
USB-Buchse.) Aber hätte dann das ST-Link-Ultility Erfolg vermeldet? 
Hätte ein "Compare device memory with [hex]" nicht einen Fehler melden 
müssen? Oder kann man da irgendetwas falsch einstellen?

Fakt ist: Das ausgelesene HEX hat nur 60 kiB, das Original muss damals 
ca. 480 kiB gehabt haben. Das ist mir leider erst heute aufgefallen. Und 
das macht mich nervös.

Edit: Die Versionierungs-Strategie werde ich wohl auch anpassen. Bislang 
habe ich nur Binaries ausgewählter Revisionen versioniert, aber welche 
Revision auf einer Hardware tatsächlich lange läuft, stellt sich ja 
immer erst im Nachhinein heraus.

: Bearbeitet durch User
von A. B. (Gast)


Lesenswert?

Walter T. schrieb:
> Fakt ist: Das ausgelesene HEX hat nur 60 kiB, das Original muss damals
> ca. 480 kiB gehabt haben. Das ist mir leider erst heute aufgefallen. Und
> das macht mich nervös.

Der F446RE hat 512 kByte Flash, also muss das HEX-File etwas über 1MByte 
groß sein. Das STLink-Utility kann ja nicht wissen, welche Bereiche 
tatsächlich genutzt bzw. interessant sind, also bleibt nur ein 
komplettes Auslesen von A bis Z ... Und eine Kompression gibt's bei 
Intel-HEX nicht.

von Walter T. (nicolas)


Lesenswert?

Auslesen wird es wohl komplett müssen. Und dann am Ende wohl den großen 
0xFF-Block weglöschen. Wenn vor dem Schreiben ein Chip-Erase gemacht 
wird, steht dann wieder das Gleiche im Flash.

So mein naiver Denkansatz, warum alle ausgelesenen HEXen kleiner als 
2x512 kiB+Prüfsummen sind.

von Bauform B. (bauformb)


Lesenswert?

Walter T. schrieb:
> Einen Wackelkontakt kann ich nicht 100%ig ausschließen. Nur zu 99%, weil
> ich das selbe Kabel jetzt seit 2 Jahren nutze. (Auf der USB-Seite sieht
> es etwas schlechter aus. Mein alter Laptop hatte eine wacklige
> USB-Buchse.) Aber hätte dann das ST-Link-Ultility Erfolg vermeldet?
> Hätte ein "Compare device memory with [hex]" nicht einen Fehler melden
> müssen?

Ja und nein. Ein Ausleseprogramm muss natürlich einen Wackelkontakt 
melden, sonst hätte es kein Ausleseprogramm werden dürfen. Allerdings 
sehen alle Dialogboxen gleich aus und wer liest schon das 
Kleingedruckte...

Beim Compare finde ich das Verhalten vernünftig. Normalerweise steht das 
gültige Original ja in der Datei und man vergleicht, weil man dem Flash 
oder dem Programmiergerät nicht traut. Insofern interessiert sich 
niemand für den Flash-Inhalt jenseits vom Dateiende. Normalerweise 
möchte man in der Datei auch keine unbenutzten FF speichern.

Walter T. schrieb:
> Es bleibt also erst einmal nur sicherzustellen,
> dass das Problem nie wieder passiert
>
> wie kann ich sicherstellen, dass nichts schiefgegangen ist?

Wie gesagt: das Original ist die Datei, nicht der Flash-Inhalt. Wenn man 
dann ausliest und vergleicht, fallen Fehler eher auf und lassen sicher 
leichter eingrenzen. Bei einzelnen falschen Bytes kann man z.B. mit 
einem Debugger nachschauen.

Beim STM32 bietet es sich an, die CRC-Hardware für Prüfsummen zu 
verwenden. Man braucht beim make ein Tool, das die Prüfsumme(n) in die 
Hex-Datei schreibt. Damit kann man die ausgelesene und die 
Original-Datei auf dem PC prüfen und das uC-Programm kann sich selbst 
prüfen.

> Ich war schlau genug, die Revisionsnummer, die beim
> Start angezeigt wird, als Dateinamen zu nutzen.

In diesem Fall war das wohl vorteilhaft, aber im Allgemeinen sind Namen 
Schall und Rauch. Nur der Zeitstempel des Dateisystems ist noch 
vergänglicher. Ich schreibe den Revisionsstand, Start- und End-Adressen, 
einen Zeitstempel u.ä. zusammen mit der Prüfsumme in die Hex-Datei.

von Walter T. (nicolas)


Lesenswert?

Bauform B. schrieb:
> Ich schreibe den Revisionsstand, Start- und End-Adressen,
> einen Zeitstempel u.ä. zusammen mit der Prüfsumme in die Hex-Datei.

Bis auf die Prüfsumme mache ich das auch. Die waren nur nicht in den 
ausgelesenen 60 kiB dabei.

Wie wird das mit der Prüfsumme gemacht? Einmal CRC32 über den ganzen 
Flash-Adressbereich? Und wie kommt die Prüfsumme ins HEX?

von Bauform B. (bauformb)


Lesenswert?

Walter T. schrieb:
> Bauform B. schrieb:
>> Ich schreibe den Revisionsstand, Start- und End-Adressen,
>> einen Zeitstempel u.ä. zusammen mit der Prüfsumme in die Hex-Datei.
>
> Bis auf die Prüfsumme mache ich das auch. Die waren nur nicht in den
> ausgelesenen 60 kiB dabei.

Solche Info gehört natürlich auf eine feste Adresse ganz am Anfang. Beim 
Cortex-M mit VTOR geht das ab 0x008, oder 0x010, falls man gleich beim 
Start einen Hard Fault erwartet ;)

> Wie wird das mit der Prüfsumme gemacht? Einmal CRC32 über den ganzen
> Flash-Adressbereich?

Je nach persönlichem Sicherheitsbedürfnis, über den ganzen Bereich bis 
hin zu je eine pro Flash-Sektor. Die Prüfsumme steht auf einer festen 
Adresse und die 4 Bytes werden bei der Berechnung übersprungen. Die 
eigentliche CRC-Berechnung hab' ich hier geklaut:
http://zorc.breitbandkatze.de/crc.html

> Und wie kommt die Prüfsumme ins HEX?

Also, ja, das ist eine dumme Geschichte. Ich neige dazu, für solche 
Sachen ein C-Programm zu schreiben, wenn ich nicht sofort etwas fertiges 
finde.

von W.S. (Gast)


Lesenswert?

Walter T. schrieb:
> Wie wird das mit der Prüfsumme gemacht? Einmal CRC32 über den ganzen
> Flash-Adressbereich? Und wie kommt die Prüfsumme ins HEX?

Mal das Dateiformat für .hex Dateien nachzulesen würde helfen. Also, 
jede Zeile enthält eine 8 Bit Prüfsumme über alle Zeichen in der Zeile 
(Modulo 256). Das ist keine starke Prüfsumme wie z.B. Adler32 oder so, 
aber es reicht normalerweise aus.

Ebenso wichtig ist die Auswahl der Blocktypen. Habe selber schon Klagen 
gehört, wonach Leute mit meinem Brennprogramm nicht zu Potte gekommen 
sind, weil sie den GCC benutzen und dieser (zumindest bei ihnen) den 
Blocktyp 3 benutzt. Das ist der für den 8086 (CS:IP). Für 32 Bit Targets 
ist der Blocktyp 4 vorgesehen.

Was mich wundert, ist daß hier Leute schreiben, daß sie in eine .hex 
Datei Zusatzinformationen hineinschreiben. Normalerweise macht man sowas 
nicht, weil es für sowas keinen standardmäßigen Blocktyp gibt. Und 
einfach Klartext nach dem Endeblock (Typ 1 = End of File) anfügen ist 
mMn ne Unsauberkeit.

W.S.

von Bauform B. (bauformb)


Lesenswert?

W.S. schrieb:
> Was mich wundert, ist daß hier Leute schreiben, daß sie in eine .hex
> Datei Zusatzinformationen hineinschreiben. Normalerweise macht man sowas
> nicht, weil es für sowas keinen standardmäßigen Blocktyp gibt. Und
> einfach Klartext nach dem Endeblock (Typ 1 = End of File) anfügen ist
> mMn ne Unsauberkeit.

Leute? Ein einzelner Chaot. Hineinschreiben? Ja, und zwar mitten rein. 
Zusatzinformationen? Die Revision kann man auch im Quelltext 
unterbringen, das Build-Datum nicht ganz so einfach, aber die Prüfsumme? 
Bring das mal dem Linker bei... Eine .hex Datei? Das ist eine 
HEX-Datei, aber eine HEX-Datei kann auch eine .s19 Datei sein. Das 
srecord Format kennt keine Blocktypen und man braucht auch keine. Die 
Prüfsumme ist ein 32-Bit-Datenwort wie jedes andere. Die taucht im 
uC-Programm als Teil einer struct auf.

Nach dem Endeblock Angehängtes könnte als Kommentar interpretiert 
werden, bei Intel weiß man das ja nie so genau. Aber Klartext ist für 
Menschen, das ist optional. Erstmal brauchen wir etwas für die 
Maschinen.

von W.S. (Gast)


Lesenswert?

Bauform B. schrieb:
> Das
> srecord Format kennt keine Blocktypen und man braucht auch keine.

Auch das Motorola-Format kennt Blocktypen und ne Prüfsumme am 
Zeilenende. Schau dir mal sowas selber an. Allerdings ist bei Motorola 
kein CS:IP Typ dabei.

W.S.

von Mike R. (thesealion)


Lesenswert?

Walter T. schrieb:
> Dazu habe ich mit dem ST-Link-Utility und meinem ST-Link V2/isol den
> Speicher ausgelesen und als Intel/Hex gespeichert.
> Speicher-/Ausleseschutz habe ich nicht implementiert.

Wenn du einfach nur auf lesen gedrückt und dann die ausgelesenen Daten 
gespeichert hast, dann kann ich dir sagen was schief gegangen ist.

Das ST Link Utility liest normalerweise NICHT den kompletten Flash 
sondern nur einen kleinen Teil aus. Wenn man alles lesen will muss man 
manuell bei Size einstellen wieviel er lesen soll.
Und der Speichern Befehl schreibt nur die gelesenen Daten in eine Datei.

von Bauform B. (bauformb)


Lesenswert?

Mike R. schrieb:
> Das ST Link Utility liest normalerweise NICHT den kompletten Flash
> sondern nur einen kleinen Teil aus.

Sag' bitte, dass das ein Scherz war. Das Programm ist zwar schon älter, 
aber doch nicht "640K ought to be enough for anyone" alt? Oder ist das 
so eine kastrierte Trial-Version? Offiziell soll man es ja nicht mehr 
benutzen, weil CubeMX jetzt alles kann. Ist das da dann auch so?

von Walter T. (nicolas)


Lesenswert?

Mike R. schrieb:
> Das ST Link Utility liest normalerweise NICHT den kompletten Flash
> sondern nur einen kleinen Teil aus. Wenn man alles lesen will muss man
> manuell bei Size einstellen wieviel er lesen soll.

Okay. Das kann ich bestätigen. Wenn kein Vergleichs-HEX geladen ist und 
nichts verstellt wird, lädt er immer 60 kiB. Das ist übel, da 
kontraintuitiv.

Setze ich manuell die Größe auf 0x80000 Bytes, wird alles gelesen.

Version 4.4.0

Danke für die Erklärung!

Nachtrag: In der Doku wird das mehr angedeutet als beschrieben. "Save 
as... Saves the content of the memory panel into a binary, Intel Hex or 
Motorola
S-record"

Bei den Commandozeilenoptionen gibt es dann noch -dump für den ganzen 
Flash.

: Bearbeitet durch User
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.