LPC 17xx Interruptverhalten

Gast #2672108
Lesenswert?

Moin, Moin,

ich hab eine Frage bzgl. der LPC17xx Reihe zwecks Interrupts.

Beispiel:

volatile unsigned int counter;

void TIMER0_IRQHandler(void) {

    if (TIM_GetIntStatus(LPC_TIM0,TIM_MR0_INT) == SET) {
  counter++;
    }
}

wie kann ich ausserhalb des int's sicherstellen, dass während ich in die 
variable counter reinschreibe, dort kein interrupt aktiv ist ?

bei den avr's muss man ja cli() und sei() verwenden, beim lpc hab ich 
auf die schnelle nichts gefunden.
Gast #2672143
Lesenswert?

> bei den avr's muss man ja cli() und sei() verwenden

Muss man nicht. Man kann es verwenden, um den Zugriff innerhalb des 
Nicht-IRQ-Codes atomar zu machen. Es gibt auch bequeme Makros dafür in 
der avr-libc. Es ist aber eine Brachialmethode, weil alle IRQs und nicht 
nur der Timer-IRQ betroffen sind.

Eine Methode unter anderen wäre, mit einen Software-Flag (=> Semaphor) 
zu arbeiten. Im Nicht-IRQ Programmteil wird ein Software-Flag gesetzt, 
bevor die gemeinsame Variable verändert wird und das Software-Flag wird 
gelöscht, wenn das Update abgeschlossen ist. Das Software-Flag wird in 
der ISR entsprechend beachtet z.B. indem die ISR mit/ohne Quittieren des 
IRQ-Auslösers verlassen wird, wenn das Software-Flag gesetzt ist oder 
indem das counter++ dann nicht ausgeführt wird. Was sinnvoll ist, hängt 
von der Programmlogik ab.
Gast #2672160
Lesenswert?

hm, die idee mit dem semaphor ist gut. ich hatte die bisher immer 
verworfen, weil ich davon ausging, dass ich im nicht-IRQ Teil auf die 
Variable zugreifen würde, während der IRQ aktiv ist, aber dieser Fall 
ist ja garnicht möglich.

Kurz und schmerzlos: Danke ;)
#2672463
Lesenswert?

Der Tipp mit der Semaphore wird bei einem Cortex-M3 wohl krachend in die 
Hose gehen, denn diese Prozessoren dürften eine ISR, die ihre Ursache 
nicht zurücksetzt, als Dauerschleife betreiben, ohne auch nur einen 
einzigen Befehl des Hauptprogramms weiter zu kommen.

Mit Semaphoren blockiert man Tasks gegenseitig. Nicht Interrupt-Handler.

Es hilft nix. Wenn die betreffenden Operationen nicht atomar sind, dann 
muss der betreffende Interrupt abgeschaltet werden. Sei es direkt per 
NVIC, sei es per temporärer kontrollierem Priority-Level. Alternativ 
kann man auch mit LDREX/STREX/CLREX arbeiten. Letzteres hat den Vorteil, 
die Latenz nicht negativ zu beeinflussen.

Einfaches Schreiben in eine wortgrosse Variable ist bei einem CM3 
allerdings atomar, da brennt nichts an.
#2672503
Lesenswert?

Beispiel für die o.A. Alternative:

Inkrementieren im Interrupt-Handler:
1
  counter++;
2
  __CLREX();
Dekrementieren im Hauptprogramm:
1
  unsigned value;
2
  do {
3
     value = __LDREXW(&counter) - 1;
4
  } while (__STREXW(value, &counter);
Die __xxxxx Funktionen sind Teil vom CMSIS.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren