Moin! Ich bin gerade an einem Projekt auf einem TI CC3200 Launchpad dran, bei dem ich viele "linked Lists" verwende, z.T. sogar verschachtelt. Diese sollen im nichtflüchtigen Speicher abgelegt werden, damit sie nach einem Neustart wiederverwendbar sind. Ich steh grad auf dem Schlauch, wie ich die Rohdaten beim Neustart wieder in die "Listen verpackt" kriege. Nach meiner Logik muss ich da ziemlich viele Steuerdaten mit Adressen etc. an vordefinierten Speicheradressen ablegen, um nachher in einer Startup-Routine die Listen wieder zu erstellen und mit Daten zu füllen... das klingt für mich sehr komplex und aufwändig. Hab ich mir das richtig überlegt oder gibt es einen viel einfacheren Weg? Bitte nicht böse sein, falls es eine blöde frage ist - ich hab schon länger nicht mehr embedded programmiert :-) Vielen Dank! Gruss Philipp
Gleich alle Listen im FRAM bearbeiten und halten?
Die Frage ist, ob sich die Listen zur Laufzeit ändern oder immer gleich sind. -> Dann könntest du sie im Code ablegen. Nächste Frage wäre, ob sich die Listen bei "Konfiguration" ändern. -> Dann müssteste du dir eine Konfigurationsstruktur überlegen. Sind sie völlig dynamisch, dann wäre ein Konfigurationsloader sinnvoll, der die Daten aus dem Flash einliest. Da wäre es sinnvoll mit IDs und Header zu arbeiten, analog FAT Dateisystem. Vielleicht hast du ein einfaches Beispiel, dann kann man das besser abschätzen.
Das Stichwort lautet "Serialisieren". Du musst deine Datenstrukturen (d.h. alle deine Listen/Bäume) irgendwie in einen seriellen Bytestrom umwandeln (serialisieren), den du dann direkt abspeichern kannst. Zum Einlesen verwandelst du diesen Bytestrom wieder in deine Listenstruktur (deserialisieren). Dafür gibt es fertige Bibliotheken, oder du baust das selbst. Als Beispiel: Wenn du eine doppelt verkettete Liste hast, dann speicherst du darin mindestens zwei Zeiger plus das Datenelement. Abspeichern brauchst du aber nur die Anzahl der Datenelemente plus die Elemente selbst (die Zeiger kannst du beim Einlesen neu erzeugen, deren genaue Werte sind ja egal). Speichert deine Liste aber Zeiger, dann musst du diese vorher auflösen, d.h. entweder das gezeigte Objekt stattdessen speichern oder eine Referenz darauf (z.B. ID).
Hi! Vielen Dank für die schnellen antworten, das hilft mir weiter und ich habe nun auch das Gefühl, dass ich ungefähr in die richtige Richtung überlegt habe! Die Listen können zur Laufzeit jederzeit verändert, erweitert oder verkleinert werden... zudem enthalten sie Pointer auf andere Listen, was das genannte serialisieren schwierig machen dürfte. Als Codebeispiel:
1 | // Struct to define the order and use of the DMX-Channels for a specific fixture type
|
2 | typedef struct fixtureChannel { |
3 | char purpose[MAX_NAMING_LETTERS]; // Predefined are d = Dimmer, r = red, g = green, b = blue, w = white, a = amber, u = uv, c = cyan, m = magenta, y = yellow |
4 | struct fixtureChannel * next; |
5 | } fixtureChannel_t; |
6 | |
7 | // Struct to define the DMX protocol of a fixture
|
8 | typedef struct fixture { |
9 | int id; |
10 | char name[MAX_NAMING_LETTERS]; |
11 | fixtureChannel_t * chanList; |
12 | int chanCount; |
13 | char colType; // 1 = No Color, 2 = RGB, 3 = RGBW, 4 = RGBWA, 5 = RGBWUV, 6 = RGBWAUV, 7 = CMY, 8 = Wheel |
14 | char hasDimmer; // 1 = yes, 0 = no (virtual Dimmer needed) |
15 | struct fixture * next; |
16 | struct fixture * previous; |
17 | } fixture_t; |
Ich habe nun so grob die Idee, die "inneren" Listen separat der äusseren zu serialisieren und dann in der Serialisierung der "äusseren" Listen auf die Anzahl und Startadresse der jeweils inneren zu speichern. Klingt das nach einer Idee, falls ich mich verständlich ausgedrückt habe? Bezüglich fertiger Bibliotheken: Wenn euch gerade eine einfällt, immer her damit! :-) Gruss Philipp
Kleiner Tipp: Wenn deine Listen im Speicher auch als Adressen abgebildet sind, hilft es, beim serialisieren diesen Nummern zu geben. die Adressen können und werden sich im Programm ändern. Beispiel zum Serialisieren:
1 | typedef struct fixture { |
2 | int id; |
3 | char name[MAX_NAMING_LETTERS]; |
4 | fixtureChannel_t * chanList; |
5 | int chanCount; |
6 | char colType; |
7 | char hasDimmer; // 1 = yes, 0 = no (virtual Dimmer needed) |
8 | struct fixture * next; |
9 | struct fixture * previous; |
10 | } fixture_t; |
1 | T_FIXTURE;1;test;1;1;1;1 |
2 | T_FIXTURE;2;test2;1;1;1;1 |
Annahmen: *next und *previous werden berechnet Name enthält nur ASCII Space und Zahlen und keine \0 Mit T_FIXTURE definierst du den Typ. Als chanlist verwendest du eine ID anstatt Zeiger. Jetzt kannst du über tokenizing die Strings zerlegen und zusammenbauen. Dabei aufpassen, dass keiner die Strukturen zwischenzeitlich ändert.
1 | typedef struct fixtureChannel { |
2 | char purpose[MAX_NAMING_LETTERS]; |
3 | struct fixtureChannel * next; |
4 | } fixtureChannel_t; |
wird dann zu: T_CHAN;1;test1 T_CHAN;2;test2 Ich hoffe damit wird es klarer.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.