Tach, ich bin ganz neu in der ARM-Welt. Habe erst angefangen, mit LPC2000 zu basteln :-) Genauer gesagt verwende ich einen LPC2364. So, und nun habe ich dazu ein paar kleine Fragen... 1. Der ARM-Core kennt ja verschiedene Modi - UND, ABT, SVC und so weiter. Im Startup-Code wird dann ja einmal in jeden dieser Modi umgeschaltet, und der Stackpointer initialisiert. Das ist schön und gut; aber was bringen denn diese Modi, wenn man einfach so zwischen denen umschalten kann? Was unterscheidet die Modi von einander? Früher habe ich mit Motorola 68k gebastelt; die haben auch einen "Supervisor" und einen "User" Mode. Nach dem Reset war man immer im Supervisor, und konnta da alles initialisieren; wenn man erst einmal in den User-Mode geschaltet hatte, konnt man bestimmte Register nicht mehr verändern und auch den Status nür über spezielle Befehle wieder wechseln. Sozusagen als "Schutz", damit der User das System nicht zerschiessen kann, indem er unberechtigte Sachen ändert. Kann das der ARM auch? 2. Der Assembler ist ja ein bisschen gewöhnungsbedürftig ;-) man kann Konstanten manchmal mit mov in ein Register laden, und manchmal benötigt man LDR, und manchmal LDR mit diesem komischen = Operator (LDR r0, =0x1234). Frage: Findet sich irgendwo eine übersichtliche Liste der Befehle, die der ARM7 kann, und wie die Syntax dieser auszusehen hat?
Henry schrieb: > Was unterscheidet die Modi von einander? Link-Register, Stack-Pointer und SPSR. Die Modi sind nötig, weil im Unterschied zum 68000 Return-Adresse und alten Statusregister bei Abort/... Exceptions nicht auf dem Stack landen, sondern im R14 und SPSR des jeweiligen Exception-Modus. RISC lässt grüssen. Die manuelle Umschaltung ist nur für die Initialisierung von R13 (Stack-Pointer) nötig. 68K macht das über Spezialbefehl, ARM über Modusumschaltung. > Kann das der ARM auch? Ja. Das unterscheidet USER und SYSTEM Mode. > Frage: Findet sich irgendwo eine übersichtliche Liste der Befehle, die > der ARM7 kann, und wie die Syntax dieser auszusehen hat? Es gibt auf arm.com zwei Kurzreferenzen. Da ist allerdings alles drin, nicht nur ARM7.
Hallo A.K., warum kann ich dann im Startup-Code einfach so zwischen User und System Mode umschalten? Sollte diese Umschaltung nicht auch irgendwie eingeschränkt sein, sodass man vom einen Mode zwar in den anderen kommt, aber nicht mehr zurück? sonst würde das ja keinen Sinn ergeben.
Ich kenne deinen Startup-Code nicht, aber normalerweise wird nicht in den User-Mode geschaltet. Der System-Mode benutzt die gleichen Register wie der User-Mode, deswegen reicht es, den zu Initialisieren. Jürgen
Den brauchst du dann, wenn du ein Programm(teil) laufen lassen willst, das nicht über priveligierte Rechte verfügen soll.
Henry schrieb: > warum kann ich dann im Startup-Code einfach so zwischen User und System > Mode umschalten? Von System nach User geht. Umgekehrt nicht. Überlicherwise verwendet mal bei Verwendung als Mikrocontroller ohne Betriebssystem entweder den einen oder den anderen Modus, je nach persönlichem Geschmack. Ansonsten verwenden Handler für verschachtelte Interrupts u.U. den System Modus, denn der Interrupt Modus ist nicht reentrant. Ein Konstruktionsfehler der ARM Architektur.
Aber klar doch. Nested IRQ oder FIQ gehen ohne Probleme. Modespezifische-Register sichern, I/F Flags wieder löschen. Irgendwann wieder setzen, Mode register zurückspielen. Kannst machen bis dir der Speicher ausgeht.
Nur solange der Handler keine Funktion aufruft. Auch keine Compiler-Runtime. Der Interrupt-Handler verwendet genauso R14 als Link-Register für seinen eigenen Code wie jeder andere. Und wenn er eine Funktion aufruft, dann landet die Return-Adresse wie üblich ebendort. Und wird beim ersten Schachtelinterrupt von der Hardware überschrieben. Weshalb ein Handler für nested Interrupts vor/mit Freigabe des Interrupts den Modus wechselt. Das fällt nur nicht so auf, weil das mit der Freigabe vom I-Flag kombiniert wird. Siehe http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka11008.html. Wissen sollte man es aber schon, denn es bedeutet, dass solche Interrupt-Handler hauptsächlich den System/User-Stack beanspruchen, nur 2 Worte pro Level landen im Interrupt-Stack.
Erm, wie bei jedem branch with link, sicherst du R14(lr) auf dem Stack. Da ist kein Unterschied zu rekursiven Funktionsaufrufen in Hinsicht des LR.
Maxxie schrieb: > Erm, wie bei jedem branch with link, sicherst du R14(lr) auf dem Stack. Eine Funktion, die keine weitere Funktion aufruft, ist nicht verpflichtet R14 zu sichern. Wird dies meistens auch nicht tun, wie bei jedem branch with link. Selbst wenn du den Compiler dazu bringen könntest dies immer zu tun besteht dennoch zwischen BL und dem STM-Befehl immer noch ein Fenster in dem R14 zerstört wird, wenn der Interrupt genau da hinein rutscht. Hältst du ARM für blöd?
Maxxie schrieb: > Da ist kein Unterschied zu rekursiven Funktionsaufrufen in Hinsicht des > LR. Oh doch. Der Interrupt ist asynchron, kann zu jedem Zeitpunkt auftreten zu dem er freigegeben ist. Der rekursive Funktionsaufruf hingegen geschieht nur an genau kontrollierter Stelle. Das genau ist der Unterschied.
Leute, der LR wird gesichert (gemeinsam mit dem cpsr und evtl anderen genutzten registern, wärend das i flag noch gesetzt ist. Damit sind diese Werte verlässlich. Danach kann ich zu jedem Zeitpunkt gerne wieder unterbrochen werden, und lösche das i flag. Am Ende der (unterbrechenbaren) Interruptbehandlung wirds i flag wieder gesetzt. LR und co wieder hervorgeholt und per MOVS pc,lr herausgesprungen. Wo seht ihr da ein Problem?
1 | @ISR: |
2 | stmdb sp!,{r0-r4,r12,lr} ; ABI conform: in whatever_wherever veränderbare register |
3 | MRS r0,CPSR |
4 | stmdb sp!,{r0} |
5 | BIC r0,#0xC0 |
6 | MSR CPSR, r0 ; bis hier kann kein reentry auftreten |
7 | |
8 | BL @whatever_wherever |
9 | |
10 | ldmia sp!,{r0} |
11 | MSR CPSR,r0 ; ab hier wieder nicht |
12 | ldmia sp!{r0-r4,r12,lr} |
13 | movs pc,lr |
Maxxie schrieb:
> BL @whatever_wherever
Explizit passiert hier;
R14_irq = PC
PC = whatever
Und nun kommt an genau dieser Stelle, also direkt unmittelbar sofort
nach BL, der Schachtelinterrupt und macht:
R14_irq = PC
SPSR_irq = CPSR
PC = 0x000000xx
schwupps, weg ist der vorherige Inhalt von R14. Wenn also
irgendwannwhatever beendet wird, geht es ab in den Wald, genauer gesagt
dorthin wo der Schachtelinterrupt auftrat. Und nicht hinter den BL.
> und weg ist das vorherige R14. Wenn also irgendwannwhatever beendet > wird, geht es ab in den Wald Ok, ja hab mein Problem jetzt gesehen. Danke
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.