mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ARM/KEIL: Wie kann eine C-Funktion erkennen ob sie aus ISR heraus aufgerufen wurde?


Autor: Alexander I. (daedalus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich muss eine kleine API schreiben, die unsere hausintere API an das 
RL-ARM Betriebssystem von KEIL anflanscht. Dabei ist es bei einigen 
API-Funktionen notwendig, dass diese erkennen können, ob sie von einer 
ISR heraus aufgerufen wurden oder nicht.

Beispiel:
Die nachfolgende Funktion löscht ein Event und darf nicht in einer ISR 
aufgerufen werden. Wenn doch, gibt sie OS_ERROR_ISRLEVEL zurück. Im 
OK-Fall ruft sie die os_evt_clr von RL-ARM auf.
Status ClearEvent(EvtMask mask)
{
 if(AusISRherausAufgerufen) // <-- gibt's da ein Makro / Intrinsic / ... ?
 {
  return OS_ERROR_ISRLEVEL;
 }
 else
 {
  os_evt_clr(event);
  return OS_OK;
 }
}

Da ich noch nicht so vertraut bin mit der KEIL-Umgebung meine Frage an 
euch, gibt's eine einfache Methode rauszufinden, ob die Funktion gerade 
in einer ISR läuft oder nicht? Könnte ich dazu z.B. VICVectAddr auf 0 
vergleichen?

Habe beim Debugging gesehen, dass der erkennt, ob ich im Mode "ISR" oder 
"User" bin. Scheint also irgendwie möglich zu sein. Ich hab aber keine 
Möglichkeit gefunden, an diese Aussage mit C-Code heranzukommen.

Vielen Dank vorab.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klassische ARMs: Im Statusregister steht drin, in welchem 
Registerkontext er grad läuft (das wird das sein, was du im Debugger 
siehst). Das funktioniert aber nur, wenn man keine verschachtelten 
Interrupts zulässt, weil er sonst im Handler sofort vom 
Interrupt-Context wegschaltet. Ansonsten kann es sein, dass der 
Interrupt-Controller diese Information vermittelt, aber da gibt's mehr 
als einen Typ von.

Cortex-Cores: Aktuelle Priorität.

Autor: Thomas K (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Das hört sich nach einer ARM-CPU. Eine genauere Angabe wäre hilfreich. 
Die ARMs haben ein Feld im PS-Register das den Modus bestimmt. Je nach 
ARM sieht es unterschiedlich aus.. Eines der Modi signalisiert die 
Ausführung eines Interrupts. Google mal nach ARM processor modes.. 
Ausserdem: das CPU Manual ist dein Freund! :)

Gruss
thomas

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS: Das sieht irgendwie nach RTOS aus. Ein RTOS, das verschachtelte 
Interrupts zulässt, benötigt auf klassischen ARMs üblicherweise einen 
Zähler für diese Verschachtelung. Der lässt sich auch dafür nutzen.

Autor: Alexander I. (daedalus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

der Controller ist ein LPC2387 von NXP. Was ich bisher so gelesen hab, 
scheint man ja nur die unteren 5 Bits des CPSR-Registers via 
Inline-Assembler auslesen zu müssen?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jein.

Autor: Alexander I. (daedalus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es müsste doch folgendes klappen, oder?
int status;
__asm {mrs status, cpsr};

if(status & 0x12) 
{
 // IRQ
}
else
{
 if(status & 0x10)
 {
  // User
 }
 else
 {
  // Unzulässig!
 }
}

Ein erster Test hat jedenfalls funktioniert... warum "Jein."?

Autor: Flag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Setze einfach ein Flag.

Interrupt
 Flag=1;
 Aufruf Routine;
 Flag=0;



Routine:
  if (Flag) return;
  else ....

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alexander I. schrieb:

> Ein erster Test hat jedenfalls funktioniert... warum "Jein."?

Wdh: Das funktioniert nur, wenn man keine verschachtelten
Interrupts zulässt, weil sonst im Handler sofort vom
Interrupt-Kontext wegschaltet wird (meist in den System-Kontext. Ob 
deine Umgebung verschachtelte Interrupts zulässt weiss ich nicht, 
deshalb "jein".

Autor: Alexander I. (daedalus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso, alles klar. Ich verwende vorerst kein Interruptnesting.
Danke mal soweit!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Flag schrieb:

> Interrupt
>  Flag=1;
>  Aufruf Routine;
>  Flag=0;

Auch dies funktioniert nur, wenn Interrupts keine Interrupt-Handler 
unterbrechen können.

Besser:
  IrqLevel+=1;
  Aufruf Routine;
  IrqLevel-=1;

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.