Forum: Mikrocontroller und Digitale Elektronik PIC32/XC32: Attribute 'Packed'


von Master S. (snowman)


Lesenswert?

Hallo zusammen

Ich habe structs, die genau 32Bytes sein sollen, weil ich die in 
32Byte-EEPROM-Blocks abspeichere. Verwenden tue ich einen PIC32 mit dem 
XC32.

typedef struct {
   char cA;    // 8 bit
   char cB;    // 8 bit
   char cC;    // 8 bit
   short sA;   // 16 bit
   ...         // restliche Bytes
} __attribute__((packed)) StructElement1;

typedef struct {
   char cA;    // 8 bit
   char cB;    // 8 bit
   char cC;    // 8 bit
   char cD;    // 8 bit
   short sA;   // 16 bit
   ...         // restliche Bytes
} __attribute__((packed)) StructElement2;

StructElement1 E1;
StructElement2 E2;

void TestFunction(short *i) {...}

Wenn ich nun "TestFunction(&E1.sA);" verwende verabschiedet sich das 
Programm ins Nirvana, bei "TestFunction(&E2.sA);" jedoch nicht.

Lösung:
a) Sehe ich das richtig, dass der XC32 die shorts immer auf einer 
geraden(?) Adresse braucht; ich also im gemischten Struct zuvor eine 
gerade Anzhal Char-Variablen brauche? Uhhh, gefällt mir gar nicht sowas, 
ich möchte mich nicht auf Zufall-Compilierung verlassen.
b) Meine 32Byte-Structs nur mit Short-Variablen machen. Wie kann ich da 
sicher sein, dass mir der Compiler aus Laufzeitoptimierung, diese Shorts 
als 16bit und nicht als 32bit im Struct abspeichert? Resp. das Struct 
dann je nach Compilerverfassung 64Byte gross ist, resp. dann nicht mehr 
in ein EEPROM-Block passt.
c) ... ?

Was würded ihr vorschlagen?

Vielen Dank für Ratschläge! :-)

: Bearbeitet durch User
von guest (Gast)


Lesenswert?

Master S. schrieb:
> a) Sehe ich das richtig, dass der XC32 die shorts immer auf einer
> geraden(?) Adresse braucht;

Nein, nicht direkt der XC32, sondern der ARM-Core Deines PIC32, der kann 
16-Bit Zugriffe nur auf graden Adressen.

Master S. schrieb:
> b) Meine 32Byte-Structs nur mit Short-Variablen machen. Wie kann ich da
> sicher sein, dass mir der Compiler aus Laufzeitoptimierung, diese Shorts
> als 16bit und nicht als 32bit im Struct abspeichert?

Dann nimm "uint16_t", das ist exakt 16Bit breit (oder der Compiler, 
repektive die Standardlibrary ist Schrott)

von (prx) A. K. (prx)


Lesenswert?

guest schrieb:
> Nein, nicht direkt der XC32, sondern der ARM-Core Deines PIC32,

MIPS Core, nicht ARM.

von (prx) A. K. (prx)


Lesenswert?

Master S. schrieb:
> Wenn ich nun "TestFunction(&E1.sA);" verwende verabschiedet sich das
> Programm ins Nirvana, bei "TestFunction(&E2.sA);" jedoch nicht.

Das kann nicht funktionieren, wenn die zugrundeliegende Maschine 
Zugriffe nur mit passendem Alignment durchführen kann. Der Compiler kann 
zwar Zugriffe der Form
  ... = E1.sA;
entsprechend umständlich byteweise durchführen, weil er weiss, dass die 
Struct packed ist. Aber wenn du die Adresse eines solchen Objekts einem 
Pointer zuweist, dann geht diese Information verloren.

von guest (Gast)


Lesenswert?

A. K. schrieb:
> MIPS Core, nicht ARM.

Ooops, bei ARM taucht das Problem aber auch auf.

von (prx) A. K. (prx)


Lesenswert?

guest schrieb:
> Ooops, bei ARM taucht das Problem aber auch auf.

Teils. Manche ARMe können misaligned accesses. Während aber die meisten 
CPUs, die es nicht können, darauf unubersehbar mit einem Trap antworten, 
liefern die klassischen ARMe einfach das ab, was bei der Adressierung in 
Verbindung mit dem von den untersten 2 Bits gesteuerten 
Barrel/Bytelane-Shifter rauskommt.

: Bearbeitet durch User
von Master S. (snowman)


Lesenswert?

Danke schonmal für Antworten. Also um sicher zu gehen, einfach innerhalb 
eines Structs den gleichen Variablen-Typ verwenden?

von guest (Gast)


Lesenswert?

Master S. schrieb:
> einfach innerhalb
> eines Structs den gleichen Variablen-Typ verwenden

Wenn dann nur bei 'packed' Structs. Wenn man auf das Alignment achtet 
muß das  aber da auch nicht sein.
Ich würd die Structs allerdings nicht packen sondern die Werte Byteweise 
aus dem EEPROM holen und passend zusammenbauen.

von Master S. (snowman)


Lesenswert?

guest schrieb:
> Ich würd die Structs allerdings nicht packen sondern die Werte Byteweise
> aus dem EEPROM holen und passend zusammenbauen

Naja, das wären dann total 512 Bytes, die ich beim EEPROM schreiben und 
lesen rumschubsen muss. Und wie mache ich das mit 32bit-Floats?

Da scheint mir auf Aligment zu achten einfacher. Wie sage ich aber dem 
Compiler, dass er den "Beginn" eines solchen Structs immer schön auf den 
Start seiner hanbaren 32bit-Adresse legt?

: Bearbeitet durch User
von guest (Gast)


Lesenswert?

Master S. schrieb:
> Wie sage ich aber dem
> Compiler, dass er den "Beginn" eines solchen Structs immer schön auf den
> Start seiner hanbaren 32bit-Adresse legt?

Das macht der sowieso so daß es passt (es sei denn Du sagst ihm explizit 
was anderes).
Ansonsten RTFM, da findest Du dann z.B. was über "__align(alignment) 
specifier".

von guest (Gast)


Lesenswert?

Master S. schrieb:
> Naja, das wären dann total 512 Bytes, die ich beim EEPROM schreiben und
> lesen rumschubsen muss. Und wie mache ich das mit 32bit-Floats?

Wenn Du 16 verschiedene Structs hast? Na und, wieviel tausendmal pro 
Sekunde willst Du das tun, daß das ein Problem ist?

von Master S. (snowman)


Lesenswert?

Ich mache mir da weniger Sorgen um Ressourcen/Zeit sondern um meine 
Faulheit, das explizit auszucoden, wenn es eventuell einfacher ginge - 
ich lerne lieber von anderen als mühselig aus eigenen Fehlern ;-)

RTFM: Ja... Wieviel RTFM sollte man betreiben und wieviel sollte man tun 
und Hilfe in einem Forum erwarten und geben?

: Bearbeitet durch User
von Bernd K. (prof7bit)


Lesenswert?

Ordne die Elemente im struct so an dass 16bit an geraden und 32bit an 
durch vier teilbaren offsets zu liegen kommen. Also der Offset immer 
durch die Größe des jeweiligen Elements teilbar ist. Dann ist es 
portabel und Du brauchst kein packed.

von Master S. (snowman)


Lesenswert?

Bernd K.: Danke, ich glaube, das ist das, was ich (vorerst) am 
einfachsten umsetzen werde.

von Bernd K. (prof7bit)


Lesenswert?

Hier ist auch noch Literatur drüber:
http://www.catb.org/esr/structure-packing/

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.