2010-08-23 16 views
9

Ich habe kürzlich die Notwendigkeit eingeführt, selten aktualisierte Konfigurationsvariablen im EEPROM eines Mikrocontrollers zu speichern. Hinzufügen Zustand unmittelbar in das Programm zwingt man überSicheres Speichern und Zugreifen auf das EEPROM

  • Erkennung von nicht initialisierten Daten im EEPROM (dh erstes Boot) zu sorgen,
  • Umwandlung oder Daten aus alten Firmware-Versionen ungültig zu machen, und
  • mehrerer Strukturen Adressierung, von denen jede in Firmware-Updates wachsen kann.

Umfangreiches Googeln hat nur einen Artikel aufgetaucht, der keeping your EEPROM data valid through firmware updates adressiert. Hat jemand den in diesem Artikel beschriebenen Ansatz verwendet? Gibt es einen besseren alternativen Ansatz?

Antwort

7

Persönlich bevorzuge ich ein "Taged Table" -Format.

In diesem Format sind Ihre Daten in eine Reihe von "Tabellen" aufgeteilt. Jede Tabelle hat eine Kopfzeile, die einem vorhersehbaren Format folgt, und eine Textstelle, die sich ändern kann, wenn Sie sie benötigen.

Hier ist ein Beispiel dafür, was eine der Tabellen aussehen würde:

Byte 0: Table Length (in 16-bit words) 
Byte 1: Table ID  (used by firmware to determine what this data is) 
Byte 2: Format Version (incremented every time the format of this table changes) 
Byte 3: Checksum  (simple sum-to-zero checksum) 
Byte 4: Start of body 
... 
Byte N: End of body 

ich nicht viele Daten speichern, so habe ich ein einziges Byte für jedes Feld in der Kopfzeile. Sie können die Größe verwenden, die Sie benötigen, solange Sie sie nicht ändern. Die Datentabellen werden nacheinander in das EEPROM geschrieben.

Wenn Ihre Firmware die Daten aus dem EEPROM lesen muss, beginnt sie an der ersten Tabelle zu lesen. Wenn die Firmware die Tabellen-ID erkennt und die angegebene Tabellenversion unterstützt, lädt sie die Daten aus dem Hauptteil der Tabelle (natürlich nach Überprüfung der Prüfsumme). Wenn die ID, die Version oder die Prüfsumme nicht ausgecheckt werden, wird die Tabelle einfach übersprungen. Das Längenfeld wird verwendet, um die nächste Tabelle in der Kette zu lokalisieren. Wenn die Firmware eine Tabelle mit einer Länge von Null erkennt, weiß sie, dass sie das Ende der Daten erreicht hat und dass keine weiteren Tabellen zu verarbeiten sind.

Ich finde dieses Format flexibel (Ich kann jede Art von Daten in den Körper einer Tabelle hinzufügen) und robust (halten Sie das Header-Format konstant und die Datentabellen werden sowohl vorwärts als auch rückwärts kompatibel sein).

Es gibt ein paar Vorbehalte, obwohl sie nicht zu belastend sind. Zuerst müssen Sie sicherstellen, dass Ihre Firmware den Fall behandeln kann, dass wichtige Daten entweder nicht in der Tabelle enthalten sind oder eine nicht unterstützte Formatversion verwenden. Sie müssen auch das erste Byte des EEPROM-Speicherbereichs auf Null initialisieren (so dass Sie beim ersten Start nicht in den Müll geladen werden und denken, dass es sich um Daten handelt). Da jede Tabelle ihre Länge kennt, ist es möglich, eine Tabelle zu erweitern oder zu verkleinern; Sie müssen jedoch den Rest des Tabellenspeicherbereichs verschieben, um sicherzustellen, dass es keine "Löcher" gibt (wenn die gesamte Tabellenkette nicht in den Speicher Ihres Geräts passen kann, kann dieser Vorgang lästig sein). Persönlich finde ich keines dieser Probleme so groß, und es lohnt sich, die Mühe zu sparen, die ich mit anderen Methoden der Datenspeicherung gespart habe.

+0

Dies klingt wie eine gute Lösung, um Änderungen der Tabellengröße zwischen Firmware-Versionen zu behandeln. Haben Sie einen Tipp dafür, dass es neben der Duplizierung der Daten tolerant gegenüber Power-Loss Mid-Write ist? –

+2

Schreiben Sie die gesamte Tabelle mit einer ungültigen Prüfsumme, dann (in einer separaten Transaktion) gehen Sie zurück und schreiben Sie die richtige Prüfsumme. Wenn während des Schreibens ein Problem auftritt, ist Ihre Prüfsumme falsch, wenn Sie die Daten einlesen. – bta

+0

Das ist eine elegante Lösung, die trivial zu implementieren ist: Danke fürs Nachfassen. –

3

Nigel Jones hat einige der Grundlagen in Ihrer Referenz behandelt. Es gibt viele Alternativen.

Eine Alternative, von Ihnen haben viel Platz, speichert Schlüssel-Wert-Paare anstelle von Strukturen. Dann können Sie einen Wert aktualisieren (indem Sie ihn anhängen), ohne alles zu löschen. Dies ist besonders nützlich bei Geräten mit einer begrenzten Anzahl von Löschzyklen. Ihre Lese-Routine muss von Anfang an scannen und die Werte jedes Mal aktualisieren, wenn der Schlüssel gefunden wird.Natürlich muss Ihre Update-Routine einen "Garbage Collector" haben, der sich einschaltet, wenn der Speicher voll ist.

Um Gerätefehler und Stromausfälle mitten in Updates zu behandeln, speichern wir normalerweise mehrere Kopien der Daten. Der einfachste Ansatz besteht darin, mit Hilfe der Sequenznummer zwischen den Hälften des Geräts zu pingen, um festzustellen, welches neuer ist. Ein CRC auf jedem Abschnitt wird verwendet, um es zu validieren. Dies betrifft auch das Problem nicht initialisierter Daten.

Für die Schlüssel-Wert-Version müssen Sie den neuen CRC nach jedem Schreiben anhängen.

+0

Ich mag den Sound dieses Ansatzes in der Theorie, aber leider nicht genug EEPROM zur Verfügung, um es machbar zu machen: nur 1 kB auf einem ATmega328p. Danke für die Beschreibung! –