Inkrementieren von Bits in Bitfeldern

Gast #1639736
Lesenswert?

Hallo uC-Gemeinde,

ich habe ein Problem mit dem Inkrementieren eines oder mehrerer Bits in 
einem Bitfeld.

Folgender Code inkrementiert alle Member des Bitfelds:
1
static volatile struct{
2
    unsigned a:3;
3
    unsigned b:3;
4
    unsigned c:2;
5
  }status;
6

7
status.a++;

status.a += 1; funktioniert auch nicht.

Die direkte Zuweisung eines Wertes hingegen funktioniert.

Kann mir jemand sagen warum?

Vielen Dank im Voraus.

Gruß,
Hans.
Gast #1639768
Lesenswert?

Hallo A.K.,

der Compiler ist der gcc. Ich glaube nicht, dass der Fehler hier liegt.
Hier dein kompilerbares Beispiel.

Hab leider keine echte Hardware da, aber kann es sein, dass der 
Simulator des AVR-Studios einen Bug hat?
1
static volatile struct{
2
      unsigned char a:3;
3
      unsigned char b:3;
4
      unsigned char c:2;
5
    }status;
6

7
int main(void){
8
  
9

10
    status.a = 0;
11
    status.b = 0;
12
    status.c = 0;
13
    status.a++;
14
}

Gruß,
Hans.
Gast #1639800
Lesenswert?

A. K. schrieb:
> Woran erkennst du in diesem Beispiel, dass das ganze Byte inkrementiert
> wird? Es wird so oder so 1 rauskommen.

Ich schau mir die einzelnen Member im AVR-Simulator an.
"Es wird so oder so 1 rauskommen" -> Versteh grad nicht, was genau du 
mit dieser Aussage meinst...

@Stefan:
Mit der Aussage könnte ich schon mehr anfangen. ;-)
Gast #1639811
Lesenswert?

A. K. schrieb:
> Hans schrieb:
>
>> "Es wird so oder so 1 rauskommen" -> Versteh grad nicht, was genau du
>> mit dieser Aussage meinst...
>
> Vorher:
>   a = 0, b = 0, c = 0. Byte = 0.
> Nachher:
>   a = 1, b = 0, c = 0. Byte = 1.

Ok, das wäre das, was ich erwartet hätte. Der AVR-Simulator sagt aber 
folgendes:

Vorher:
   a = 0, b = 0, c = 0.
Nachher:
   a = 1, b = 1, c = 1.
#1640387
Lesenswert?

Welcher Compilerversion?

Habs hier mit der WinAvr-20090313 ausprobiert.
Der Assemblercode sieht gut aus
1
int main(void){
2
  
3

4
    status.a = 0;
5
  7c:  80 91 60 00   lds  r24, 0x0060
6
  80:  88 7f         andi  r24, 0xF8  ; 248
7
  82:  80 93 60 00   sts  0x0060, r24
8
    status.b = 0;
9
  86:  80 91 60 00   lds  r24, 0x0060
10
  8a:  87 7c         andi  r24, 0xC7  ; 199
11
  8c:  80 93 60 00   sts  0x0060, r24
12
    status.c = 0;
13
  90:  80 91 60 00   lds  r24, 0x0060
14
  94:  8f 73         andi  r24, 0x3F  ; 63
15
  96:  80 93 60 00   sts  0x0060, r24
16
    status.a++;
17
  9a:  90 91 60 00   lds  r25, 0x0060
18
  9e:  9f 5f         subi  r25, 0xFF  ; 255
19
  a0:  97 70         andi  r25, 0x07  ; 7
20
  a2:  80 91 60 00   lds  r24, 0x0060
21
  a6:  88 7f         andi  r24, 0xF8  ; 248
22
  a8:  89 2b         or  r24, r25
23
  aa:  80 93 60 00   sts  0x0060, r24
24
}
25
  ae:  80 e0         ldi  r24, 0x00  ; 0
26
  b0:  90 e0         ldi  r25, 0x00  ; 0
27
  b2:  08 95         ret

Lass dir mal ein List-File erzeugen und sieh nach, was der Compiler 
daraus gemacht hat
Gast #1640415
Lesenswert?

So, jetzt hab glaube ich verstanden zu haben, was da vor sich geht.
1
static volatile struct{
2
    unsigned a:3;
3
    unsigned b:3;
4
    unsigned c:2;
5
  }status;
Für das Struct werden im Speicher 8Bit reserviert. (Erkennbar an den 
daraufolgenden Speicheradressen)

Komischerweise, liest das AVR-Studio 16 Bit ein.
Ich habe aber 2 dieser Structs nebeneinander im Speicher, daher liest er 
wenn Struct1 und Struct2 ist 257 als Wert für Struct1 ein.

Der Fehler ist nicht nur im Simulator, sondern auf dem Atmel läuft der 
Zugriff auch falsch ab, weil Abfragen auf Struct1 == 1 dann falsch 
ausgewertet werden.

Mit
1
static volatile struct{
2
    unsigned char a:3;
3
    unsigned char b:3;
4
    unsigned char c:2;
5
  }status;
funktioniert das Ganze.

Was sagt ihr dazu?

Gruß,
Hans.
#1640426
Lesenswert?

Bis zum Beweis des Gegenteils glaube ich dem Compiler und misstraue der 
Variablenanzeige des Debuggers. Probier mal mit der ursprünglichen 
Version
   volatile unsigned temp;
   ...
   status.a++;
   temp = status.b;
und schau danach rein, was in temp steht. Vermutlich der korrekte Wert.

M.a.W: Du kämpfst grad gegen Gepenster. Weder Compiler noch Simulator 
noch Hardware machen etwas falsch, sondern die Anzeige der Daten ist 
falsch. Hast du wohlmöglich den Optimizer eingeschaltet?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren