Hallo,
in meinem C-Projekt möchte ich verschiedene Varriablen beim Erkennen von Netzausfall ins Flash speichern und natürlich beim nächsten Einschalten wieder aus dem Flash laden.
Beispiel:
1
unsignedintWert1;
2
floatWert2;
3
charWert3;
Meine Speicher/Lade Routine kann 256 Bytes in einem Rutsch laden oder speichern.
Aber dazu müssen die Varriablen mit ihren verschiedenen Größen hintereinander im Speicher liegen.
Jetzt dache ich das irgendwie mit einem "union" zu machen.
Mit nur einer Varriable würde das je gehen:
1
uniontest{
2
unsignedintWert1;
3
unsignedcharzum_speichern[256];
4
};
Jetzt würde ich mit speichern(zum_speichern); ja den INT Wert1 abspeichern.
Aber wie kann man ein union basteln, wo mehrere verschiedene Varriablen hintereinander im Speicher abgelegt werden ?
Aber wie kann man ein union basteln, wo mehrere verschiedene Varriablen
hintereinander im Speicher abgelegt werden ?
Wozu das mit den Unions?
Eine Struktur definieren. Du kannst deine Speicherroutine aufrufen indem du ihr die Adresse der Struktur und die Länge übergibst (mit dem sizeof-Operator). Natürlich prüft man die Länge nach, vor dem Schreiben.
Dann kümmert sich der compiler darum, wo was steht.
Eventuell habe ich dein Problem aber nicht verstanden, das ist durchaus drin.
Hallo Bergler,
guter Hinweis.
Ist denn bei einer Struktur sicher, dass alle Elemente lückenlos hintereiander und in der richtigen Reihenfolge im Speicher liegen ?
Hallo Bergler,
guter Hinweis.
Ist denn bei einer Struktur sicher, dass alle Elemente hintereinander
lückenlos im Speicher liegen ?
Lückenlos würde ich mich nicht sagen trauen. Z.B. wenn da ein bool drin ist, hat das garantiert nicht die Größe 1 Bit. Oder wenn man ein wirres Sammelsurium aus 32-Bit und 8-Bit Variablen deklariert, dann hängt auch vom Compiler ab, wie der das einsortiert.
Wie groß sie wirklich wird, sollte man darum immer den compiler mit sizeof ermitteln lassen. Wird ja nicht zur Laufzeit gemacht, kostet also nichts.
Aber die Variablen liegen schon hintereinander im Speicher, im Sinne von die Struktur belegt einen durchgehenden Block der größe sizeof(struktur) ab der Adresse der Struktur.
Man kann z.B. Dinge wie memcpy oder memset für eine Struktur verwenden. Oder sie auch einfach ins Flash schreiben (mit den Flash-Spezialfunktionen natürlich).
Da sträubt sich einem alles.
Das ist wie mit "Sattelit", was mit einem Sattel nun auch wirklich nichts zu tun hat, wenn man von den Stabilitätseigenschaften der Lagrangepunkte L1, L2 oder L3 absieht.
Vielleicht bringt ein Moderator wenigsten den Titel in eine sprachlich nicht ganz so peinliche Form.
Ist denn bei einer Struktur sicher, dass alle Elemente lückenlos
hintereiander und in der richtigen Reihenfolge im Speicher liegen ?
Ist es denn sicher dass du diese Anforderung brauchst? Was soll
das für einen Sinn machen wenn du sowieso in der Struktur immer
eindeutig auf jedes Element zugreifen kannst? Man kann ja mittels
EEPROM Read/Write auf einzelne Elemente zugreifen, muss nicht
die Struktur als Ganzes im Speicher (RAM) stehen haben.
Und was soll es bringen die Variablen "in der richtigen
Reihenfolge im Speicher" zu haben?
Ok, ich hab mich dahingehend geirrt dass ich vom EEPROM
gesprochen habe während die Daten ja im Flash abgespeichert
werden sollen.
Im Flash speichern wird aber unter Umständen schwierig werden
wenn die Flash-Sektoren "gross" sind oder aber der freie Flash-
Bereich so klein ist dass ein Teil des Programms betroffen ist.
Bei meinen Schaltungen gibts es da immer ein extra EEPROM
sofern nicht schon eines im Controller (AVR) enthalten ist.
Kost' fast nix und ist weitaus komfortabler als Flash.
Meine Speicher/Lade Routine kann 256 Bytes in einem Rutsch laden oder
speichern.
als Parameter verarbeiten kann.
Ansonsten ist eine Struktur aller benötigten Variablen der richtige Weg.
Ob da jetzt irgendwo eine Lücke ist oder nicht ist völlig egal (außer dir wird der Platz zu knapp) Die Lücke wird sowohl beim Speichern als auch beim Laden gleich sein solange du da die gleiche Struktur benutzt.
p.s. Man sollte lernbereit sein, auch wenn es die Rechtschreibung betrifft.
Ist denn bei einer Struktur sicher, dass alle Elemente lückenlos
hintereiander und in der richtigen Reihenfolge im Speicher liegen ?
Ist es denn sicher dass du diese Anforderung brauchst?
Sehr wahrscheinlich braucht er die nicht. Warum sollte es die Speicherfunktion jucken, ob da Lücken zwischen den Variablen sind? Die weiß ja nicht mal was von Variablen, sondern kopiert einfach nur einen Block aus Bytes 1:1 von A nach B. Das wäre zumindest das, was ich erwarten würde. Und wenn ich diesen Block später wieder Byte für Byte zurück nach A kopiere, ist dort natürlich alles wieder exakt gleich wie vorher. Reihenfolgen oder Lücken sind dafür völlig unerheblich.
Ok, ich hab mich dahingehend geirrt dass ich vom EEPROM
gesprochen habe während die Daten ja im Flash abgespeichert
werden sollen.
Bisher wissen wir nicht einmal um was für eine µC-Familie es überhaupt geht und ob mit "Flash" der eingebaute Speicher oder ein externes Flash-Modul gemeint ist.
Bisher wissen wir nicht einmal um was für eine µC-Familie es überhaupt
geht und ob mit "Flash" der eingebaute Speicher oder ein externes
Flash-Modul gemeint ist.
Ist denn bei einer Struktur sicher, dass alle Elemente lückenlos
hintereiander und in der richtigen Reihenfolge im Speicher liegen ?
Eine stichhaltige Begründung für diese Anforderung wäre sehr
hilfreich. Oft werden solche Dinge einfach mal "ins Blaue"
gefordert ohne genau zu wissen warum.
Ist es denn sicher dass du diese Anforderung brauchst? Was soll
das für einen Sinn machen wenn du sowieso in der Struktur immer
eindeutig auf jedes Element zugreifen kannst? Man kann ja mittels
EEPROM Read/Write auf einzelne Elemente zugreifen, muss nicht
die Struktur als Ganzes im Speicher (RAM) stehen haben.
Da muss ich bei jeder neuen remanenten Variable (dieses mal richtig geschrieben) meine Speicherroutine anpassen. Ist mir zu aufwendig und fehleranfällig.
Und was soll es bringen die Variablen "in der richtigen
Reihenfolge im Speicher" zu haben?
Wenn in einigen Jahren ein Firmware Update kommt, welche mit einer anderen Version des Compilers oder ein andere Compiler erstellt wurde, und dann die Anordnung der alten Daten im Flash nicht mit der u.U. neuen Anordnung übereinstimmt.
Bisher wissen wir nicht einmal um was für eine µC-Familie es überhaupt
geht und ob mit "Flash" der eingebaute Speicher oder ein externes
Flash-Modul gemeint ist.
Wenn in einigen Jahren ein Firmware Update kommt, welche mit einer
anderen Version des Compilers oder ein andere Compiler erstellt wurde,
und dann die Anordnung der alten Daten im Flash nicht mit der u.U. neuen
Anordnung übereinstimmt.
Deswegen die Verwendung einer Struktur. Und die Anweisung an
den Compiler die Struktur so zu "packen" wie man es braucht
und für richtig hält. Alignments gibt es auch noch als Option.
Und was soll es bringen die Variablen "in der richtigen
Reihenfolge im Speicher" zu haben?
Wenn in einigen Jahren ein Firmware Update kommt, welche mit einer
anderen Version des Compilers oder ein andere Compiler erstellt wurde,
und dann die Anordnung der alten Daten im Flash nicht mit der u.U. neuen
Anordnung übereinstimmt.
Die Reihenfolge der Elemente einer struct ist in C immer die, in der sie im Code definiert wurden. Ein Compiler, der die anders sortiert, würde an der Stelle massiv gegen den Standard verstoßen. Für einzelne Variablen, die nicht in einer struct sind, gilt das übrigens nicht.
Ich sehe zwei Dinge, die dir bei einem Compilerwechsel theoretisch (aber auch eher unwahrscheinlich) passieren können:
Die Größen von Datentypen ändern sich - in dem Fall bringt dir ein Packen der Struktur aber nichts.
Das Alignment ändert sich - dagegen kann das Packen helfen, falls der µC damit umgehen kann. Ich würde dann eher mit Füll-Elementen arbeiten, um damit das Alignment manuell zu erzielen.
Generell würde ich das (da eben eher unwahrscheinlich) nicht weiter bedenken, sondern einfach im Code ein paar static-asserts einbauen, die mir - falls so ein Fall doch mal nach einem Compilerwechsel auftritt - einen Fehler ausgeben. Dann kann man sich immer noch darum kümmern.
Ist denn bei einer Struktur sicher, dass alle Elemente lückenlos
hintereiander und in der richtigen Reihenfolge im Speicher liegen ?
Sie liegen exakt in der Reihenfolge, wie Du sie in der Struct deklariert hast. Das ist der Sinn einer Struct.
Es können allerdings Lücken auftreten, wenn der Compiler ein Alignment auf CPU-Datenbreite vorsieht. Daher sollte man vorzugsweise in der Struct die Variablen nach absteigendem Format anordnen (64Bit zuerst ... 8Bit am Ende).
Wenn in einigen Jahren ein Firmware Update kommt, welche mit einer
anderen Version des Compilers oder ein andere Compiler erstellt wurde,
und dann die Anordnung der alten Daten im Flash nicht mit der u.U. neuen
Anordnung übereinstimmt.
Wenn das wichtig ist oder vielleicht sogar eine Übertragung der Daten zu einem anderen System, dann schreibt man sich dafür explizite Funktionen zur Serialisierung und Deserialisierung der Daten in/von einem Byte Array. Das Byte Array kann man dann speichern, kopieren, verschicken.
Die Reihenfolge der Elemente einer struct ist in C immer die, in der sie
im Code definiert wurden. Ein Compiler, der die anders sortiert, würde
ROTFL da glaubt noch einer an das Gute im Programmierer. Nein, das ist laut Standard "implementation defined", also so wie es den Erstellern des Compilers in den Kram gepasst hat. Wenn Software, die mit haargenau dem selben Compiler übersetzt wurde, die Daten schreibt und auch liest, ist man ziemlich auf der sicheren Seite, dass alles wieder da raus kommt, wo es rein ging. Ich kann mich aber ernsthaft an ein Compilerupdate (also selber Compilerhersteller, selber Produktname) erinnern, nach dem die Reihenfolge der Elemente in den Strukturen umgedreht war.
Und da sind wir wieder bei den Anforderungen an die Software des Fragestellers. Ist denn überhaupt verlangt, dass nach einem Update (noch schwieriger : nach einem Downgrade) seiner Software, die alten Daten noch aus dem NVM gelesen werden können ? Dabei könnten ja Daten hinzukommen oder wegfallen.
Wenn das nicht gefordert ist : blockiere die Übernahme von Daten in einem anderen (unbekannten) Format durch eine Versionsnummer, die vor den Daten abgelegt wird und vertraue auf eine Struktur.
Wenn es denn sein muss, mach Dir ganz viele Gedanken, wie Du mit allen Möglichen Sonderfällen umgehst und schreibe die Routinen zur Serialisierung und Deserialisierung komplett selbst.
"Foolproof" wäre es, per Linker Description Definition jeder
Variable einen eigenen Flash-Speicherraum (soweit der Speicher-
Platz im Controller sein soll) zu reservieren. Für jede neu
hinzugekommene Variable dann einen neuen Speicherraum definieren.
bei erhöhten Anforderungen an die "Mutationsrate" der abzuspeichernden Variablen und sogar bei eventuellen Architekturänderungen bietet sich CBOR (z.B. tinycbor von Intel) als Speicherformat für Deine Werte an.
Über irgendwelche Strukturformate Deines Compilers musst Du Dir dann jedenfalls keine Gedanken mehr machen, das ist alles in CBOR definiert.
In 256 Bytes lässt sich mit CBOR so Einiges unterbringen.
Es können allerdings Lücken auftreten, wenn der Compiler ein Alignment
auf CPU-Datenbreite vorsieht. Daher sollte man vorzugsweise in der
Struct die Variablen nach absteigendem Format anordnen (64Bit zuerst ...
8Bit am Ende).
Dagegen hilft doch ein
1
#pragma pack(1)
2
structfoo
3
{
4
...
5
}
Führt zwar zu (etwas) erhöhtem Ausführungsaufwand, funktionert aber in Bezug auf linearen Speicher einwandfrei.
Und da sind wir wieder bei den Anforderungen an die Software des
Fragestellers. Ist denn überhaupt verlangt, dass nach einem Update (noch
schwieriger : nach einem Downgrade) seiner Software, die alten Daten
noch aus dem NVM gelesen werden können ? Dabei könnten ja Daten
hinzukommen oder wegfallen.
Wenn das Problem auftritt, kann man auch sagen: "Pech gehabt!"
PS: Du plenkst.
Wir arbeiten hier mit mindestens zwei verschiedenen Compilern (arm und AVR) und verwenden ohne Probleme systemübergreifende structs.
Ist denn bei einer Struktur sicher, dass alle Elemente lückenlos
hintereiander ... im Speicher liegen ?
Nein. Es kommt aufs Alignment an. Du solltest es für diesen Struct auf 1
Byte stellen.
Warum?
Sonst werden u.U. bei einem 32-Bit-Prozessor hinter jedes einzelne Byte 3 "Füllbytes" gelegt, damit wieder eine D-Wort-Adresse herauskommt und der Prozessor optimal schnell auf den Speicher zugreifen kann.
Ein Struct aus 65 Bytes passt dann auf einmal überraschenderwiese nicht mher in die 256-Byte-Page...
Wir arbeiten hier mit mindestens zwei verschiedenen Compilern (arm und
AVR) und verwenden ohne Probleme systemübergreifende structs.
Wenn man dann aber mal mit Litte- und Big-Endian zu tun bekommt (ARM<->x86), und diese structs dazwischen austauschen muss, dann erreicht man einen neuen Level... ;-)
Wenn man dann aber mal mit Litte- und Big-Endian zu tun bekommt
(ARM<->x86), und diese structs dazwischen austauschen muss, dann
erreicht man einen neuen Level... ;-)
Wir verwenden keine X86 oder PowerPC als Senke.
Die Structs bzw. .h-Dateien werden von einem PC-Programm generiert - dabei sind die Endians aber egal, da am Ende nur Text herauskommt.
Wenn ich mich recht erinnere kann man beim arm auch zwischen BigEndian und LittleEndian umschalten (nie benutzt, kann auch woanders herstammen).
Auf solche Probleme kann man natürlich auch vorher testen...
Auf solche Probleme kann man natürlich auch vorher testen...
Wenn man zwischen mehreren Systemen Daten austauscht kann man das auch einfach gleich richtig machen.
Stichwort Serialisieren/deserialisieren wurde genannt.
Nächste Stufe wäre dafür ein definiertes Format zu nehmen, wurde auch schon genannt:
Nein. Es kommt aufs Alignment an. Du solltest es für diesen Struct auf 1
Byte stellen.
Warum?
Sonst werden u.U. bei einem 32-Bit-Prozessor hinter jedes einzelne Byte
3 "Füllbytes" gelegt, damit wieder eine D-Wort-Adresse herauskommt und
der Prozessor optimal schnell auf den Speicher zugreifen kann.
Ich habe noch nicht gehört, dass auf einem Prozessor ein 8-Bit-Typ ein 32-Bit-Alignment bekäme - oder überhaupt, dass Typen ein Alignment bräuchten, das größer ist als der Typ selbst. Hast du mal ein Beispiel für sowas? Ich halte das eher für ungewöhnlich, gerade bei µCs, wo das ja übelste Platzverschwendung wäre.
Die Reihenfolge der Elemente einer struct ist in C immer die, in der sie
im Code definiert wurden. Ein Compiler, der die anders sortiert, würde
ROTFL da glaubt noch einer an das Gute im Programmierer. Nein, das ist
laut Standard "implementation defined", also so wie es den Erstellern
des Compilers in den Kram gepasst hat.
Die Reihenfolge ist garantiert:
C99 TC3 §6.7.2.1p13 "structure and union specifiers":
"Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared."
Den Level hatte man schon mit einfachen TCP Verbindungen.
Probleme nit denen man sich beschäftigt, wenn sie auftreten...
Das wäre in meinem Fall eine Erweiterung, die bis jetzt noch nicht benötigt wurde. Aber auch sowas sollte man gelöst bekommen...
Kann man, sollte man aber nicht, weil man dann wieder aus der Reihe
tanzt.
Bei den "Experten", die ich schon kennenlernen durfte, wäre sowas definitiv möglich, wenn sie dadurch einfacher zum Ziel kommen.
Die andere Seite ist natürlich das Problem der andere...
Habe es eben ausprobiert (PIC32MZ + XC32 Compiler):
Bei #pragma pack(1) oder #pragma pack(2) stürzt der Prozessor ab.
#pragma pack(4) geht, bringt dann aber nichts mehr.
Habe es eben ausprobiert (PIC32MZ + XC32 Compiler):
Bei #pragma pack(1) oder #pragma pack(2) stürzt der Prozessor ab.
#pragma pack(4) geht, bringt dann aber nichts mehr.
Es gibt Prozessoren, da dürfen variablen nicht über 2 oder 4 byte-Grenzen liegen. Also ein uint32 darf nur an Adresse 0, 4, 8, 12 ... anfangen, nicht 1,2 oder 3.
Das Problem löst Peters Anordnung im struct automatisch, egal welches pragma.
Warum erlaubt der Compiler es dann, wenn der Prozessor abstürzt? Naja, der Trick ist dann, mit memcpy darauf zuzugreifen. Das geht immer.
Habe es eben ausprobiert (PIC32MZ + XC32 Compiler):
Bei #pragma pack(1) oder #pragma pack(2) stürzt der Prozessor ab.
#pragma pack(4) geht, bringt dann aber nichts mehr.
Habe es eben ausprobiert (PIC32MZ + XC32 Compiler):
Bei #pragma pack(1) oder #pragma pack(2) stürzt der Prozessor ab.
#pragma pack(4) geht, bringt dann aber nichts mehr.
Das ist exakt das, was ich anfangs damit meinte:
Solange man nur über die struct oder Zeiger auf die struct auf die Member zugreift, sollte es auch mit pack(1) funktionieren. Der Compiler generiert dann bei einem unaligned access für z.B. uint32 automatisch 4 Bytezugriffe und setzt die Werte richtig zusammen. Wenigstens GCC macht das. Ob das im Standard definiert ist, weiß ich gerade nicht.
Wenn der Compiler irgendwann das Wissen über die unaligned Adresse verliert, weil man z.B mit uint32 *p = &str.counter arbeitet und dann p an eine Funktion übergibt, die uint32 * erwartet und da dann so zugreift, dann wird es zum Absturz führen. Hier hat der Compiler kein Wissen mehr über die Struktur und generiert einen 32 Bit Wortzugriff der dann unter Umständen unaligned ist. Dann fällt die Kuh um.
Ja, nach einer Weise, die in diesem Fall zum verwendeten Prozessor
inkompatibel ist.
Microchip mal wieder...
Compiler-Bug-Report schreiben! (oder auf Controller und Compiler
umsteigen, die das können.)
Das ist kein Compiler-Bug. Du hast einfach ein Feature falsch benutzt. Und wenn du nur mit µCs umgehen kannst, die keine Alignment-Anforderungen haben, dann machst du was falsch.
Solange man nur über die struct oder Zeiger auf die struct auf die
Member zugreift, sollte es auch mit pack(1) funktionieren. Der Compiler
generiert dann bei einem unaligned access für z.B. uint32 automatisch 4
Bytezugriffe und setzt die Werte richtig zusammen.
Ist dann halt im Vergleich zu einem normalen Zugriff elends langsam.
Wenigstens GCC macht das. Ob das im Standard definiert ist, weiß ich
gerade nicht.
Ist es nicht. Im Standard ist auch das Pragma nicht definiert. Dort ist nur definiert, dass du die Alignment-Anforderungen einhalten musst. Wenn du den Compiler über eine non-Standard-Erweiterung explizit anweist, das zu missachten, musst du eben genau wissen, was du tust, sonst kann es knallen.
Wenn der Compiler irgendwann das Wissen über die unaligned Adresse
verliert, weil man z.B mit uint32 *p = &str.counter arbeitet und dann p
an eine Funktion übergibt, die uint32 * erwartet und da dann so
zugreift, dann wird es zum Absturz führen. Hier hat der Compiler kein
Wissen mehr über die Struktur und generiert einen 32 Bit Wortzugriff der
dann unter Umständen unaligned ist. Dann fällt die Kuh um.
Jo, Packing ist und bleibt halt eine Frickellösung.
Jo, Packing ist und bleibt halt eine Frickellösung.
Manchmal hat man kaum eine Wahl. Ich mach dann "intern" alles ohne packing und für die Interfaces (hier das Flash) explizit Zugriffsfunktionen, die das dann richtig regeln. Damit ist dann das packing sauber gekapselt.
In diesen Interface-Funktionen kann man auch ohne struct und pack arbeiten. Damit ist man nicht compilerabhängig.
Das ist kein Compiler-Bug. Du hast einfach ein Feature falsch benutzt.
Für mich ist es ein Bug, wenn andere Compiler es umsetzen.
Es ist kein Fehler-Bug; eher ein Missing-Feature-Bug.
Es wäre für mich ein Ausschlusskriterium den Controller / Compiler zu verwenden.
Und wenn du nur mit µCs umgehen kannst, die keine
Alignment-Anforderungen haben, dann machst du was falsch.
Was hat das eine mit dem anderen zu tun?
Natürlich ist es eine Software-Lösung, die dazu führt, dass die Ausführungsgeschwindigkeit sich verlangsamt.
Nach deiner Aussage darf man also für Modbus-Geschichten maximal 16-Bit-Controller verwenden?! (oder auf einem 32-Bit-System Speicherplatz verwendet).
Ist dann halt im Vergleich zu einem normalen Zugriff elends langsam.
Einen Tod musst du halt sterben.
Es gibt nicht immer "normale" Zugriffe für unaligned Daten. Siehe als Beispiel Ethernetpakete. Ob du die Zugriffe jetzt per packed struct oder selber einzelne Bytezugriffe machst, ist dann egal.
Bei packed struct nimmt einem der Compiler die Arbeit ab. Wenigstens GCC.
Du hast aber empfohlen, den Controller zu wechseln, um das Problem zu
umgehen.
Wenn man es einfacher haben will, und die Möglichkeit hat, würde ich umsteigen (Der Spruch bezieht sich auf mich - das ist keine Empfehlung für andere; höchstens ein Lösungsvorschlag unter o.g. Bedingungen).
Wenn man es einfacher haben will, und die Möglichkeit hat, würde ich
umsteigen (Der Spruch bezieht sich auf mich - das ist keine Empfehlung
für andere; höchstens ein Lösungsvorschlag unter o.g. Bedingungen).
Naja, ob's jetzt einfacher ist, den Compiler und den µC zu wechseln als seinen Code so zu schreiben, dass er ohne Packing auskommt, sei mal dahingestellt.
Ist dann halt im Vergleich zu einem normalen Zugriff elends langsam.
Einen Tod musst du halt sterben.
Ja, klar. Solange man, wie du schreibst, diesen Teil rein auf die Schnittstelle begrenzt und nicht überall im Code auch intern die gepackten Strukturen nutzt, fällt der Aufwand so oder so an, auch wenn man's von Hand macht.
Naja, ob's jetzt einfacher ist, den Compiler und den µC zu wechseln als
seinen Code so zu schreiben, dass er ohne Packing auskommt, sei mal
dahingestellt.
Dann darf ich mich einfach glücklich schätzen, dass unsere Controller und Compiler das unterstüzen.
Eine bewährte Methode, die ich in allen Projekten mit dem Bedarf an reset- resistenten Variablen benutze ist diese: In der RAM section des Linkers habe ich eine Section mit dem Namen PS_PARARAM definiert. Alle Variablen, die überleben sollen werden wie folgt irgendwo global im C-Code definiert (Beispiel):
Eine Funktion SaveParams() sichert die gesamte Section ins Flash und eine entsprechende Funktion reloadParams() lädt die gesamte Section vom Flash. Bei Start des Programms wird reloadParams() ausgeführt. Die Funktion prüft über einen Hashwert, ob der Flash jemals gefüült wurde. Falls nicht, wird auch nichts geladen und die Variablen im RAM behalten ihren Initialwert. Die sporadisch aufgerufene Funktion saveParams() prüft, ob sich Variablen geändert haben (über einen Hash) und flashed falls der Hashwert sich ändert. SaveParams() kann man natürlich auch jederzeit aufrufen, um ein Speichern zu erzwingen.