Forum: Mikrocontroller und Digitale Elektronik STM32F4: EXTI-Interrupt-Flag löschen


von Rainer R. (Firma: Reusch Elektronik) (reusch)


Lesenswert?

Hallo STM32F4-Spezialisten!
Ich beschreibe hier ein kleines Problem mit dem STM32F407, das sich zwar 
umgehen lässt, aber trotzdem hätte ich gerne gewusst, warum es so ist.

Gegeben ist die folgende Interrupt-Routine. Durch ein externes Signal 
wird die EXTI-Routine regelmäßig aufgerufen. Mit Timer2 wird der 
zeitliche Abstand zwischen zwei Interrupts ermittelt (Aufwärtszähler). 
(die ausgelesenen Timer-Werte werden in der Hauptschleife über die 
serielle Schnittstelle ausgegeben)
1
void EXTI0_IRQHandler(void)
2
{
3
  //TP2_H;      // Makro für Testpin auf high (für Messung mit Oszi)
4
  Tim2Cnt = TIM2->CNT;  // zeitl. Abstand messen
5
  TIM2->CNT = 0;
6
//  EXTI->PR = EXTI_Line0;  // EXTI_ClearITPendingBit (wenn es hier steht, ist alles ok)
7
  Externe_Routine();  // Berechnungen, dauern ca. 2µs (ist unkritisch)
8
  EXTI->PR = EXTI_Line0;  // EXTI_ClearITPendingBit (wenn es hier steht, treten Fehler auf)
9
  //TP2_L;      // Makro für Testpin auf low (für Messung mit Oszi)
10
}
Die Interrupt-Routine arbeitet, so wie sie oben aufgeführt ist, meistens 
korrekt, d.h. es wird ein Timer-Wert von ca. 37000 ermittelt. Relativ 
häufig tritt jedoch ein Timer-Wert von etwa 100 auf, d.h. die 
Interrupt-Routine wird zweimal hintereinander aufgerufen!

Um das messtechnisch nach zu weisen, ändere ich den Zustand eines 
Test-Pins. Sobald ich jedoch die "TP_"-Zeilen entkommentiere, tritt der 
Fehler nicht mehr auf!

Der Fehler verschwindet auch dann, wenn ich das Interrupt-Flag nicht am 
Ende sondern ganz am Anfang oder aber weiter vorne (wie im Listing 
angedeutet) lösche.

Meine Fragen:
Warum tritt der Interrupt manchmal zweimal auf, wenn das Interrupt-Flag 
am Ende gelöscht wird?
Warum sollte es am Anfang gelöscht werden?

Wenn ich es richtig verstehe, müsste ein gesetztes Interrupt-Flag doch 
verhindern, dass der Interrupt erneut aufgerufen wird. Und um zu 
verhindern, dass ein Aufruf erfolgt während die Interrupt-Behandlung 
noch läuft, ist ein Löschen des Flags am Ende doch eher sinnvoll. Aber 
das ist ja problematisch, wie das Beispiel zeigt.

von dummy (Gast)


Lesenswert?

>Warum tritt der Interrupt manchmal zweimal auf, wenn das Interrupt-Flag
>am Ende gelöscht wird?

Weil das Interrupt Flag etwas braucht um gelöscht zu werden.
D.h. es kann passieren das das Flag beim verlassen des Int.
immer noch gesetzt ist. Die Folge: Noch ein Int.
Also immer am Anfang der Interruptroutine löschen.

von m.n. (Gast)


Lesenswert?

dummy schrieb:
> Weil das Interrupt Flag etwas braucht um gelöscht zu werden.

So ist es. Aber über diese Stelle sind schon Manche gestolpert ;-)
Die CPU rennt mit 168 MHz weiter, während die Peripherie nur mit 42/84 
MHz bedient werden kann.
Wenn es kritisch ist, am besten den erzeugten Code kontrollieren.

von Rainer R. (Firma: Reusch Elektronik) (reusch)


Lesenswert?

Vielen Dank für die Antworten! Das leuchtet ein, insbesondere mit dem 
Hinweis auf 168MHz Core-Takt und 42/84MHz Peripherie-Takt. Ich meine, 
auch schon mal irgendwo (vermutlich hier im Forum) gelesen zu haben, das 
Flag müsse am Anfang gelöscht werden. Mit diesen einleuchtenden 
Erklärungen müsste es allerdings heißen: "nicht ganz am Ende löschen".

von M. Н. (Gast)


Lesenswert?

Hallo,

das Problem ist hier ja schon aufgezeigt. Wollte nur ergänzen, dass man 
mit den Assembler Befehlen DSB und DMB (Data Synchronisation Barrier) 
die CPU anhalten kann bis der Zugriff abgeschlossen ist.

Es sollten C Makros in der CMSIS Header-Datei für den Cortex M4 
definiert sein. Hab den Namen der H-Datei vergessen. Iwie core_cm4.h 
oder so.

Da sind _DMB(); und _DSB(); definiert. Einfach eins von beiden (welches 
ist recht egal) ans Ende der Routine und der Core wartet, bis alle 
Speicherzugriffe durch sind.

also:
1
Handler()
2
{
3
//Code
4
//Flag löschen
5
_DSB();
6
}

von m.n. (Gast)


Lesenswert?

M. H. schrieb:
> Wollte nur ergänzen,

daß man das Alles auch nachlesen kann in: "The definitive guide to ARM 
Cortex-M3 and Cortex-M4 processors" von Joseph Yiu.
Das hatte A.K. mal empfohlen und ist sein Geld wert, da man zum Lesen 
keinen Bildschirm und nur einen ruhigen Ort braucht: Sessel, Sofa, Bett, 
...

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


Lesenswert?

Es lohnt sich auch oft, zu prüfen, ob das IT Bit auch das richtige war:
1
void EXTI9_5_IRQHandler(void)
2
{
3
  if(EXTI_GetITStatus(PLAY_EXTI_LINE) != RESET)
4
  {
5
    /* Clear the EXTI line pending bit */
6
    EXTI_ClearITPendingBit(PLAY_EXTI_LINE);
7
    if (!fastFlags.PlayUpdate) {
8
        fastFlags.PlayUpdate = TRUE;
9
    }
10
  }

: Bearbeitet durch User
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.