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
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.
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.
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?
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
Sebastian B. schrieb: > Ich versuche bei meinem Cortex-M4 uc einen Context switch zu machen books.google.de : cortex m4 context switching pending
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.
(: 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
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.