Forum: Mikrocontroller und Digitale Elektronik Frage zu ARM-Modi und Assembler


von Henry (Gast)


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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.

von Henry (Gast)


Lesenswert?

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.

von Jürgen (Gast)


Lesenswert?

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

von Henry (Gast)


Lesenswert?

Also braucht man den User-Mode eigentlich gar nicht?

von Maxxie (Gast)


Lesenswert?

Den brauchst du dann, wenn du ein Programm(teil) laufen lassen willst, 
das nicht über priveligierte Rechte verfügen soll.

von (prx) A. K. (prx)


Lesenswert?

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.

von Maxxie (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Maxxie (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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.

von Maxxie (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von Maxxie (Gast)


Lesenswert?

> 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
Noch kein Account? Hier anmelden.