Häufiges Schreiben in den nichtflüchtigen Speicher

Ich entwerfe ein Gerät, das seine physische Position automatisch anpasst, wenn sich die Temperatur ändert. Wenn das Gerät ausgeschaltet oder die Stromversorgung unterbrochen wird, muss sich das Gerät an seine letzte Temperatur und Position erinnern. Ich kann diese Werte im EEPROM speichern, aber das Problem ist, dass sich Position und Temperatur sehr schnell ändern können. Wenn ich die Temperatur und Position nach jeder Änderung in das EEPROM schreiben würde, würde dies (1) die Firmware etwas verlangsamen und (2) wahrscheinlich das EEPROM nach ein oder zwei Jahren zerstören. So wie ich das sehe, habe ich folgende Möglichkeiten...

1) Verwenden Sie einen Kondensator / eine Batterie, um das Gerät nach einem Stromausfall für kurze Zeit mit Strom zu versorgen, damit ich die Werte nur zu diesem Zeitpunkt in das EEPROM schreiben kann. Ich mag das nicht, weil das Board irgendwie machthungrig ist und dies eine große Obergrenze erfordern würde. Und ich habe nicht viel freien Speicherplatz. Und ich möchte nicht die zusätzlichen Kosten für eine Batterie und einen Batteriehalter / oder eine große Kappe.

2) Verwenden Sie F-RAM anstelle von EEPROM, damit ich Billionen Male darauf schreiben kann, ohne es zu verschleißen. Ich mag diese Option nicht, weil FRAM um einiges teurer ist als EEPROM und dies für ein Produktionsprodukt ist (nicht nur für eines).

3) Schreiben Sie die Position und Temperatur nur alle 5 Minuten oder so. Auf diese Weise habe ich immer eine ziemlich aktuelle Position/Temperatur aufgezeichnet, aber ich schreibe nicht jede Sekunde, damit mein Programm nicht verlangsamt wird und das EEPROM nicht so schnell stirbt. Dies scheint meine beste Option zu sein.

Hat sonst noch jemand Vorschläge, an die ich nicht denke?

Nur eine Frage. Wenn das Gerät seine physische Position automatisch anpasst, warum müssen Sie sich dann an die letzte Temperatur erinnern? Wenn Sie das Gerät wieder einschalten, aktualisiert es die Temperatur nicht und passt seine Position nicht an?
Ich stimme Daniel zu. Was ist, wenn Sie das Gerät ausschalten und sich die Umgebungstemperatur drastisch ändert? Wenn Sie beim Einschalten die zuletzt gespeicherte Temperatur / Position verwendet haben, wären Sie sowieso an der falschen Stelle, und das Gerät würde sich trotzdem bewegen. Gibt es eine weitere Anforderung, die in Ihrer Frage nicht aufgeführt ist?
Was ist die EEPROM-Spezifikation - wie viele Schreibzyklen?

Antworten (5)

Was Sie brauchen, ist eine Technik namens Wear Leveling . Es schreibt Ihre Daten nicht jedes Mal an die gleiche Stelle im EEPROM, sondern verwendet einen Algorithmus, um verschiedene Stellen zu verwenden. Ich habe über komplexe Wear-Leveling-Algorithmen gelesen, aber ich wüsste nicht, warum die folgende einfache Methode nicht funktionieren würde.

Fügen Sie Ihren Daten einen 24-Bit-Zähler hinzu, sodass Ihr Datenblock beispielsweise 8 Bytes lang ist. Seiten auf einem 24AA64 sind 32 Bytes lang, ein 64-KB-EEPROM enthält also 256 Seiten. Aus dem Datenblatt:

"Beim Schreiben von weniger als 32 Bytes werden die Daten im Rest der Seite zusammen mit den zu schreibenden Datenbytes aktualisiert. Dadurch wird die gesamte Seite gezwungen, einen Schreibzyklus zu überstehen, aus diesem Grund wird die Dauer pro Seite angegeben."

Daher ist es nicht sinnvoll, Datenblöcke zu verwenden, die kleiner als eine 32-Byte-Seite sind.

Sehen Sie sich den Zähler der ersten Seite an. Wenn es Null ist, haben Sie die maximale Anzahl von Schreibzyklen für diese Seite verwendet, also gehen Sie zur nächsten Seite und überprüfen diesen Zähler. Wiederholen Sie dies, bis Sie einen Zähler > Null finden. Das ist die Seite, die Sie gerade verwenden. Die EEPROMs von Microchip haben eine Lebensdauer von 1 Million Zyklen, die Sie mit dem angegebenen Beispiel von maximal 32 Bytes pro Block in einem 64-KB-EEPROM auf 256 Millionen erhöhen können. Das sollte ausreichen, um Ihr Produkt zu überdauern: 40 Jahre, wenn Sie alle 5 Sekunden (!) einmal schreiben.

Sie sollten Ihr EEPROM bei der ersten Verwendung initialisieren. Woher weißt du, wann das ist. Verwenden Sie die letzte Seite, um bei der Initialisierung eine eindeutige Signatur zu schreiben. Überprüfen Sie bei jedem Einschalten, ob die Signatur vorhanden ist. Ist dies nicht der Fall, muss das Gerät initialisiert werden. Sie können den Zähler in jeder Seite mit 0xF4240 (für 1 Million) voreinstellen oder alles auf 0xFF löschen und die 0xF4240 schreiben, wenn Sie die Seite zum ersten Mal verwenden.
Das Initialisieren eines EEPROM ist erforderlich, weil manchmal im Produktions-/Testprozess ein bestimmtes Muster darauf geschrieben wird.

Bearbeiten
Das Wear Leveling sollte Ihre Probleme lösen, aber ich möchte noch die Kondensatorlösung kommentieren. Sie sagen, die Platine ist ziemlich stromhungrig, aber vielleicht können Sie die Stromversorgung des Mikrocontrollers / EEPROM mit einer Diode vom Rest der Platine trennen. Sie benötigen also wahrscheinlich nur wenige mA, wenn die Hauptstromversorgung unterbrochen ist. Der 24AA64 schreibt eine Seite in weniger als 5 ms, dann bei 10 mA und einem zulässigen Spannungsabfall von 100 mV, den Sie benötigen

C = ich t Δ v = 10 m EIN 5 m s 100 m v = 500 μ F

Einfach mit einem kleinen Supercap.

weiterführendes
Datenblatt 24AA64
EEPROM Endurance Tutorial

Die Lebensdauer des EEPROMs wird pro Seite angegeben (zumindest für 24AA64 und andere EEPROMs, die ich verwendet habe). Der 24AA64 gibt eine 32-Byte-Seite an, daher sollte die Zählung pro Seite und nicht pro Block erfolgen.
@ Saad - Richtig. In meiner Antwort behoben.

1) Sobald Sie den Schreibvorgang gestartet haben, müssen Sie nur die MCU/EEPROM mit Strom versorgen und sicherstellen, dass die Steuerleitungen nicht stören - I2C ist dafür wahrscheinlich SPI vorzuziehen. Benötigen Sie nur wenige mA für einige Millisekunden, sollte dies also keine große Obergrenze sein, und Sie könnten die MCU in den Ruhezustand versetzen, sobald der Schreibvorgang eingeleitet wurde. 3) Sie können wahrscheinlich etwas Intelligenz anwenden, z. B. einen Holdoff - einmal geschrieben, hält es immer eine bestimmte Zeit, bevor ein weiterer Schreibvorgang erfolgen kann. Oder warten Sie, bis der Wert für eine Weile stabil ist, bevor Sie schreiben.
Sie können die Ausdauer auch erhöhen, indem Sie die Daten auf mehrere Standorte verteilen. Microchip hat einige Tools und Appnotes, um die Lebensdauer für ihre Eeproms zu berechnen, was nützlich sein kann.

Microchip-App-Hinweis zur Ausdauer: ww1.microchip.com/downloads/en/AppNotes/01019A.pdf Aus der Appnote können Sie auch die Ausdauer um etwa das Zweifache erhöhen, indem Sie die Betriebsspannung von 5 V auf 3,5 V verringern.
Wenn Sie Ihre erste Methode verwenden, stellen Sie sicher, dass das Schreiben in den nichtflüchtigen Speicher in Ihrem System die höchste Priorität hat, sobald es gestartet wird, dh. dass Interrupts nicht dazu führen können, dass sich Ihre Werte während des Schreibens ändern oder dass das Mikro eine andere Verarbeitung startet, wodurch Ihnen die Zeit davonläuft. Es ist äußerst wichtig, dass Sie beim Herunterfahren keine beschädigten Werte schreiben. Darüber hinaus würde Ihnen ein CRC für die Werte helfen, zu bestätigen, dass keine Beschädigung aufgetreten ist, aber Sie müssten entscheiden, was zu tun ist, wenn dies der Fall wäre, z. B. die Verwendung von Standardwerten.

Ich würde vorschlagen, ein blockorientiertes Flash-Gerät zu verwenden und ein Byte von jedem Block als Modus-Flag zu verwenden. Behalten Sie als Invariante bei, dass fast alle Modus-Flags programmiert werden; Es wird nur einen Block geben, in dem das Modus-Flag nicht programmiert ist, aber das des vorherigen Blocks (Umbruch, falls erforderlich). Dieser Block ist derjenige mit den neuesten Daten. Wenn dieser Block voll ist, löschen Sie den folgenden Block (beachten Sie, dass der zu löschende Block während des Löschzyklus eine beliebige Kombination von Daten enthalten könnte und die Invariante immer noch gelten würde), und programmieren Sie nach Abschluss des Löschvorgangs das Modus-Flag auf das, was früher war der letzte Block sein.

Es ist notwendig, die Versorgung des Flash gut genug zu schützen, um sicherzustellen, dass jeder Versuch, ein Byte zu programmieren, entweder erfolgreich ist oder vollständig fehlschlägt, aber es spielt keine Rolle, ob ein Löschzyklus unterbrochen wird und einen Block voller beliebiger Daten hinterlässt. da der nächste Versuch, einen Dateneintrag zu schreiben, diesen Block erneut löscht.

Wenn Ihre Daten 16 Bit groß sind, enthält ein 64Kx8-Chip über 32.000 Einträge. Das Schreiben eines Eintrags pro Sekunde würde den Chip etwa 2,7-mal füllen. Selbst ein Chip mit einer Lebensdauer von „nur“ 10.000 Löschzyklen würde über 10 Jahre halten. Die Verwendung eines größeren Chips oder eines mit einer Lebensdauer von 100.000 würde die Nutzungsdauer proportional verlängern.

1) Möglicherweise die einfachste Option, obwohl möglicherweise Hardwareänderungen erforderlich sind. Ich habe dies zuvor ohne PBC-Modifikationen erreicht, indem ich einfach die Entkopplungskappen erhöht und den Brown-Out unterbrochen habe.

2) Wie Sie bereits betont haben, ist das Problem bei FRAM der Preis!

3) Abhängig von der Volatilität Ihrer Temperatur- und Positionsdaten erhöhen Sie die Lebensdauer, indem Sie nur schreiben, wenn sich der Wert geändert hat. Möglicherweise messen Sie die Temperatur einmal pro Sekunde, aber wenn sie sich nur alle 5 Minuten ändert, ist das Problem gelöst.

So habe ich dieses Problem in meinem Projekt gelöst:

Reservieren Sie 1 Flash-Sektor, um eine Bitmaske nicht verwendeter Slots und eine Anzahl von Slots für den Wert zu halten.

Die verwendete Bitmaske war 16 Bytes lang, also hatte ich 128 Slots, um Werte zu setzen.

Die Bitmaske wird auf alle Einsen initialisiert, was in Flash-Begriffen der gelöschte Zustand ist.

Wenn Sie einen neuen Wert schreiben möchten, lesen Sie die Bitmaske ein und finden Sie das erste Bit, das eine Eins ist. Dies ist die Steckplatznummer, in die Sie den Wert schreiben. Ändern Sie dieses Bit in eine Null, um es als verwendet zu markieren, und schreiben Sie die Bitmaske zurück in den Flash, ohne sie vorher zu löschen. Als nächstes schreiben Sie den Wert in den Steckplatz nach der Bitmaske, auch ohne den Flash zu löschen.

Auf diese Weise verlängern Sie die Flash-Schreibzyklen um das 128-fache, indem Sie die neue Bitmaske nur mit einer Änderung von einer Eins zu einer Null schreiben.

Wenn die gesamte Bitmaske 0 ist, löschen Sie den Flash-Sektor und beginnen Sie neu.

Ich könnte Sie enttäuschen, aber wenn Sie ein bisschen blinken, wird der gesamte Sektor überschrieben. Ihre Lösung wird den 'Bitmask'-Sektor sehr bald tot machen.
Wenn Sie den Flash nicht löschen, verbrauchen Sie keinen der 10.000 Löschzyklen für den Sektor. Wenn Sie den Wert 0x7F haben und den Wert 0x3F schreiben, ist das Ergebnis 0x3F. Dies hält die Bitmaske aktuell, löscht aber nicht den Flash. Das Löschen erfolgt erst, wenn die gesamte Bitmaske 0 ist.
Wenn ich falsch liege, lass uns diskutieren. Ich möchte hier keine schlechten Antworten und ich möchte wirklich kein schlechtes Design in meinem Projekt.
Ich denke Robert hat Recht. Auf meinem Mikrocontroller können Sie nur 4 Bytes gleichzeitig schreiben, aber die erforderlichen Bits sind auf Null gesetzt. Die einzige Möglichkeit, sie wieder auf 1 zu bringen, besteht darin, den 1k-Block zu löschen. Es sind nur die Löschzyklen, die den Blitz verschleißen ...
Dies kann für jeden Speichertyp und möglicherweise sogar für den Speicheranbieter unterschiedlich sein. Ich habe gesehen, dass EEPROMs die Seite löschen und dann für jeden Schreibvorgang neu schreiben müssen. Ich habe Flash-Speicher gesehen, in den Sie Bits schreiben können, die immer noch Einsen sind, ohne die Seite zu löschen.