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

OP #3171615
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
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
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
@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
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.
#3171648
amateur schrieb:
> Da geht’s um den gleichzeitigen Aufruf einer Funktion von mehreren
> Stellen aus. Nicht jede Funktion kann das bzw. verträgt das.

Im Prinzip richtig, aber ein Cortex M3 ist kein 8-Bit Controller.

A. S. schrieb:
> Hat jemand von euch eine Idee?

Im speziellen Fall vom SysTick: SCB_SHCSR.SYSTICKACT
Gast #3171665
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
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
@ 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 ;-)
#3171675
A. S. schrieb:
> Diese beiden kommen mit FreeRTOS mit.

Dafür dass sie bei FreeRTOS dabei sind ist schon beachtlich, dass Google 
sie nicht findet. ;-)

Wäre schon interessant, worin der Unterschied besteht. Ich werde das 
Gefühl nicht los, dass da was auf dem Kopf steht, so überflüssig viel 
Komplexität eingebracht wird.
Gast #3171685
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
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
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.
Gast #3171709
A. K. schrieb:
> Ich hatte danach
> im Cortex M3 Manual gesucht, nicht in der Architektur.
Die Architecture Reference ist enorm hilfreich für alles, die sollte man 
auf jeden Fall kennen...!

A. S. schrieb:
> Evtl. finde ich noch in der CMSIS etwas passendes.
Ja enthält die __get_IPSR () Funktion dafür.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 13 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.