Forum: Compiler & IDEs Bitfeld und union


von Tobias P. (hubertus)


Lesenswert?

Hallo allerseits

ich lese von einer SD-Karte das CID-Register. Es beinhaltet ein 128 Bit 
breites Bitfeld. Man kann die einzelnen Teile des Bitfelds als 4 Wörter 
zu je 32 Bits lesen, wobei die Bits

127..96 -> Wort 0
95..64 -> Wort 1
63..32 -> Wort 2
31..0 -> Wort 0

verteilt sind. Ich möchte nun die Teile des Bitfelds mit einer Struktur 
in C auswerten. Man könnte zwar mit Maskierung und Shiften etc. das auch 
erledigen, aber der Cortex M bietet ja extra Befehle für Bitfelder und 
ich denke mir, dass es mit einer Struktur schöner (und auch einfacher) 
gehen müsste:
1
typedef union
2
{
3
  uint32_t cid[4];
4
  struct
5
  {
6
    unsigned mid : 8;
7
    unsigned oid : 16;
8
    uint64_t pnm : 40;
9
    unsigned prv : 8;
10
    unsigned psn : 32;
11
    unsigned rsvd1 : 4;
12
    unsigned mdt : 12;
13
    unsigned crc : 7;
14
    unsigned rsvd2 : 1;
15
  } __attribute__((packed));
16
} cid_t;

Leider geht das so nicht wirklich. Die gelesenen Werte sind Mist. Ich 
habe dann probehalber mal mid und oid auf bekannte Werte gesetzt und 
geschaut, was dabei herauskommt. Setzt man in cid[4] alles auf 0 und 
schreibt iin mid 0xff rein und in oid 0x8001, dann erhalte ich in cid[0] 
den Wert 0x8001ff. Das ist irgendwie nicht ganz richtig, denn mid müsste 
eigentlich auf das MSB abgebildet werden d.h. für mich es müsste, wenn 
das Bitfeld richtig implementiert ist, der Wert 0xff800100 raus kommen 
(entsprechend müsste natürlich ein 0xff800100 in cid[0] einen Wert von 
0xff für mid und einen Wert von 0x8001 für oid ergeben).

Kurz gesagt: wie kann ich die Zuordnung der Bits im Bitfeld so 
hinbiegen, dass mid die obersten 8 Bit von cid[0] abgebildet werden und 
so weiter?

von Clemens L. (c_l)


Lesenswert?

Bitfelder sind nicht portabel, und Compiler-abhängig.

Tobias P. schrieb:
> wie kann ich die Zuordnung der Bits im Bitfeld so hinbiegen,
> dass mid die obersten 8 Bit von cid[0] abgebildet werden und
> so weiter?

Reihenfolge der drei Felder in cid[0] umkehren.

Dabei ist es keine gute Idee, ein Feld mit mehr als 32 Bits zu haben.

: Bearbeitet durch User
von Eric B. (beric)


Lesenswert?

Tobias P. schrieb:
> aber der Cortex M bietet ja extra Befehle für Bitfelder

Wenn du damit das Bit-Banding meinst: mit Bit-Banding kann man einzelne 
bits setzen, nicht aber bitfields.

von Jim M. (turboj)


Lesenswert?

Eric B. schrieb:
> Tobias P. schrieb:
>> aber der Cortex M bietet ja extra Befehle für Bitfelder
>
> Wenn du damit das Bit-Banding meinst: mit Bit-Banding kann man einzelne
> bits setzen, nicht aber bitfields.

Dann schau Dir nochmal den Instruktionssatz genau an. Da gibt es auch 
Bitfield Extract Befehle. Muss in ein 32 Bit Register reinpassen, und es 
gibt keine extra Lade- oder Schreibbefehle, so dass ein Bit setzen dann 
ein read-modify-write Zyklus wird.

von Daniel A. (daniel-a)


Lesenswert?

Tobias P. schrieb:
> struct
>   {
>     unsigned mid : 8;
>     unsigned oid : 16;
>     uint64_t pnm : 40;
>     unsigned prv : 8;
>     unsigned psn : 32;
>     unsigned rsvd1 : 4;
>     unsigned mdt : 12;
>     unsigned crc : 7;
>     unsigned rsvd2 : 1;
>   } __attribute__((packed));

Tobias P. schrieb:
> ich lese von einer SD-Karte das CID-Register.

Ich weise darauf hin, das dies kein geeigneter Anwendungsfall für c 
bitfields ist. Bei bitfields ist das Bit-order und die Reihenfoöge der 
Felder von der ABI festgelegt, deshalb kannst du dich nicht darauf 
verlassen. Ohne bitshifts gehts nicht. Ich würde die Struktur so 
schreiben:
1
struct
2
  {
3
    uint8_t mid;
4
    uint16_t oid;
5
    uint32_t pnm1;
6
    uint8_t pnm2;
7
    uint8_t prv;
8
    uint32_t psn;
9
    uint16_t rsvd1_mdt;
10
    uint8_t crc_rsvd2;
11
  } __attribute__((packed));
Dabei sollte mit hton oder eigenen makros/funktionen die Endiannes 
beachtet werden.

Auf die resultierenden instruktionen hat dass normalerweise keinen 
einfluss.

von Tobias P. (hubertus)


Lesenswert?

Hallo

Danke euch für die Hilfe. Ich habe jetzt alle möglichen Varianten 
durchprobiert und habe es einfach nicht hinbekommen, dass alles richtig 
funktioniert. Ich habe es jetzt also trotzdem mit Bitmaskierungen und 
-shifts gelöst. Gibt keinen schönen Code, aber funktioniert wenigstens 
:-)

Gruss
Tobias

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.