Forum: Mikrocontroller und Digitale Elektronik Warum funktioniert Bit-Toggle mit XOR nicht im Interrupt?


von Max M. (maxmicr)


Angehängte Dateien:

Lesenswert?

Hat jemand eine Idee, warum beim STM32F103C8 ein Bit-Toggle per XOR in 
einem Timer-Interrupt nicht funktioniert?
1
void TIM2_IRQHandler() {
2
  GPIOC->ODR ^= GPIO_ODR_ODR13;
3
  TIM2->SR &= ~TIM_SR_UIF;
4
}

Entsprechendes Assembly (sieht okay aus):
1
    71:         GPIOC->ODR ^= GPIO_ODR_ODR13; 
2
0x0800031A 6801      LDR      r1,[r0,#0x00]
3
0x0800031C F4815100  EOR      r1,r1,#0x2000
4
0x08000320 6001      STR      r1,[r0,#0x00]

Sobald ich mit dem Debugger durchsteppe, funktioniert es auch. Nur im 
laufenden Betrieb nicht.

Das hier dagegen funktioniert auch im Betrieb:
1
void TIM2_IRQHandler() {
2
  if(is_led_on) {
3
    GPIOC->ODR &= (uint16_t)( ~GPIO_ODR_ODR13 );
4
    is_led_on = false;
5
  } else {
6
    GPIOC->ODR |= GPIO_ODR_ODR13;
7
    is_led_on = true;
8
  }
9
  TIM2->SR &= ~TIM_SR_UIF;
10
}

Für den jeweiligen Fall erhalte ich die angehängten Messungen mit einem 
Logic Analyzer.

Das funktioniert übrigens auch:
1
  while(true) {
2
    GPIOC->ODR ^= GPIO_ODR_ODR13;
3
    wait(1000000);
4
    GPIOC->ODR ^= GPIO_ODR_ODR13;
5
    wait(1000000);
6
  }

von Jim M. (turboj)


Lesenswert?

Falsch herum, so wäre es richtig:
1
void TIM2_IRQHandler() {
2
  TIM2->SR &= ~TIM_SR_UIF;
3
  GPIOC->ODR ^= GPIO_ODR_ODR13;
4
}


Hintergrund ist der Schreibpuffer im Cortex-M, der dazu führt das der 
Interrupt Handler 2x hintereinander ausgeführt wird, weil das Flag nicht 
rechtzeitig vor dem Tail-Chaining zurück gesetzt wird.

Der nachfolgende GPIO Zugriff ändert dies - nun ist das Interrupt Flag 
im NIVC zurück gesetzt während des Rücksprungs.

von Max M. (maxmicr)


Lesenswert?

Tatsächlich. Vielen Dank!

von Stefan F. (Gast)


Lesenswert?

Jim M. schrieb:
> Hintergrund ist der Schreibpuffer im Cortex-M, der dazu führt das der
> Interrupt Handler 2x hintereinander ausgeführt wird, weil das Flag nicht
> rechtzeitig vor dem Tail-Chaining zurück gesetzt wird.

Wegen dieser Sache hatte ich mal eine andere mutmaßliche Fehlfunktion an 
der ist schier verzweifelte.

Vielleicht sollte ST mal eine Anleitung veröffentlichen, wie man korrekt 
zischen den Zeilen des Referenzhandbuches liest und welche 
Kapitel-Übergreifenden Zusammenhänge es da gibt, die nicht direkt im 
Text stehen.

Wenn man von AVR auf STM32 wechselt, fällt man da sonst in ziemlich 
schockierend kaltes Wasser.

von Peter D. (peda)


Lesenswert?

Bei den Boliden sind Interrupt-Controller und CPU getrennt getaktete 
Einheiten. Daher dauert es ein paar Takte, ehe ein Befehl von der CPU 
beim Interrupt-Controller wirksam geworden ist. Das genaue Verhalten 
sollte aber im Manual zum Interrupt-Controller stehen.

Ähnliches gibt es auch beim asynchronen Timer des AVR (z.B. ATtiny261). 
Da dauert es mehrere Takte, ehe ein Löschen des Interruptflags alle 
Synchronisationsstufen des Timers durchlaufen hat. Der Pferdefuß dabei 
ist, diese Verzögerung ist auch im synchronen Mode wirksam.

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.