Hallo,
in einem meiner aktuellen Projekte werden (kleine) Datenmengen
regelmäßig aktualisiert und sollen halbwegs persistent gespeichert
werden. Ich habe mich für FRAM entschlossen, welcher mittels I2C von
meinem AVR (ATmega328p) angesprochen wird.
Teil meines Projekts ist eine I2C Bibliothek sowie eine FRAM Bibliothek,
welche die Zugriffe etwas abstrahieren. Auf Daten im FRAM kann ich dann
mit folgenden Funktionen zugreifen:
1 | uint8_t fram_read_byte(uint16_t addr);
|
2 | void fram_read_block(uint16_t addr, void* dst, size_t len);
|
3 |
|
4 | void fram_write_byte(uint16_t addr, uint8_t val);
|
5 | void fram_write_block(uint16_t addr, void* src, size_t len);
|
Die Adresse ist ja jeweils nur eine Zahl, die sich auf das entsprechende
Byte im FRAM bezieht. Das funktioniert soweit auch super, nun habe ich
aber eine eher konzeptuelle Frage. Wie lässt sich der Speicher nun
bequem mittels C bzw. avr-libc heraus verwalten und darauf zugreifen?
Beispeiseweise möchte ich eine größere Struktur folgender Art im FRAM
ablegen:
1 | typedef struct {
|
2 |
|
3 | char name[64];
|
4 | uint16_t impulses;
|
5 | uint64_t counter;
|
6 |
|
7 | } prefs_sub_t;
|
8 |
|
9 | typedef struct {
|
10 |
|
11 | version_t version;
|
12 | size_t length;
|
13 | prefs_sub_t prefs[256];
|
14 |
|
15 | } prefs_t;
|
Insgesamt ist eine konkrete Instanz diesen Typs zu groß, um sie im RAM
vorzuhalten. Außerdem möchte ich mir den Overhead der korrekten
"Synchronisation" beider Kopien ersparen. Daher möchte ich die Daten NUR
(!) im FRAM vorhalten und mittels geeigneter Funktionen bequem auf diese
zugreifen können.
Allerdings erscheint mir das relativ kompliziert und ich muss händisch
die jeweiligen Offsets berechnen. Mal angenommen, ich möchte auf den
Namen des 17. Elements zugreifen, sähe das ja in etwa so aus (vom
Konzept her, ob es tatsächlich kompiliert weiß ich gar nicht):
1 | char[32] str;
|
2 | fram_read_block(0 + sizeof(version_t) + sizeof(length) + sizeof(prefs_sub_t) * 17, str, 64);
|
Das erscheint mir etwas unpraktisch und erfordert wohl viel Rechnerei.
Vorallem erfordert es Anpassungen, sobald sich die Strukturen einmal
ändern.
Schöner wäre es, wenn man z.B. ähnlich zum Zugriff auf dem EEPROM einen
eigenen Pointer-Typ definieren könnte. Ist das denn (ohne tiefgreifende
Eingriffe in avr-libc bzw. avr-gcc) möglich? Also ein eigenes Attribut
z.B. FMEM zu definieren (analog zu EEMEM)?
Wie würdet ihr so etwas lösen? Gibt es hier brauchbare Projekte, bei
denen man sich inspirieren lassen kann? Externen Speicher mittels I2C
anzusprechen ist ja nicht ganz exotisch, auch wenn es meistens EEPROM
ist ...
Vielen Dank!