Forum: Mikrocontroller und Digitale Elektronik Speicherort Variabeln


von Pascal E. (nimmzwei)


Lesenswert?

Hallo Gemeinde,

ich initialisiere meine Variabeln wie folgt:
1
unsigned char    EE_actualSpeed          = 0;
2
unsigned short    EE_Test              = 0;
3
unsigned char    EE_minPWM            = 10;

Nun müsste man doch meinen, dass wenn ich mit einem Zeiger
1
&EE_actualSpeed
 die Adresse 9299 auslese. Die folgende Variabel
1
 &EE_Test
 an der Adresse 9300 befinden müsste.

Dies ist leider nicht so. Kann ich da meinem xMega irgendwie unter die 
Arme greiffen um dem Compiler zu sagen, dass die Adressen hier 
eingehalten werden müssen.

Besten Dank im Voraus

von Falk B. (falk)


Lesenswert?

@ Pascal E. (nimmzwei)

>ich initialisiere meine Variabeln wie folgt:

>unsigned char    EE_actualSpeed          = 0;
>unsigned short    EE_Test              = 0;
>unsigned char    EE_minPWM            = 10;

Wo stehen die? In einer Funktion oder global?

>&EE_actualSpeed

> die Adresse 9299 auslese. Die folgende Variabel

> &EE_Test

> an der Adresse 9300 befinden müsste.

Nein. Die Reihenfolge und Lage von einzelnen Variablen ist NICHT 
garantiert. Das ist C, nicht ASM.

>Dies ist leider nicht so. Kann ich da meinem xMega irgendwie unter die
>Arme greiffen um dem Compiler zu sagen, dass die Adressen hier
>eingehalten werden müssen.

Ja, indem du diese Variablen in einem struc zusammenfasst. Dort MUSS der 
Compiler die Lage einhalten.

von Mark B. (markbrandis)


Lesenswert?

Pascal E. schrieb:
> dass die Adressen hier eingehalten werden müssen.

Wozu?

von Falk B. (falk)


Lesenswert?

@ Mark Brandis (markbrandis)

>> dass die Adressen hier eingehalten werden müssen.

>Wozu?

Berechtigte Frage. Denn normaleweise hat man in C mit absoluten Adressen 
nix zu tun, man greift immer über den Variablennamen auf Variablen zu.

von Ponter (Gast)


Lesenswert?

Falk Brunner schrieb:
> man greift immer über den Variablennamen auf Variablen zu.
oder Pinter, welch Adresse jetzt aber genau im Pointer steht 
interessiert meistens niemanden.

von Pascal E. (nimmzwei)


Lesenswert?

Danke für die rege Beteiligung

Um Missverständnisse zu beseitigen:

Ich brauche keine Fixe Adresse, wo das Zeug steht ist im Prinzip egal. 
Wichtig ist, dass die Reihenfolge innerhalb dieses Blocks "richtig" ist.

Geht darum einen Offsett für die Ablage ins EEprom zu berechnen und so 
automatisiert die Variabeln zu übertragen.

Interessant ist für mich nur, ob mein Wunsch vom Compiler erfüllt werden 
kann.

von PittyJ (Gast)


Lesenswert?

Dann solltest du wirklich mit einem struct arbeiten, und die Variablen 
darin zusammen fassen.

von Pascal E. (nimmzwei)


Lesenswert?

PittyJ schrieb:
> Dann solltest du wirklich mit einem struct arbeiten, und die Variablen
> darin zusammen fassen.

Bin mir nicht sicher, ob ich das soll.

Habe die Lösung auf einem anderen Controller bereits lauffähig gesehen.
Leider habe ich nicht ansatzweise eine Idee wie ich dem AVR-GCC meinen 
Wunsch aufdrücken kann.

von Peter II (Gast)


Lesenswert?

Pascal E. schrieb:
> Bin mir nicht sicher, ob ich das soll.

warum nicht, welche bedenken gibt es?

> Habe die Lösung auf einem anderen Controller bereits lauffähig gesehen.
> Leider habe ich nicht ansatzweise eine Idee wie ich dem AVR-GCC meinen
> Wunsch aufdrücken kann.
weil C außer mit einer struct (packed!) dafür keine Möglichkeiten 
bieten.

von MaWin (Gast)


Lesenswert?

Pascal E. schrieb:
> Nun müsste man doch meinen, dass wenn ich mit einem Zeiger
> Die folgende Variabel an der Adresse 9300 befinden müsste.

Nein.
Manche Compiler ordnen den Platz erst zu, wenn die Variabke benutzt 
wurde, und verwenden geeinsame Plätze für Variabken, die nicht gemeinsam 
verwendet werden können.
1
 void func(int i)
2
{
3
    int n=5*i;
4
    if(n>10)
5
    {
6
        int a=i-n;
7
        printf("a=\n",a);
8
    }
9
    else
10
    {
11
        int b=n-i;
12
        printf("b=\n",b);
13
    }
14
}
Da kann sich der Compiler entscheiden, n gar nicht zu speichern und a 
und b auf denselben Speicherort zu lege.

> Kann ich da meinem xMega irgendwie unter die
> Arme greiffen um dem Compiler zu sagen, dass die Adressen hier
> eingehalten werden müssen.
1
struct
2
{
3
    unsigned char    EE_actualSpeed;
4
    unsigned short    EE_Test;
5
    unsigned char    EE_minPWM;
6
}
7
EE_struct={0,0,10};
Achtung, Alignment wird gegebenenfalls EE_test nicht auf 
EE_actualSpeed+1 legen, aber eventuell EE_minPW in den Platz zwischen 
EE_actusalSpeed und EE_Test schieben, also achte auf das eingestellte 
Alignment;

von Max H. (hartl192)


Lesenswert?

Wenn du die Struktur mit __attribute__((packed)) erstellst, dann kannst 
du dem Compiler auch verbieten irgendwelche Padding-Bytes einzufügen.

von Falk B. (falk)


Lesenswert?

@Pascal E. (nimmzwei)

>Wichtig ist, dass die Reihenfolge innerhalb dieses Blocks "richtig" ist.

>Geht darum einen Offsett für die Ablage ins EEprom zu berechnen und so
>automatisiert die Variabeln zu übertragen.

Auch dafür braucht man keine feste Reihenfolge, denn auch EEPROM 
Variablen werden über den NAMEN angesprochen, nicht die reale Adresse. 
Um die realen
1
uint16_t varRAM;
2
uint16_t varEE EEPROM;
3
4
eeprom_write_word(&varEE, varRAM);
5
varRAM = eeprom_read_word(&varEE);

>Habe die Lösung auf einem anderen Controller bereits lauffähig gesehen.

Na dann zeig sie doch mal hier.

>Leider habe ich nicht ansatzweise eine Idee wie ich dem AVR-GCC meinen
>Wunsch aufdrücken kann.

Lese- und Schreibzugriffe laufen beim avr gcc über Funktionen. Siehe 
Doku der libc.

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#EEPROM

von Klausy (Gast)


Lesenswert?

Im AVR Codevision gibt es die möglichkeit über @ die Adresse 
festzulegen.
also: unsigned char  EE_actualSpeed@0x5000;
Ansonsten gibts evtl. sowas wie
#pragma DATA_SECTION(...);

von Thomas (Gast)


Lesenswert?

Hallo Pascal,

eigentlich gibt es nur drei Möglichkeiten, die sinnvoll sind:

a) Du vertraust dem C-Compiler (und glaub mir, der weiß was er tut!) und 
nutzt normale C-Syntax um auf Variablen zuzugreifen (Pointer, sowie 
Pointer-Arithmetik),

b) Du nutzt eine Struktur, am besten gepackt, und kannst mit 
einigermaßen Gewissheit sagen wie der Compiler diese Sturktur füllt und 
könntest nun von einer vorherigen Variable in der Struktur die Adresse 
der nächsten Ableiten - macht aber ja nicht so richtig Sinn weil du 
gleich den Variablennamen der Variable in der Struktur nehmen kannst,

c) Du weißt es besser als der C-Compiler und programmierst entweder die 
Funktion, oder gleich das komplette Programm selber in Assembler.

Sinnvollerweise wirds also wohl a) oder c) sein.

Thomas

von Axel S. (a-za-z0-9)


Lesenswert?

Thomas schrieb:
> eigentlich gibt es nur drei Möglichkeiten, die sinnvoll sind:

Es gibt mindestens noch eine 4. Möglichkeit:

d) du definierst eine eigene Sektion im EEPROM der du dann im Linker- 
skript einen Adreßbereich zuweisen kannst und weist den Compiler an, 
deine Variablen (oder die struct) in diese Sektion zu legen.

Im Prinzip macht die EEMEM Deklaration nichts anderes, nur daß die halt 
den gesamten EEPROM als eine Sektion behandelt.

von Karl H. (kbuchegg)


Lesenswert?

Thomas schrieb:

> b) Du nutzt eine Struktur, am besten gepackt, und kannst mit
> einigermaßen Gewissheit sagen wie der Compiler diese Sturktur füllt und
> könntest nun von einer vorherigen Variable in der Struktur die Adresse
> der nächsten Ableiten - macht aber ja nicht so richtig Sinn weil du
> gleich den Variablennamen der Variable in der Struktur nehmen kannst,

Oder aber. Man kopiert ganz einfach das komplette Strukturobjekt so wie 
es ist, ohne sich weiter um seine inneren Aufbau kümmern zu müssen.
Das macht dann am allermeisten Sinn, weil man ein Ding weniger hat, um 
das man sich kümmern muss.
1
struct MotorData
2
{
3
  unsigned char   actualSpeed;
4
  unsigned short  Test;
5
  unsigned char   minPWM;
6
};
7
8
struct MotorData Motor1 = { 0, 0, 10 };   // Das Objekt im Speicher
9
10
struct MotorData EE_Motor EEMEM;          // Die Variante davon im EEPROM
11
12
.....
13
   // Vom EEProm in den Speicher
14
   eeprom_read_block( &Motor1, &EE_Motor, sizeof( Motor1 ) );
15
...
16
  // Vom Speicher ins EEPROM
17
   eeprom_write_block( &Motor1, &EE_Motor, sizeof( Motor1 ) );


Pascal schrieb
> Bin mir nicht sicher, ob ich das soll.

Doch. Genau das sollst du. Und wenn du schon dabei bist, sollst du auch 
noch ein C-Buch kaufen und durcharbeiten.

: Bearbeitet durch User
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
Noch kein Account? Hier anmelden.