Inkrementieren von Bits in Bitfeldern

Gast #1639736
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
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
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
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.
Gast
Hallo,

ich nochmal.
Ich habs es gerade nochmal auf der echten Hardware ausprobiert.
Da ist es genauso.
Der Fehler muss also doch woanders liegen...
Hat jemand ne Idee?

Gruß,
Hans
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
@Hans: Vermutlich hast du den gleichen defekten Debugger diesmal auf die 
echte Hardware gehetzt. Naturgemäss mit dem gleichen Ergebnis. Nicht die 
Simulator-Engine ist das Problem, sondern der entweder darauf oder auf 
der echten Hardware aufsitzende Debugger.
Gast
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.
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

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.