Forum: Compiler & IDEs AVR GCC Timer-irqs <-> main Probleme bei Variablen


von Hanns-Jürgen M. (yogy)


Lesenswert?

Hallo,
ich verstehe die Welt nicht mehr, daher, please help.
(Ich verwende AVR Studion 4 mit GNU GCC Compiler für AVR Mega; Sprache: 
Standard "C")
Problem:

Im hauptprogramm setze ich nach der Initialisierung in der 
Hauptprogrammschleife sekündlich eine global deklarierte Steuervariable 
"OneWireFlag", die im Time-Compare-Intterrupt (Timerclock 0,5 us) 
ausgewertet wird. danach wird ein kurzes Stepping durchlaufen, wobei die 
Steuervariable das Ganze händelt.

Soweit, so gut, das geht alles. Am Ende wird die Steuervariable auif 
einen "Endcode", hier 0x88 gesetzt.

Das Hauptprogramm wartet nun in einer while-Schleife auf diesen Endcode.

Solange die Warteschleife nur aus:

while (OneWireFlag != 0x88) {
wdt_reset()
}

besteht, funktioniert es nicht. Die Schleife wird nie verlassen, bzw. 
der Wert von OneWireFlag wird nicht ausgewertet.

Das klappt dann erst, wenn ich zusätzlich eine komplexere Subroutine in 
der Schleife aufrufe. Nur das einfügen von Inline "nop" bringt nichts...

Für mich ist das ein Compilerproblem bzw. ein Optimierungsproblem???

Hat einer eine Idee? Mir fehlen dazu die Erfahrungen mit dem GNU GCC. 
Danke.

So, die Programmschipsel hänge ich mal an:

Ausschnitt aus dem Hauptprogramm:
Aufruf der Subroutine
1
    crc=OneWire_ReadRom();
Die Subroutine (Testversion)
1
U8 OneWire_ReadRom(void)
2
{
3
  U8 i, crc;
4
  OneWire_Write_Byte(0xF0);
5
  crc=0;
6
  return crc;
7
}
8
U8 OneWire_Write_Byte(U8 WriteByte)
9
{
10
  U8 i;
11
  for (i = 0;i < 8; i++){
12
    OneWireFlag = OneWire_Write_Bit(WriteByte & (1 << i));
13
  }
14
  OneWireFlag=0;
15
  return OneWireFlag;
16
}
17
U8 OneWire_Write_Bit(U8 Bitwert)
18
{
19
  if (Bitwert == 0) {
20
    OneWireFlag = 0x10;  // write 0
21
  } else {
22
    OneWireFlag = 0x20;  // write 1
23
  }
24
  while (OneWireFlag != 0x88)  //DIESE BOESE WARTSCHLEIFE
25
  {
26
//    csabs(2,1);  // mit geht, ohne nicht...
27
    wdt_reset();
28
  }
29
  return OneWireFlag;
30
}
Die Timer-Rouine (gekürzt)
1
ISR (TIMER1_COMPC_vect) //fuer 0newire bus / divers
2
{
3
  //  timer zaehlt mit 0.5 us
4
  U16 Icompvalue;
5
  Icompvalue = OCR1C;
6
  if (OneWireFlag == 1) {
7
...............................
8
...............................
9
10
  } else if (OneWireFlag == 0x10) {
11
    OneWirePortWrite &= ~(1<<OneWirePortPin);    //pin = 0
12
    OneWirePortDir |= (1<< OneWirePortPin);    // dir = output
13
    OneWireFlag = 0x11;
14
    Icompvalue += 64*2;  //64 us low
15
    OCR1C = Icompvalue;
16
  } else if (OneWireFlag == 0x11) {
17
//          PORTB ^= 0x80;  /// xtc
18
    OneWirePortDir &= ~(1<<OneWirePortPin);    // Release
19
    OneWireFlag = 0x88;
20
    Icompvalue += 50 * 2;  //50 us wait
21
    OCR1C = Icompvalue;
22
23
  // schreibe 1
24
  } else if (OneWireFlag == 0x20) {
25
    OneWirePortWrite &= ~(1<<OneWirePortPin);    //pin = 0
26
    OneWirePortDir |= (1<< OneWirePortPin);    // dir = output
27
    _noppen();
28
29
30
    OneWireFlag = 0x21;
31
    Icompvalue += 4*2;  //2 us low
32
    OCR1C = Icompvalue;
33
  } else if (OneWireFlag == 0x21) {
34
35
    OneWirePortDir &= ~(1<<OneWirePortPin);    // Releas resp hig
36
    Icompvalue += 64*2;  //64 
37
    OCR1C = Icompvalue;
38
    OneWireFlag = 0x22;
39
  } else if (OneWireFlag == 0x22) {
40
    OneWirePortDir &= ~(1<<OneWirePortPin);    // Release
41
    OneWireFlag = 0x88;
42
    Icompvalue += 50 * 2;  //50 us wait
43
    OCR1C = Icompvalue;
44
45
46
  } else if (OneWireFlag == 0x88) {
47
    Icompvalue += 50*2;  //50 us warten
48
    OCR1C = Icompvalue;
49
  } else if (OneWireFlag == 0x0) {
50
    Icompvalue += 200;  
51
    OCR1C = Icompvalue;
52
  } else  {
53
    Icompvalue += 20000;  //10 ms
54
    OCR1C = Icompvalue;
55
  }
56
}

von Stefan E. (sternst)


Lesenswert?

Hanns-Jürgen "Yogy" Mostert schrieb:
> Solange die Warteschleife nur aus:
>
> while (OneWireFlag != 0x88) {
> wdt_reset()
> }
>
> besteht, funktioniert es nicht. Die Schleife wird nie verlassen, bzw.
> der Wert von OneWireFlag wird nicht ausgewertet.
>
> Das klappt dann erst, wenn ich zusätzlich eine komplexere Subroutine in
> der Schleife aufrufe. Nur das einfügen von Inline "nop" bringt nichts...

Da fehlt dann wohl ein "volatile".

von Hanns-Jürgen M. (yogy)


Lesenswert?

Stefan Ernst schrieb:
> Hanns-Jürgen "Yogy" Mostert schrieb:
>> Solange die Warteschleife nur aus:
>>
>> while (OneWireFlag != 0x88) {
>> wdt_reset()
>> }
>>
>> besteht, funktioniert es nicht. Die Schleife wird nie verlassen, bzw.
>> der Wert von OneWireFlag wird nicht ausgewertet.
>>
>> Das klappt dann erst, wenn ich zusätzlich eine komplexere Subroutine in
>> der Schleife aufrufe. Nur das einfügen von Inline "nop" bringt nichts...
>
> Da fehlt dann wohl ein "volatile".

hmm, wo soll das denn bitte hin?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

In die Definition von OneWireFlag. Woher soll denn der Compiler sonst 
wissen, dass ihm "unterm Arsch" die Variable über eine ISR geändert 
wird?

von Hanns-Jürgen M. (yogy)


Lesenswert?

Ach so, ich hatte doch geschrieben, daß diese Variable GLOBAl deklariert 
wurde als:

U8 OneWireFlag = 0;

von Stefan E. (sternst)


Lesenswert?

Hanns-Jürgen "Yogy" Mostert schrieb:
> hmm, wo soll das denn bitte hin?

Hanns-Jürgen "Yogy" Mostert schrieb:
> Ach so, ich hatte doch geschrieben, daß diese Variable GLOBAl deklariert
> wurde als:
>
> U8 OneWireFlag = 0;

Informiere dich darüber, was "volatile" überhaupt bedeutet, dann weißt 
du auch, wo und warum es hier nötig ist.

von Hanns-Jürgen M. (yogy)


Lesenswert?

volatile wirkt hier zwar überraschednerweise, aber, wie gesagt , 
überaschenderweise.

Laut dem Schirmer-Buch über "C"

"Mit dem Attribut 'volotile' sagen sie über eine Variable aus, daß ihr 
Typ implementierungsabhängige Eigenschaften besitzen kann.Genaueres legt 
der ANSI-Standard hier nicht fest. Insbesondere werden volotile-Objekte 
von der Optimierung beim Compilieren ausgeschlossen"

So, was sagt das jetzt?!

a) Der Compiler verschluckt Variablen, obwohl sie benutzt werden? So was 
hätte mir früher einer implementieren sollen, Au Backe

b) unbekanntes Verhalten im ANSI Dschungel? In der GNU Compiler Doku 
steht nix zu volotile

Aber egal, danke für die Hilfe, es funzt mit volotile. Problem für mich 
hier gelöst.  Happy Halloween :-)

Yogy

von Karl H. (kbuchegg)


Lesenswert?

Hanns-Jürgen "Yogy" Mostert schrieb:
> volatile wirkt hier zwar überraschednerweise, aber, wie gesagt ,
> überaschenderweise.

Nein,  nicht überraschend.

FAQ: Was hat es mit volatile auf sich


> So, was sagt das jetzt?!
>
> a) Der Compiler verschluckt Variablen, obwohl sie benutzt werden?

Das sagt es nicht aus

> Aber egal, danke für die Hilfe, es funzt mit volotile.
Es heißt volAtile.
UNd lies die FAQ. Dann verstehst du auch wo das Problem liegt.

von Hanns-Jürgen M. (yogy)


Lesenswert?

ja, volatile natürlich, sry

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.