Forum: Compiler & IDEs WinAVR-20080610: mit -Os kaputtoptimiert ?


von Oleg R. (m_bedded)


Lesenswert?

Ich habe ein Phänomen mit WinAVR-20080610 + AStudio. Wie es für mich 
aussieht, hat -Os etwas zu viel wegoptimiert.

Ein Mega32 soll ein SPI-Slave sein, der 16 Bytes Daten zur Abholung 
bereitstellt. Alles ganz einfach: im ewigen Zyklus wird SlaveSelect 
überwacht (wenn 1->0, Zähler auf 0 setzen). Und im ISR(SPI_STC_vect) den 
Zähler inkrementieren und das nächste Byte in SPDR geladen.

Dies funktioniert auch in Hardware, wenn die Optimierung ausgeschaltet 
ist. Wird aber -Os benutzt, passiert folgendes. Der Zähler wird im 
ewigen Zyklus nicht mehr auf 0 gesetzt. Scheinbar hält der Compiler die 
Anweisung "SpiBufPtr = 0" für eine ohne Auswirkung, obwohl eine ISR eben 
diesen Zähler nutzt.

Was mach' ich bloß falsch?

Hier Ausschnitt aus main():
1
  while(1)
2
  {
3
    cli();
4
    //SPI slave select edge (nSS falling edge)
5
    if (!(PINB & 0x10)) {
6
      if (prev_nSS) {
7
        PrepSpiSndBuf();
8
        SpiBufPtr = 0; // <---- diese Anweisung fehlt nachher
9
        SPDR = SpiSndBuf[SpiBufPtr];
10
      }
11
      prev_nSS = 0;
12
    } else {
13
      prev_nSS = 1;
14
    }
15
    
16
    if (SpiBufPtr > PKT_SIZE-1) { //receive buffer full
17
      ReadSpiRecBuf();
18
    }
19
    sei();
20
  }

Und so wurde es übersetzt:
1
  while(1)
2
  {
3
    cli();
4
 296:  f8 94         cli
5
    //SPI slave select edge (nSS falling edge)
6
    if (!(PINB & 0x10)) {
7
 298:  b4 9b         sbis  0x16, 4  ; 22
8
 29a:  02 c0         rjmp  .+4        ; 0x2a0 <main+0x3a>
9
 29c:  81 e0         ldi  r24, 0x01  ; 1
10
 29e:  04 c0         rjmp  .+8        ; 0x2a8 <main+0x42>
11
      if (prev_nSS) {
12
 2a0:  88 23         and  r24, r24
13
 2a2:  11 f0         breq  .+4        ; 0x2a8 <main+0x42>
14
        PrepSpiSndBuf();
15
        SpiBufPtr = 0;
16
        SPDR = SpiSndBuf[SpiBufPtr];
17
 2a4:  9f b9         out  0x0f, r25  ; 15
18
 2a6:  80 e0         ldi  r24, 0x00  ; 0
19
    }
20
    
21
    if (SpiBufPtr > PKT_SIZE-1) { //receive buffer full
22
      ReadSpiRecBuf();
23
    }
24
    sei();
25
 2a8:  78 94         sei
26
 2aa:  f5 cf         rjmp  .-22       ; 0x296 <main+0x30>

von Andreas K. (a-k)


Lesenswert?

"volatile" bei den gemeinsamen Variablen von Prog und Interrupt-Routine 
vergessen.

von Oleg R. (m_bedded)


Lesenswert?

stimmt!! Danke vielmals!

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.