Wie sicher erkennen, ob Funktion innerhalb einer ISR aufgerufen wird?

OP #3171615
Lesenswert?

Hallo!

Ich programmiere einen ARM Cortex M3 (NXP LPC1769) und bin auf der Suche 
nach einer Möglichkeit (höchstwahrscheinlich ein Register rauslesen), 
wie ich innerhalb einer Funktion erkennen kann, ob ich mich gerade in 
einer ISR befinde oder nicht. Abhängig davon würden verschiedene Befehle 
ausgeführt werden.

Ich habe nun schon etwas herumexperimentiert und auch das Reference 
Manual zum LPC1769 gewesen, welches Register mir die passende 
Information liefert.

Z.B. habe ich versucht wenn ich mich in der SysTick-ISR befinde, ob das 
"Interrupt Active Bit Register" (IABR) einen Wert != 0 hat. Dies ist 
nicht der Fall. Es hat den Wert 0x00000000. Dies bedeutet, dass kein 
Interrupt aktiv ist. Auch ansonsten habe ich bisher kein Register finden 
können (weder in den NVIC noch in den SC Registern) mit dem ich sicher 
kennen kann, ob ich in einer ISR bin.

Hat jemand von euch eine Idee?

Danke und Grüße,
ferraith
Gast #3171631
Lesenswert?

Wird die Funktion von einer ISR UND außerhalb aufgerufen?

Wenn nicht versuchst du den Kreis eckig zu machen.

Selbst deine Testsequenz wird ja nur dann durchlaufen, wenn gerade keine 
ISR aktiv ist. Sogar eine zwischenzeitliche Unterbrechung wird nicht 
bemerkt - soll ja auch so sein.
Gast #3171635
Lesenswert?

Verschiedene Möglichkeiten:
1.
Zwei verschiedene Funktionen, eine für ISR, eine für allgemeinen Aufruf.

2.
Der Funktion beim Aufruf durch einen Parameter mitteilen, was zu tun 
ist.

3.
Am Anfang der ISR ein globales Flag setzen, das in der funktion 
ausgewertet wird.

Die Reihenfolge gibt meine Empfehlung wieder :-)
OP #3171642
Lesenswert?

@Floh & amateur

das ist exakt was es bereits gibt:

Ich habe zwei Funktionen:
1
int GetTickCountFromISR()
2
int GetTickCount()

Diese beiden kommen mit FreeRTOS mit. Ich habe um die gesamte 
Basisfunktionalität von FreeRTOS (Task Verwaltung) einen C++ Wrapper 
geschrieben.

Nun möchte ich nicht mehr in der Klasse die zwei oben genannten Methoden 
anbieten, sondern nur noch:
1
int GetTickCountNew();
Diese soll wie folgt implementiert sein:
1
int GetTickCountNew() {
2
  if(calledFromISR() == TRUE) {
3
    return GetTickCountFromISR();
4
  else {
5
    return GetTickCount();
6
  }
7
}

Ich versuche sozusaggen von der ISR zu abstrahieren.
Gast #3171646
Lesenswert?

Wird eine Funktion innerhalb einer ISR UND außerhalb aufgerufen, so 
solltest Du Dich mal mit der Problematik des reentranten Aufrufs 
beschäftigen.
Da geht’s um den gleichzeitigen Aufruf einer Funktion von mehreren 
Stellen aus. Nicht jede Funktion kann das bzw. verträgt das.
Gast #3171665
Lesenswert?

Die Problematik des reentranten Aufrufs ist unabhängig vom Prozessor und 
der internen Datenwortbreite. Nutzt Du aber ein RT-OS so sollte man 
davon ausgehen können, dass die <<mitgelieferten>> Funktionen damit 
keine Probleme haben.
Ich gehe mal davon aus, dass Du am schnellsten glücklich wirst, wenn Du 
ein globales Flag, beim Eintritt in die ISR setzt und beim Austritt 
zurücksetzt. Und das natürlich abfragst. Auch dürfte dies ein 
Mechanismus sein, der sich in 5 Jahren noch identifizieren lässt.
#3171669
Lesenswert?

Weshalb muss GetTickCount überhaupt diesen Unterschied machen? Geht es 
darum, in dieser Routine sicherzustellen, dass sie nicht vom SysTick 
Interrupt unterbrochen wird? Dafür liesse sich beispielsweise 
BASEPRI_MAX einsetzen. Vorher so setzen, dass der SysTick nicht 
durchkommt, nachher auf alten Wert zurück. Das darf man dann auch in 
ISRs.
OP #3171672
Lesenswert?

@ A.K.

Danke für den Hinweis. Gerade eben habe ich auch das SHCRS Register 
entdeckt. Mein Fehler war, dass ich nicht gewusst habe, dass eine ISR 
sowohl von einem Interrupt als auch von einer Exception aufgerufen 
werden kann.

Somit könnte ich nun mit Hilfe von SHCRS, IABR0 und IABR1 erkennen ob 
eine ISR gerade aktiv ist oder nicht.

Nun habt ihr soviel kritische Fragen aufgeworfen, dass ich mir im Moment 
garnicht sicher bin, ob ich so einen Mechansimus einbauen möchte oder 
nicht ;-)
Gast #3171685
Lesenswert?

Zig Antworten und keine enthält die offensichtliche Lösung: Register 
IPSR auslesen. Seite 624 im ARMv7M Reference Manual. Ist 0 oder Nummer 
der aktuellen Exception. Löst natürlich nicht das Reentrant-Problem
Gast #3171696
Lesenswert?

Schreib eine zusätzliche Auswertung!

ISRCall = 0;

wenn in der ISR die Routine ausgeführt werden soll:

ISRCall = 1;
Routine_Start;


ISRCall kannst Du dann auf 1 prüfen wann und so oft du willst...
OP #3171703
Lesenswert?

Ich werde mein Problem mit dem IPSR-Register lösen. Das ist super 
elegant. Werde den Register-Check noch abstrahieren, damit nicht in 
meiner Klasse direkt Register geprüft werden. Evtl. finde ich noch in 
der CMSIS etwas passendes.

Aktuell sehe ich kein Reentrant-Problem mit folgender (prototypischer) 
Umsetzung:
1
int GetTickCountNew() {
2
  if(SCB_ICSR != 0) {
3
    return GetTickCountFromISR();
4
  else {
5
    return GetTickCount();
6
  }
7
}

Ich habe keine globale Variable in der Methode, die während der normalen 
Programmausführung bzw. in der ISR manipuliert werden könnte, und somit 
zu einem Fehlverhalten führen würde.

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