Forum: Mikrocontroller und Digitale Elektronik ARM7: Critical Section bzw. Mutex programmieren?


von Peter (Gast)


Lesenswert?

Hallo,
Ich möchte Code absichern, so daß er nicht gleichzeitig vom 
Hauptprogramm und von Interrupt-Routinen betreten werden kann. Einfach 
Interrupts disablen und danach wieder einschalten wird nicht funzen, 
weil dir Funktionen selbst aus einer ISR aufgerufen werden könnten. 
Reicht es, wenn ich das CPSR zwischenspeichere und danach wieder 
restauriere?

von Andreas K. (a-k)


Lesenswert?

Interrupts abschalten. Ob alle, oder bloss den betreffenden, kannst du 
dir aussuchen.

Eine Mutex ist ein RTOS-Konstrukt und hindert Zugriff durch 
konkurrierende Prozesse indem ggf. der eine auf den anderen wartet. Bei 
Interrupts lässt sich das schlecht machen.

von Peter (Gast)


Lesenswert?

> Interrupts abschalten. Ob alle, oder bloss den betreffenden, kannst du
> dir aussuchen.

Naja, aber was passiert wenn ich in einer ISR die Interrupts ab- und 
danach wieder einschalte. Das funktioniert doch nicht, oder. Beispiel:
1
// Diese Funktion darf nicht gleichzeitig betreten werden
2
void LockedFunction (void)
3
{
4
  __disable_interrupt();
5
  // ...
6
  // Weiterer Code
7
  // ...
8
  __enable_interrupt();
9
}
10
11
// Hauptprogramm
12
void main ()
13
{
14
  for (;;)
15
  {
16
    // ...
17
    LockedFunction();   // Wäre ja kein Problem
18
    // ...
19
  }
20
}
21
22
// Interrupt Routine
23
void ISR (void)
24
{
25
  // ...
26
  LockedFunction();   // Aber wie mache ich das?
27
  // ...
28
}

von Andreas K. (a-k)


Lesenswert?

Nö, das funktioniert nicht. Drum sieht das auch eher so aus:
1
void LockedFunction (void)
2
{
3
  unsigned savedCPSR = __disable_interrupt();
4
  // ...
5
  // Weiterer Code
6
  // ...
7
  __restore_interrupt(savedCPSR);
8
}

Alternativ kann man nur der betreffende Interrupt abschalten. In der ISR 
ist es meist egal ob man den auch dort zeitweilig mal aus- und 
einschaltet. Hier am Beispiel LPC2000:
1
void LockedFunction (void)
2
{
3
  VICIntEnClr = 1<<UARTInterrupt;
4
  // ...
5
  // Weiterer Code
6
  // ...
7
  VICIntEnable = 1<<UARTInterrupt;
8
}
Wobei man dabei die Verzögerung der Interrupt-Pipeline und des 
Speicherbefehls beachten sollte, weshalb es nach VICIntEnClr einige 
wenige Takte dauern kann, bis das wirklich greift.

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.