STM32FXX Flash Speicher weniger abnutzen

Feb 12, 2020 34 Replies
Jump to replies (34)

Moin,



Für deinen STM32F107 Connectivity Line möchte ich einen nicht flüchtigen Ereigniszähler implementieren und das interne Flash Memory benutzen. Ich benötige lediglich eine Routine welche die Zahl der Ereignisse zurückgibt und eine Andere welche die Anzahl der Ereignisse um 1 erhöht.



Der Chip hat in seinem Flash Speicherseiten mit 2048 bytes die als Ganzes gelöscht werden können (danach sind alle bytes 0xFF) und die mitgelieferte Bibliothek verwendet fürs Schreiben einer Zelle jeweils ein word mit 2 byte.



Für die Speicherung von Parametern gibt es von ST eine EEPROM-Simulation die hier beschrieben ist und etwa 4 byte Flashspeicher bei jedem Schreibzugriff für die Aktualisierung eines Parameters neu beschreibt:



formatting link

Die Anzahl der Ereignisse so hoch dass ich Bedenken hätte dass die Abnutzung des Flashspeichers zu hoch wird (Etwa Faktor 40). Daher die Frage:


- Ist es möglich bei dem Chip einzelne bytes zu schreiben?


- Es es u.U sogar möglich in bereits beschriebene Speicherzellen zu schreiben? z.B. ein bit nach dem Anderen löschen ( 0XFF, 0XFE, 0XFC ... 0X00)?



Kennt jemand den Chip oder die Funktionsweise des internen Flash etwas genauer oder hat einen anderen Tip?



Danke und viele Grüße,



O.J.


Am 12.02.2020 um 14:53 schrieb Ole Jansen:

Das geht, das habe ich für einen Betriebsstundenzähler auch schon gemacht.

Mann kann bei den einfachen STM-Typen jedes Bit einzeln setzen. Löschen kann man jedoch nur die gesamte Page.

Man muss aber aufpassen, falls der Controller eine ECC-Korrektur hat, dann gehts nicht. Dann kann man ein ganzes Wort nur komplett setzten. Wort kann hier auch 64-Bit auf einmal bedeuten. Die schnelleren

32-Bit-Typen haben oft ein 64-Bit-Flash-Interface. Datenblatt befragen!

Die Bits der Flash-Page können je nach Typ nach dem Löschen alle auf 1 oder 0 sein.

Gruß Andreas

Ole Jansen snipped-for-privacy@gmx.de wrote: > Moin,

Bei STM32F1 werden immer Worte geschrieben

0xffff erhaelst Du mit Page Erase. Danach kannst du Bit nur noch nach Null schreiben. Das aber auch in vielen verschiedenen Schreibvorgaenngen .

Was spricht gegen die Art und Weise wie ST das implementier?

Hi Ole,

Kommt eben drauf an, wie oft man solche Schreibvorgänge vor hat.

Eher 4 bei einem 32 Bit µC

klingt logisch

Nein

Das müsste sogar gehen

Ein kleines serielles EEProm. Die sind genau dafür da. Alternativ wäre noch ein Batteriebackup bzw Goldcap und erst ins Flash schreiben, wenn die Spannungsversorgung zusammenbricht.

Marte

Moin,

Am 12.02.2020 um 16:27 schrieb Andreas Fecht:

Vermutlich wird sowas ja öfter verlangt.

Das war meine Hoffnung. Mein erster Versuch mit Sourcery G++ Lite for ARM EABI war allerdings bislang nicht erfolgreich.

Ich verwende die Bibliothek stm32f10x_flash.c und wenn ich die Routinen FLASH_ProgramHalfWord (16bit) oder FLASH_ProgramWord(32bit) auf eine bereits beschriebene Adresse benutze benutze gibt die Funktion einen Fehler zurück und der Speicherinhalt ändert sich nicht.

Weiss ich ehrlich gesagt nicht.

Ich muss gestehen dass ich mich beim Durcharbeiten der Datenblätter etwas schwer tue. Es gibt so viele Varianten von dem Chip. Kann man ihn vielleicht einfach selber fragen?

Die Funktion FLASH_ProgramHalfWord macht jedenfalls grob Folgendes:

// if the previous operation is completed, proceed to program the // new data:

FLASH->CR |= CR_PG_Set;

*(__IO uint16_t*)Address = Data;

//Wait for last operation to be completed status = FLASH_WaitForLastOperation(ProgramTimeout);

// Disable the PG Bit FLASH->CR &= CR_PG_Reset;

Falls es eine ECC Korrektur gibt ist die nicht in der Software.

Mein Muster hier kann 16bit oder 32bit usw. Wenn sich Footprint und Pinning nicht ändern könnte ich jetzt ggf. auch noch einen anderen Typ auswählen. Plan B wäre stumpf für jedes Inkrement 16 Nullen in die Speicherzellen zu schreiben und einen Chip mit entsprechend viel Flash zu nehmen. 40k Flash Speicher für einen "Betriebsstundenzähler" aufzuwenden ist heutzutage ja möglich aber ich fände es trotzdem häßlich.

Hier sind sie 0xFF, also 1. Wobei das auch sein kann dass der Speicher physikalisch anders organisiert ist. War jetzt nicht so wichtig für mein Problem, ich bin bloß neugierig bzw. möchte meinen Code möglichst gut portierbar schreiben.

Viele Grüße,

O.J.

Am 13.02.2020 um 08:54 schrieb Ole Jansen:

So viel Speicher muss man für einen Zähler nicht verschwenden. Bei mir genügen 2-3 Pages. Bei einer Page mit 2048 Bytes kann man bei bitweiser Ansteuerung bis zu 16384 zählen mit nur einmal löschen. Den Übertrag zählt man dann in der nächsten Page. Bei 10k erlaubten Löschvorgängen zerstört sich das Ding nach 163Mio Zählvorgängen.

Wenn man mehrere Pages für das "LSB" verwendet, erhöht sich der Wert bei jeder weiteren Page nochmal um 163Mio.

Wenn's nicht bitweise geht, verringert sich der Wert bei 32-Bit-Worten um den Faktor 32. Das sind bei einer LSB-Page immer noch über 5Mio.

Ich habe das mit dem Keil realisiert und ich programmiere über den HAL. Der ruft aber auch nur die FLASH_Program_xxxxxWord(); Funktion auf.

Getestet mit dem STM32L052 mit 1 bitweisem schreiben, bei einem STM32L433 (mit ECC) nur 64 bitweise.

Was ich auch noch festgestellt habe: Die Schreibadresse kann man nur in Vielfachen der Wortbreite des Flashs angeben. Es sieht so aus als könnte man den Speicher byteweise adressieren, bei krummen Adressen, die nicht auf die Busbreite des Flashinterfaces matchen, hagelt es Fehler.

Gruß Andreas

Am 13.02.2020 um 08:54 schrieb Ole Jansen:

Ja, man kann den Chip auch fragen, in irgendeinem Register steht das. Oder der Programmer zeigt es an.

Aber noch einfacher ist es einfach den Aufrdruck auf dem IC zu lesen. Interessant ist doch maximal der Typ und der Speicher. Die Anzahl der Pins und die Bauform sieht man auch so.

Das Reference-Manual gilt aber für die gesamte Serie, da reicht es erstmal grob den Typ zu wissen.

Wäre bei Flash skeptisch.

Aber Versuch mit einem IC im Dauerbetrieb das Zähler hochlaufen lässt ist jedoch schnell gemacht. Typisch eben den Page-Erase minimieren indem man die unteren Zähler-Bits als Bits in Bytes/Words setzt. Testpin schalten damit man sieht wie lange Operation dauert. Wahrscheinlich wird einem da schon übel. Kältespray/Heissluft drauf.

Der andere Aspekt ist unkontrollierter power down. D.h. der Benutzer schaltet Gerät nicht ordentlich ab. Er kann bei laufendem Betrieb die Batterien herausnehmen oder den Netzstecker ziehen. Für den Fall ist Redundanz zur Fehlerkorrektur sinnvoll. D.h. zwei Zähler, zwei Speicherseiten die wechselweise geschrieben werden. Stimmen die Zähler mit höherem Wert beim power up nicht überein, wird die andere alte, hoffentlich undemolierte Speicherseite als Startwert verwendet.

Ich würde externes serielles FRAM bevorzugen. FRAM schreibt schneller als EEPROM/Flash.

Power down müsste man auf Breadboard per automatischer Testschaltung prüfen. Gemischte HW/SW-Bugs brauchen immer üppige Statistik.

MfG JRD

Benötigst Du für Deinen Ereigniszähler zwingend immer die vollen 256kB des Flashspeichers oder hast Du sogar die Möglichkeit auf eine Variante auszuweichen, die (nur) 64kB Flash und 64kB SRAM hat?

In dem Fall rate ich dringend, den Flash nicht sinnlos kaputtzurösten, sondern die Zählerei im SRAM zu veranstalten und nur alle naslang genau die notwendigen Daten von SRAM in den Flash zu übertragen. Natürlich muß man sich das mit der Stromaufnahme und den Standbyzyklen genau überlegen und auch Vorkehrungen für den Brownout treffen, d. h. vielleicht einen Goldcap verwenden und mittels Betriebsspannungsüberwachung die Daten wegschreiben, bevor dem Chip der Saft ausgeht.

Irgendwelche Magie mit Bitjongliererei macht die Sache nur unnötig kompliziert und fehleranfällig. Wie stellst Du Dir das vor? Die Holzhammermethode, wo man den Speicher nicht in Words aufteilt, sondern einfach einen Bandwurm von Bits mit Nullen füllt, 100 Nullen sind dann 100 Ereignisse, usw.?

Und: 256k Flash für einen Ereigniszähler? Echt jetzt? 2^2097152 Ereignisse? Wieviele Atome in wievielen Universen willst Du denn zählen? Falls Du also nicht den vollen Speicher benötigst, hättest Du immer noch 20 Speicherseiten, über die Du permutieren könntest (wenn sie sich nur als Ganzes löschen lassen).

Auf die Schnelle habe ich im Datenblatt nur was von 10'000 Zyklen minimal gelesen, d. h. 200'000 Ereignisse minimal, wenn man es nur halbwegs schlau anstellt. Etwas schlauer schon wäre der Kompromiß, daß es auf +/-x Ereignisse nicht ankommt, dann könntest Du im SRAM zählen und nur jedes x-te Ereignis im Flash sichern. Dann wären im worst case (jemand zieht den Stecker) eben x-1 Ereignisse vergessen, das Flash würde aber im Gegenzug x*200'000 Zyklen halten.

Ciao, Volker

Hallo Volker,

Ganz so schlimm ist es glücklicherweise nicht.

Ich hole noch mal kurz aus:

Die "EEPROM Simulation" von ST verwendet zwei Speicherseiten und setzt am Anfang der Seiten jeweils Flags welche Seite aktiv ist. Bei den µC der Connectivity Line sind die Seiten 2048 bytes groß, bei anderen Linien können die auch 1024 groß sein. Die Routine schreibt Parameter weg indem eine definierte "virtual adress" (16bit) gefolgt von dem Wert (16bit) an die nächste freie Stelle geschrieben werden.

Wenn die Seite voll ist geht er die Liste mit den ihm bekannten virtuellen Adressen durch, löscht die inaktive Seite und kopiert alle gespeicherten Parameter dorthin und setzt die Seite aktiv. Damit wird einerseits die Abnutzung gleichmäßig verteilt, andererseits kann die Routine Inkonsistenzen erkennen und ggf. alles auf den letzten konsistenten Status zurücksetzen.

Angenommen also ich verwende 4096 byte Flash speicher, schreibe 4 byte pro Update und erlaube 10000 Löschzyklen, dann reichte das für grob 1e7 Ereignisse minus Verluste durch Overhead/Kopieren anderer Parameter. Erwartet werden worst case 4e8 Ereignisse.

Wenn ich die Firmware rausrechne hätte ich noch ca. 40k soda Flash Speicher die ich sinnlos kaputtrösten "darf". Sagen die Auditoren...

Ich bin bei sowas aber aber Ästhet und es könnte sein dass jemand den Quellcode gegenliest der sich auskennt ;-)

Zur Zeit gibt es kein batteriegepuffertes RAM oder externes EEPROM. Verlorene Ereignisse sind eher unerwünscht.

Ein verlorenes Ereignis bei Brownout o.Ä. wäre ggf noch akzeptabel.

Das ist durchaus eine Alternative.

Ich verwende zwei Seiten. Inkremente werden in Word0 gespeichert und ansonsten lösche ein bit nach dem Anderen. Wenn das letzte bit der Seite gelöscht ist übertrage ich die Inkremente auf word0 der anderen Seite analog zur EEPROM Simulation wie oben beschrieben. Bei 10000 Löschzyklen könnte das für 3.2e8 Ereignisse mit zwei Speicherseiten ausreichen.

Denk an Moores Gesetz. Der Markt schreit geradezu nach ZFS und GigE auf embedded Devices für Heimautomation!elf

Alle!

Die Lösung mit den 3.3e8 Könnte ich ggf. noch als ausreichend verkaufen wenn man die 10000 nicht so eng sieht.

Der Code mit der Bitschubserei läuft im Emulator, aber nicht auf dem echten Contoller. Ich vermute stark dass Andreas Recht hat und dass mein µC wegen ECC ö.Ä. keine beschriebenen Worte im Flash überschreiben will oder kann. Was z.B. auch bedeuten würde beim ersten Schreibfehler gar keine weiteren Ereignisse gezählt würden.

Leider bin ich in den Datenblättern und AppNotes immer noch nicht fündig geworden wo das genau beschrieben wird.

Viele Grüße,

O.J.

Am 13.02.2020 um 11:43 schrieb Andreas Fecht:

Die zeigt bei mit folgendes Verhalten: Sie gibt bei mir 0x04 bei Erfolg zurück und 0x02 wenn ich in eine bereits beschriebene Zelle schreiben möchte.

- Dabei ist es egal ob ich in die Zelle den aktuellen Inhalt zurückschreiben möchte oder was Anderes. Ausnahme hiervon: 0xFFFF in eine Zelle schreiben die 0xFFFF enthält gibt 0x04 zurück.

ProgramHalfWord kann bei mir 16bit weise. Weniger geht anscheinend nicht.

OK.

Hab ich noch nicht probiert.

AFAIK ist mein µC Litte Endian.

Was mir aber aufgefallen ist: Bei der ST Link Software *) ändert sich die Reihenfolge der bytes wenn ich die Wortbreite der Anzeige umschalte. So richtig verstanden habe ich den Effekt nicht. Passt die Endianess von der ST-Link Anzeige nicht zu meinem Chip/Adressschema oder sehe ich da einen anderen Effekt?

O.J.

*) Die ist bei mir schon etwas älter, Feb. 2015...

Am 14.02.2020 um 08:49 schrieb Ole Jansen:

Bei mir auch, gerade ausprobiert.

Die Software zeigt den Wert der Speicherstelle an, und je nachdem welche Datenbreite Du eingestellt hast, werden 1, 2 oder 4 Bytes dazu genommen.

Bei der Einstellung 8 bits sieht man IMHO die tatsächliche Speicherbelegung, bei 16 oder 32 bits nicht mehr.

Verstanden. Die EEPROM-Simulation taugt also nicht für Deinen Anwendungsfall bzw. man muß sie erweitern, damit sie nicht nur auf 2*2048 Bytes funktioniert, sondern auf - sagen wir - 16*2048. Das ist dann immer noch nicht ressourcenschonend und dem Problem angemessen, kann aber funktionieren, wenn geringe BOM-Kosten und minimaler Softwareaufwand oberste Priorität haben. Brownout-Handling muß nämlich auch einigermaßen schlau (=zuverlässig) implementiert werden, denn viel Zeit für irgendwelche Datenrettung hat man da typischerweise nicht.

Und das ist auch gut so. Mir hängen die halbgaren, mit geringstmöglichem Aufwand einfach so hingerotzten Lösungen, die unter der Knute irgendwelcher Projektmanager entstehen, nämlich zum Hals raus. Sowas muß mindestens als grob fahrlässige Gedankenlosigkeit bezeichnet werden, möglicherweise aber auch mit wissentlicher "Planned Obsolescence" bzw. dem erhobenen Stinkefinger gegenüber Menschen, die noch ansatzweise soetwas wie Berufsehre im Leib haben.

Mich nervte es damals schon, als der Motorola-Microcontroller im Concert/Chorus-Autoradio meines olympischen Alptraums vergeßlich wurde, nur, weil irgendso ein Arsch bei Blaupunkt es eine gute Idee fand, jede Eingabe sofort synchron aufs Flash zu schreiben, anstatt das erst im RAM zu puffern und nur kurz vor dem Standby zu übertragen.

Nur damit wir uns richtig verstehen: Der Motorcola 68HC705B32 hat 4kB EEPROM und 176 Bytes RAM und in diesem Radio ist für ihn nichts weiter zu tun als Managementaufgaben, weil es parallel dazu noch einen DSP gibt. Die paar abzuspeichernden Parameter Lautstärke, Treble, Bass, Fader, Balance, Kanal, Frequenzband, TP/RDS wird man schon in einer Handvoll Bytes unterbringen können und selbst wer die Möglichkeiten des Soft-Off-Tasters ignoriert, kann bei vernünftiger Nutzung der 4kB Flash schon auch bei nur

1000 möglichen Zyklen musealer Elektronik zuverlässig verhindern, daß die Dinger nach 10 Jahren sterben wie die Fliegen.

Aber nein, lieber zwingt man den User, ein 44-Pin PLCC auszulöten, irgendeinen funktionsgleichen Klon aus China zu orgen und dort die reverseengineerte Software aufzuspielen.

Wer jetzt "alter Käse" ruft, möge sich einfach den Fall mit der Tesla MCU [1] ansehen. Daraus:

"The information logged [on the Flash NAND] is pretty much useless on production vehicles. Unless a developer has a specific reason for enabling it, it does the customer no good. These logs are also rarely downloaded by Tesla. [...] The main issue is that this excessive log file writing causes eMMC flash wear. [...] Tesla selected a flash chip that is unable to handle the constant read/write functions. These chips have since been replaced with a more robust version. [...]".

Das ist ja eigentlich noch frivoler. Geschissen darauf, daß zahlende User sich mit einer potentiellen Reparaturrechnung von fast 2k€ konfrontiert sehen. Und nur, weil irgendeine Coderdrohne #ifdef _DEBUG ... #endif um seinen Loggercode vergessen hat.

Mannomann. Solche Leute sollte man in einen Knast stecken, wo sie *auf* einem Sinclair ZX Spectrum mit 48kB, Gummitastatur und Röhrenglotze Software *für* einen ZX Spectrum mit 48k entwickeln dürfen. Wir wollen mal nicht so sein: Das DivIDE Interface [2] ist erlaubt, ebenso HiSoft Devpac [3] und eine Papierausgabe von Rodnay Zaks "Programming the Z80" [3].

Nicht, daß wir Ärger mit irgendwelchen Menschenrechtsaktivisten kriegen.

Ciao, Volker

[1]
formatting link
formatting link
formatting link
formatting link

Ich habe lange mit AT45DB041D (atmel) gearbeitet. Eines ist extrem wichtig: Nach jedem Schreiben in eine Page muß unbedingt pauschal ein 'AUTO PAGE REWRITE' gemacht werden.

Kollegen von mir machten das nicht. Und beim Kunden haben nach wenigen Wochen alle diese Flash-Speicher versagt und alle Anlagen blieben stehen.

Am 14.02.2020 um 10:30 schrieb Volker Bartheld:

Genau. Durch kleien Änderungen könnte man x Seiten verwenden. Die Abnutzung verringerte sich entsprechend.

Es gibt keine Software On/Off. Ein/Ausschalten geschieht über Betriebsspannungsunterbrechung. Ob die Zeit zwischen der Unterbrechung der Spannungszufuhr und Brownout ausreicht um das Flash zu updaten habe ich noch nicht erforscht. Ausserdem gibt es noch folgendes Problem: Wenn der Watchdog einen Reset auslöst verliere ich Ereignisse.

Ich glaube ich erinnere mich, darüber hattest Du schon mal was geschrieben ;-)

Verbuchen wir unter Training, ja?

Dabei ist ihre Software neben der Marke das größte Asset von der Firma. Mit ihrer Hardware dürftem die kein Geld verdienen.

Solange sie nicht bei Programmieren vergessen die richtigen Fuse Bits zu setzen...

Die sind nicht so schlimm wie beleidigte TESLA-Fanboys. Glaube ich...

O.J.

Am 12.02.2020 um 14:53 schrieb Ole Jansen:

Wie wäre es mit einer Uhr (RTC mit Batterie), und Speicherung des Zählers im CMOS RAM? Dann wird das Speichern nur durch die Lebensdauer der Batterie begrenzt.

DoDi

Am 14.02.2020 um 09:33 schrieb Thorsten Böttcher:

Also die "physische" ?

Da zeigt er dann wohl "Übersetzung" nach Little Endian an. Was dann dem entspricht was die Routinen in meinem Code lesen und schreiben.

Ähh, ich glaube jetzt habe ich es verstanden.

O.J.

Am 14.02.20 um 13:45 schrieb Ole Jansen:

[Tesla NAND Problem]

Na ja, s*it happens. Peinlich ist es jedenfalls.

formatting link
Hanno

Am 14.02.2020 um 13:06 schrieb Helmut Schellong:

Ich auch, allerdings mit der großen Version, AT45DB641. Der Baustein, bzw. der Nachfolger wird immer noch verbaut.

Das steht aber so nicht im Datenblatt, und meine Erfahrung sagt das gleiche. Wenn Daten in zufälliger Reihenfolge, in einem Sektor verteilt geschrieben werden, soll ca. alle 10000 page erase/programm Operationen ein Auto Page Rewrite ausgeführt werden. Beim aktuellen Baustein sind es sogar 50000.

Mache ich auch nicht.

Früher hab ich mitgezählt, und wenn die Zahl erreicht war, hab ich den Speicher beim Einschalten komplett aufgefrischt. Mittlerweile lass ich das weg. Datenverlust ist mir bis jetzt keiner gemeldet worden. Und es kommen teilweise Geräte zur Überprüfung/Reparatur*, die älter als

10 Jahre sind.

*Aus anderen Gründen, meistens mechanische Schäden.

Am 14.02.2020 um 14:23 schrieb Hanno Foest:

Aktuell.

OK. Es ist also bei Model3 theoretisch denkbar dass der Bruttoverkaufserlös BOM und Montage abdeckt. Vielleicht hilft ja die neue Fabrik im "Billiglohnland" D :-P

BTW: Du kennst die üblicherweise als "ausreichend" angesehenen Margen im Fahrzeugbau zur Deckung von F&E, Compliance, Wasserkopf, Dividende, Vertrieb und Marketing usw. ?

O.J.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required