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
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.
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 :-)
@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.
A. S. schrieb: > 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. Der SysTick ist ein interner Interrupt. Die IABRs sind nur für externe Interrupts zuständig.
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.
PS: Extern aus Sicht des Cores, nicht des Controllers.
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
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.
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.
@ 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 ;-)
A. K. auf GetSysTick habe ich keinen Einfluss da die Funktion von FreeRTOS zur Verfügung gestellt wird.
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.
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
Dr. Sommer schrieb: > Zig Antworten und keine enthält die offensichtliche Lösung: Dazu muss man erst einmal wissen, wo man suchen muss. Ich hatte danach im Cortex M3 Manual gesucht, nicht in der Architektur.
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...
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.