Forum: Mikrocontroller und Digitale Elektronik Interupt Active bit löschen (ARM-Cortex M4 )


von Basti B. (basti195) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
ich habe eine etwas ungewöhnliche Frage.
Ich versuche bei meinem Cortex-M4 uc einen Context switch zu machen.
Hierfür habe ich eine TC dazu bestimmt den Stack von A -> B zu 
verschieben.

Da jedoch erst einmal der Stack erstellt werden muss baue ich  mir den 
selber zusammen:
im TC-ISR Sichere ich die Register vom Hauptstack, verschiebe den Stack 
und rufe dann mein Task über einen Funktion Aufruf auf. (Task1();)
Die erste Aufgabe von Task1 ist, gleich wieder die ISR-Routine(über 
funktions-call)aufzurufen. Hier wird erkannt das der Aufruf vom Task 
kommt und die Register werden wieder gesichert, der Stack zurück 
geschoben(B -> A) und der ISR verlassen.
So habe ich auf dem Mainstack eine Abgeschlossene ISR und auf dem 
B-Stack eine angefangene ISR(da der Stack wieder zurück geschoben 
wurde).

Die Idee ist wenn jetzt ein TC-Interrupt kommt kann ich einfach zu dem 
Stack wechseln auf dem die ISR Routine nicht abgeschlossen ist. Die 
müsste dann nach dem Simulierten ISR(aus Task1) weiter machen. Dann wäre 
der mainStack ISR nicht abgeschlossen.

Ansich funktioniert das auch so wie ich es mir gedacht habe. Jedoch wird 
beim Context switch das Interrupt-Aktive-bit nicht zurückgesetzt, 
weshalb keine weiteren Interrupte ausgeführt werden können (sprich der 
UC denkt er wäre immer noch in der ISR).

Leider hat man auf dieses Bit Keinerlei Schreibrechte: Weder im 
NVIC->IABR noch im CPU-Register "Interrupt Programm status"(wo die 
aktuelle ISR angezeigt wird)
Zwar sind laut DB beide R/W Jedoch lassen sich diese Bits nicht 
verändern.


Meine Frage nun ist, wie ich den NVIC so austricksen kann, das der 
entweder nach dem Context-switch wieder denkt, dass er im Normalen 
Programm ist oder das der Simulierte ISR als normaler ISR ausgeführt 
wird und nicht als Funktion.(was doch eig. nicht geht, da die M-Serie 
keine Re-enter ISR erlaubt)
Im Anhang habe ich den Inhalte der Stacks mit ihren aufrufen 
geschrieben.
Die stelle wo der Fehler auftritt wurde auch markiert.


Über eine Antwort der über Ideen und Lösungsansätze würde ich mich 
rissig Freuen :D
Sebastian Balz

von Peter D. (peda)


Lesenswert?

Ich sehe keinerlei Sinn darin, einen Interrupt zu suspendieren. Wenn 
etwas warten kann, dann bräuchte man ja keinen Interrupt dafür.
Ein Interrupt sollte immer so schnell wie möglich beendet werden. Auch 
ist ein Interrupt in der Regel nicht reentrant, d.h. er reagiert auf ein 
ganz bestimmtes Ereignis.
Der Taskwechsel-Interrupt sollte daher die niedrigste Priorität 
bekommen, so daß alle anderen Interrupts immer erst beendet werden.

Damit man sich nicht selber ins Knie schießt, sind aus gutem Grund die 
Interruptstatusbits nicht schreibbar.
Aus 8051-Zeiten kenne ich aber ein richtig richtig schmutzigen Hack, 
wenn man das wirklich wirklich will. Man ruft einfach eine Funktion auf, 
die nur aus einem RETI besteht.
Beim 8051 waren die Folgen leicht überschaubar, der hat klaglos das 
später erfolgende überzählige RETI als RET ausgeführt.
Beim Cortex bin ich aber im Zweifel, ob das Durcheinanderbringen der 
Interruptlogik ihn nicht abschmieren läßt.

von Basti B. (basti195) Benutzerseite


Lesenswert?

Der Interrupt führt ja nicht ansich eine Tätigkeit aus.
Viel mehr triggert er den Wechsel.
die Routine wird deshalb offen gelassen, damit  es eine feste stelle 
gibt in denen der Task gewechselt werden kann.
es muss ja aus sich eines Taskes wird nur kurz der ISR ausgeführt das in 
der zeit x ms vergehen bemerkt der Task.

der eigentlich Interrupt besteht nur aus dem Taskwechsel danach soll 
der(aus der Sicht von außen) wieder verlassen werden.
aus Sicht eines Taskes hingehen wird der ISR ausgeführt und der Task 
wird eine zeit lang angehalten.

von Bernd K. (prof7bit)


Lesenswert?

Ich hab sowas noch nie gemacht, aber was mir spontan durch den Kopf 
schießt ist: Was würde passieren wenn Du in Deinem Interrupt den Stack 
(Stackpointer, etc) in so einer Weise manipulierst/austauschst daß wenn 
Du anschließend den Interrupt wieder ordnungsgemäß verlässt und er 
wieder weitermachen will wo er hergekommen ist er stattdessen den 
Zustand herstellt und dorthin springt wie/wo Du ihn haben willst (der 
andere Task). Gibts einen Grund warum das nicht gehen sollte?

von Basti B. (basti195) Benutzerseite


Lesenswert?

Bernd K. schrieb:
>
> Was würde passieren wenn Du in Deinem Interrupt den Stack
> (Stackpointer, etc) in so einer Weise manipulierst/austauschst daß wenn
> Du anschließend den Interrupt wieder ordnungsgemäß verlässt und er
> wieder weitermachen will wo er hergekommen ist

Das klingt nach einer Idee
Irgendwo muss ja im stack gespeichert sein, dass es sich um eine 
ISR-Call oder um einem Thread Call handelt.
Die Frage ist nur an welcher stelle die gespeichert wird.

Grüße

von ??? (Gast)


Lesenswert?

Sebastian B. schrieb:
> Ich versuche bei meinem Cortex-M4 uc einen Context switch zu machen

books.google.de : cortex m4 context switching pending

von W.S. (Gast)


Lesenswert?

Peter D. schrieb:
> Der Taskwechsel-Interrupt sollte daher die niedrigste Priorität
> bekommen, so daß alle anderen Interrupts immer erst beendet werden.

Peter, wir sind hier ncht beim AVR, sondern beim Cortex M. Da gibt es 
keinen RETI und die Beendigung einer ISR bekommt die CPU bzw. der NVIC 
auf ganz andere Weise mit, nämlich über den Zustand des LR beim reload 
des PC. Ich zitiere hier mal:

"Exception return

Exception return occurs when the processor is in Handler mode and 
executes one of the following instructions to load the EXC_RETURN value 
into the PC:
    an LDM or POP instruction that loads the PC
    an LDR instruction with PC as the destination
    a BX instruction using any register.
EXC_RETURN is the value loaded into the LR on exception entry. The 
exception mechanism relies on this value to detect when the processor 
has completed an exception handler. The lowest five bits of this value 
provide information on the return stack and processor mode. Table 2.17 
shows the EXC_RETURN values with a description of the exception return 
behavior.

All EXC_RETURN values have bits[31:5] set to one. When this value is 
loaded into the PC it indicates to the processor that the exception is 
complete, and the processor initiates the appropriate exception return 
sequence."

Kurzum, LR ist immer 0xFFFFFFE0 oder größer je nach Prio-Level - und das 
ganze Stacking und Unstacking geht per Hardware. Einfach nur sich seine 
Stacks generieren und dann umladen, wie der TO es sich ausgedacht hat, 
führt deshalb recht zielsicher dazu, daß Prozessor/NVIC recht bald im 
höchsten vergebenen Prioritäts-Level stecken und nie wieder herunter in 
den Usermode kommen. Dazu kommt, daß der per HW auf den Stack 
geschriebene Block unterschiedlich lang sein kann, weil seine Länge eben 
auch davon abhängt, ob und wieviele Register des FP-Prozessors gerettet 
werden mußten. Das Thema ist echt kitzlig.

W.S.

von Basti B. (basti195) Benutzerseite


Lesenswert?

(: vielen Dank schon mal :)

habe habe etwas mit meinem Stacks "rum gespielt"
habe ein kleines Stack Programm geschrieben das den ISR über ein 
Interrupt aufruft und einmal über einen FUnktionCall.
dann habe ich die Stacks miteinander verglichen und versucht das 
gegenteil von meinem Problem zu erzeugen.

Anscheinend wird der Interrupt-active über den Stack gesteuert und wenn 
man EXC_Return(0xFFFFFFF 1/9/D)mit einer Rücksprung Adresse ersetzt wird 
das Interrupt aktiv bit nicht wieder zurück gesetzt.
Also schon mal vielen dank an  Bernd K.

Ich werde versuchen den Stackaufbau des Interrupts und den des ISR 
genauer zu verstehen.

grüße

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

W.S. schrieb:
> Da gibt es
> keinen RETI und die Beendigung einer ISR bekommt die CPU bzw. der NVIC
> auf ganz andere Weise mit

Ist mir schon klar, daß das RETI beim Cortex anders heißt.
Der Punkt ist aber, daß einen Interrupt zu verzögern, eine super 
schlechte Idee ist, völlig egal ob 8051 oder Cortex.
Daher sollten einfach alle Hardwareinterrupts eine höhere Priorität 
haben, als der Timer zum Taskwechsel.

von Basti B. (basti195) Benutzerseite


Lesenswert?

Soo...
Der Ansatz, die Interrupt über einem Funktions-Call aufzurufen war 
falsch.
Die Richtige Lösung ist natürlich viel einfacher(was sonst ^^)

Ich habe einfach die entsprechenden Werte(LinkRegister, PC, XPSR) im 
Stack manipuliert ,sodass die ISR au normalem Weg verlassen werden 
konnte.

Vielen Dank an alle Kommentare :))

Grüße
Basti195

von W.S. (Gast)


Lesenswert?

Peter D. schrieb:
> Der Punkt ist aber, daß einen Interrupt zu verzögern, eine super
> schlechte Idee ist, völlig egal ob 8051 oder Cortex.

Jaja doch. Dir ist das klar, mir ebenso. Aber so, wie der TO sich da 
drangemacht hat - und so, wie er per Ausprobieren ("habe ein kleines 
Stack Programm geschrieben") versucht, ohne zuvörderst die Nase in die 
Referenzdoku von ARM zu stecken, wird mir klar, daß er den ganzen Umfang 
der Problematik noch garnicht erfaßt hat.

W.S.

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.