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
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)
guest schrieb: > Nein, nicht direkt der XC32, sondern der ARM-Core Deines PIC32, MIPS Core, nicht ARM.
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.
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
Danke schonmal für Antworten. Also um sicher zu gehen, einfach innerhalb eines Structs den gleichen Variablen-Typ verwenden?
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.
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
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".
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?
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
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.
Bernd K.: Danke, ich glaube, das ist das, was ich (vorerst) am einfachsten umsetzen werde.
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.