Forum: Mikrocontroller und Digitale Elektronik [STM32F407VG, Discovery-board] Timer-interrupt verwirrt mich


von Luigi (Gast)


Angehängte Dateien:

Lesenswert?

Servus zusammen,

ich steige gerade wieder auf den STM32 ein (hatte länger nix damit 
gemacht und fange bei den basics an) aber leider bin ich jetzt auf ein 
Problem gestoßen, dessen Hintergrund ich gerne Verstanden hätte. Sollte 
auch super leich zu reproduzieren sein, sofern ein STM32F4-discovery 
board und CooCox CoIDE vorliegen. (Damit hätte ich dann wohl auch meine 
Umgebung definiert)
Die veränderten Dateien habe ich angehängt, der Rest ist von den 
Standard-Libs, die man in CoIDE einfach aktiviert und die dann 
automatisch ins Projekt kopiert werden.

Folgende Aufgabe :
Ich will eine LED innerhalb einer Interruptroutine ein- und ausschalten. 
Etwa im 1s Zyklus.

Das Problem :
So gehts :
1
void TIM2_IRQHandler(void)
2
{
3
  static uint8_t i = 0;
4
5
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
6
7
  GPIO_ToggleBits(GPIOD, GPIO_Pin_13); // LD3, orange
8
9
  if( 2 == ++i )
10
  {
11
    GPIO_ToggleBits(GPIOD, GPIO_Pin_14); // LD5, red
12
    i=0;
13
  }
14
}
So gehts nicht :
  (nur die rote LED blinkt, die orange nicht)
1
void TIM2_IRQHandler(void)
2
{
3
  static uint8_t i = 0;
4
5
  GPIO_ToggleBits(GPIOD, GPIO_Pin_13); // LD3, orange
6
7
  if( 2 == ++i )
8
  {
9
    GPIO_ToggleBits(GPIOD, GPIO_Pin_14); // LD5, red
10
    i=0;
11
  }
12
13
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
14
}

Woran kann das liegen?
Ich stehe vollkommen auf dem Schlauch. Für mich ist das gerade völlig 
unerklärlich!

Vielen Dank für eure Hilfe!
Grüße
Luigi

von Leo B. (luigi)


Lesenswert?

PS:

Hervorzuheben ist vielleicht, dass nur die Zeile
1
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
in der Position verändert wird. Das ist der einzuge Unterschlied 
zwischen "funktionier" und "funktioniert nicht".



PPS:
war nicht eingelogt, bin aber ich

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Da gabs mal was hier bei mc.net, man muss erst das Interrupt Flag 
löschen, bevor man an GPIOs rumfummelt. Ist mir auch mal beim STM32F100 
untergekommen.
Frag mich aber bitte nicht mehr nach dem Thread - ich habe nur diese 
Bemerkung in meinen Sourcen gefunden:
1
void TIM1_UP_TIM16_IRQHandler(void){
2
//uint8_t speedRegTicks = 0;
3
// microcontroller.net : Clear the IT pending bit before doing any GPIO stuff
4
TIM_ClearITPendingBit(TIM1,(TIM_IT_Update | TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3));
5
  LED_GPIO_PORT->BSRR = ERROR_LED_PIN;  // debug
6
//....

von Jim M. (turboj)


Lesenswert?

Luigi schrieb:
> Woran kann das liegen?
> Ich stehe vollkommen auf dem Schlauch. Für mich ist das gerade völlig
> unerklärlich!

TIM_ClearITPendingBit() kommt im 2. Falls zu spät. Der µC braucht ein 
paar Takte bis das Timer Peripherial die Interrupt Anforderung 
wirklich zurück nimmt - man bedenke z.B. den Schreib Puffer.

Dummerweise macht der µC dadurch beim Interrupt Return ein Tail-Chain 
wieder in denselben Handler, der dadruch 2x hintereinander aufgerufen 
wird. Du solltest bei der roten LED die doppelte Frequenz erkennen 
können.

Abhilfe: Entweder rechtzeitig Flag zurück setzen (1. Variante) oder 
nochmal ein Dummy Lesezugriff auf die Hardware ausführen (z.B. irgenden 
Register lesen).

von Leo B. (luigi)


Lesenswert?

Jim M. schrieb:
> TIM_ClearITPendingBit() kommt im 2. Falls zu spät. Der µC braucht ein
> paar Takte bis das Timer Peripherial die Interrupt Anforderung
> wirklich zurück nimmt - man bedenke z.B. den Schreib Puffer.
>
> Dummerweise macht der µC dadurch beim Interrupt Return ein Tail-Chain
> wieder in denselben Handler, der dadruch 2x hintereinander aufgerufen
> wird. Du solltest bei der roten LED die doppelte Frequenz erkennen
> können.

Eindeutig, du hast recht. Vielen Dank. Das Erklärt zu 100% das Phänomen.
Kurz Warten (2*NOP) nach dem rücksetzten ist ebenfalls eine Lösung, zu 
kurz warten (1*NOP) löst das Problem nicht (ich sage mal: q.e.d.)



Der vollständigkeit halber, so gehts auch :
1
void TIM2_IRQHandler(void)
2
{
3
  static uint8_t i = 0;
4
5
  GPIO_ToggleBits(GPIOD, GPIO_Pin_13); // LD3, orange
6
7
  if( 2 == ++i )
8
  {
9
    GPIO_ToggleBits(GPIOD, GPIO_Pin_14); // LD5, red
10
    i=0;
11
  }
12
13
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
14
15
  __asm volatile ("NOP");
16
  __asm volatile ("NOP");
17
}

Vielen Dank!

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.