@Uwe K. (Gast)
>sehe ich das richtig, dass ich mit EEMEM, Speicher für den EEPROM>alloziere
Ja.
> und gleichzeitig diese Variablen auch als "normale" nutzen>kann=
Nö. Auf die EEPROM-Variablen, hier eep, kann man nur mittels der
eeprom_read/write Funktionen zugreifen. Das einzige, was man natürlich
mehrfach wiederverwenden kann, ist deine Typdefinition var_t.
Peter D. schrieb:> Wer kommt denn auf sowas verrücktes. Den Code möchte ich nicht pflegen> müssen
Das hab ich mich auch grad gefragt, zumindest lateinische Nummerierung
hätte ich hier in Verwendung, wahrscheinlicher aber arabische
Nummerierung.
Peter D. schrieb:> Wer kommt denn auf sowas verrücktes.
Ach da muss nur der "Sinn und Zweck" von Arrays nochmal verinnerlicht
werden.
Es gibt noch viel zu lernen!
z.B. dass das durchnummerieren von Variablen, oder sonstigen
Bezeichnern, böse ist.
Gibt es diese Speicherklassen eigentlich in generalisierter Form oder
nur, wenn ein entsprechendes EEPROM verbaut ist?
Oder anders: Kann man virtuelle Addressräume frei definieren?
Ja, Sections wären schon einmal nicht schlecht. Aber was, wenn z.B. das
System eigentlich nur 16-bit Addressen unterstützt, man aber virtuell
32-bit braucht?
Einfaches Beispiel: Man klemmt ein externes EEPROM mit 4Mbit an einen
Attiny oder sowas. Die Addressen im EEPROM könnte man bequem den
Compiler berechnen lassen, wenn man an 32-bit Addressen heran käme.
Soweit mir bekannt, wird das nicht gelingen.
Das einzige mir bekannte Mittel um was zu bauen ist sizeof() in
Verbindung mit offsetof(). Aber einen größeren Wertebereich als size_t
hat das auch nicht.
Sowas befürchte ich auch. Einige AVR-Header für größere Chips besorgen
sich aber in der Tat die längeren Addressen via &-Operator. Meine
Vermutung war nun, dass das entweder gelingt, weil die Addressen erst
beim Speichern in eine Variable geclamp'd oder gewrapped werden, oder es
an einer speziellen Speicherklasse der Variablen liegt (siehe
morepgmspace.h).
Mir ist an der Stelle das Konzept vom GCC nicht klar. Bei VC war so
etwas eine Eigenschaft des Zeigertyps. "pointer to progmem_far" oder
sowas kann logischerweise nur gelingen, wenn progmem_far definiert ist.
Ich muss das wohl bei Gelegenheit mal selbst austesten...
Peter D. schrieb:> Uwe K. schrieb:>> ALERT_MINUTE_IIIIIII,>> ALERT_MINUTE_IIIIIIII,>> Wer kommt denn auf sowas verrücktes. Den Code möchte ich nicht pflegen> müssen.
Klär mich bitte auf. Wie würdest du das lösen?
Für das menschliche Auge leichter zu unterscheiden wäre
ALERT_MINUTE_1
ALERT_MINUTE_2
ALERT_MINUTE_3
...
ALERT_MINUTE_7
ALERT_MINUTE_8
Wenn Du irgendwo mitten im Code ALERT_MINUTE_IIIIIII findest, muss man
abzählen. Der Unterschied ALERT_MINUTE_IIIIIIII zu ALERT_MINUTE_IIIIIII
ist nicht auf den ersten Blick zu erkenenn. Das ist Fehleranfällig.
Uwe K. schrieb:> Klär mich bitte auf. Wie würdest du das lösen?
Na wenigsten so: ALERT_MINUTE_7 bzw. ALERT_MINUTE_8. Das ist schon mal
um Faktor 1000 besser lesbar.
Es ist übrigens eine sehr mäßige Idee einen enum Typ zu nutzen, um eine
solche Variable zu definieren. Der Grund ist, dass C dir die Größe einer
enum Variable nicht garantiert. Es garantiert dir lediglich, dass alle
Werte darin gespeichert werden können. Konkret könnte zum Beispiel
uint8, uint16 oder uint32 verwendet werden. Dies kann sich sogar mit der
Optimierungsstufe des Compilers ändern. Der GCC hat Flags womit du
explizit die Größe von enum Variablen packen kannst.
Verändert sich irgendwas (Compiler, Optimierungsstufe, ...) kann so dein
EEPROM Inhalt nicht mehr zur Variable passen, ohne dass das
offensichtlich wäre.
Es ist auch keine gute Idee eine struct zu verwenden, da ein naives
Lesen/Speichern a la
var_t x;
read_ee(0x1000, &x, sizeof(x));
write_ee(0x1000, &x, sizeof(x));
Annahmen über das Padding und Alignment in dieser Struktur macht.
NurEinGast schrieb:> Wenn Du irgendwo mitten im Code ALERT_MINUTE_IIIIIII findest, muss man> abzählen.
Ja. Und wenn du mit dem Editor nach ALERT_MINUTE_II suchst, dann findet
er auch ALERT_MINUTE_III, ALERT_MINUTE_IIII usw.
Uwe K. schrieb:> Klär mich bitte auf. Wie würdest du das lösen?
Besser wäre:
1
...
2
uint8_tALERT_MINUTE_I;
3
uint8_tALERT_MINUTE_II;
4
uint8_tALERT_MINUTE_III;
5
uint8_tALERT_MINUTE_IV;
6
...
Ist aber immer noch recht komplex lesbar (das ist lateinische/römische
Nummerierung), daher wäre es noch besser arabische Zahlen zu benutzten:
1
...
2
uint8_tALERT_MINUTE_1;
3
uint8_tALERT_MINUTE_2;
4
...
Das ist noch besser lesbar, jedoch immer noch recht komplex
automatisierbar (Programmierer sind ein recht schreibfaules Volk ;))
weshalb der ein und andere von uns wohl auf die Idee käme, es so zu
definieren:
1
...
2
uint8_tALERT_MINUTE[8];
3
...
Da könnte man z.B. mit ner for-Schleife ruck-zuck alle Werte durchgehen,
auslesen, verändern, etc.pp.
Uwe K. schrieb:> Das heißt?
Dass man schon beim Coden davon ausgeht, wie der Compiler den ganzen
Kladeradatsch im Speicher anlegen werden wird. Das kann Probleme machen
wenn man sich verschätzt hat, eine andere Optimierungsfunktion des
Compilers wählt, den Datensatz erweitern will usw.
M. K. schrieb:> Uwe K. schrieb:>> Das heißt?>> Dass man schon beim Coden davon ausgeht, wie der Compiler den ganzen> Kladeradatsch im Speicher anlegen werden wird. Das kann Probleme machen> wenn man sich verschätzt hat, eine andere Optimierungsfunktion des> Compilers wählt, den Datensatz erweitern will usw.
1
typedefenum
2
{
3
SYNC_ERROR_CNT,
4
SYNC_SUCCESS_CNT,
5
6
MAX_BYTE16_ENTRYS,
7
}bit16_enum;
8
9
uint16_tarr[MAX_BYTE16_ENTRYS-1];
Was kann der Kompilert dort anders machen mit einer anderen
Kompilierungsstufe?
Wenn ich mich auf die Byte Reihenfolge nicht verlassen kann..
Uwe K. schrieb:> typedef enum> {> SYNC_ERROR_CNT,> SYNC_SUCCESS_CNT,>> MAX_BYTE16_ENTRYS,> }bit16_enum;>> uint16_t arr[MAX_BYTE16_ENTRYS-1];>> Was kann der Kompilert dort anders machen mit einer anderen> Kompilierungsstufe?>> Wenn ich mich auf die Byte Reihenfolge nicht verlassen kann..
In deinem ursprünglichen Beitrag hattest du ein Struktur-Member mit
einem enum Typ. Jetzt steht hier nur noch ein typedef (in einem
struct??). Sagen wir du hättest das hier:
Mit O0 könnte er (auf einer 32-bit architektur) 32-bit enums machen
(letztere Variante) und für Os das enum packen und erstere Variante
nehmen. In deinem EEPROM steht dann letzere Variante. Und dein Os Code
lädst dann type_1 in byte:0
Uwe K. schrieb:> Sollte man "enums" lieber nicht als Member einer Struktur> mitgeben?
Ja. Zumindest dann nicht, wenn die Größe aus irgend einem Grund eine
Rolle spielt. Ich tendiere dazu immer Typen fester Breite zu nehmen und
mit enums nur dazu passende Konstanten.
Ichkriegmich Nichtmehr schrieb:> Faszinierend.>> Eine Variable mit <byte16> zu benennen grenzt schon> wahrlich an Genialität.
Stimmt schon. Da muss ich noch dran feilen.
x^2 schrieb:> Uwe K. schrieb:>> Sollte man "enums" lieber nicht als Member einer Struktur>> mitgeben?>> Ja. Zumindest dann nicht, wenn die Größe aus irgend einem Grund eine> Rolle spielt. Ich tendiere dazu immer Typen fester Breite zu nehmen und> mit enums nur dazu passende Konstanten.
In meinem Fall, sollten die "enums" einfach nur den Index der aktuell
benötigen Variable "ersichtlicher" machen.
Die enums sind ja in diesem Fall auch konstant.
Enums sind immer vom Typ int, d.h. je nach Architektur signed 16 oder 32
Bit. Daher ist enum als Typangabe zwar zulässig, aber ungebräuchlich.
Unter c sind Enums einfach nur eine anderer Schreibweise für
fortlaufende Defines, d.h. sie schränken nicht den Wertebereich von
Variablen ein.
Z.B.: