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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Master S. (snowman)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


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

MIPS Core, nicht ARM.

von (prx) A. K. (prx)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> MIPS Core, nicht ARM.

Ooops, bei ARM taucht das Problem aber auch auf.

von (prx) A. K. (prx)


Bewertung
0 lesenswert
nicht 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)


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

von guest (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


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

von Bernd K. (prof7bit)


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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.