Forum: Mikrocontroller und Digitale Elektronik Erklärung für eine Zeile Assembler benötigt


von Max M. (maxmicr)


Lesenswert?

Guten Abend,

ich benötige eine Erklärung für eine einzelne Zeile Assembler (ARMv6). 
Ich würde den Code, den ich benutze gerne vollständig verstehen, 
allerdings klappt das bei diesem ASM-Statement nicht:
1
asm volatile("mcr p15, 0, %[addr], c12, c0, 0" : : [addr] "r" (&interrupt_vectors));

Dabei ist
1
interrupt_vectors
 eine in C definierte Funktion. Die Zeile stammt aus diesem Repo: 
https://github.com/brianwiddas/pi-baremetal/blob/master/interrupts.c

Die Erklärung des Befehls 
(http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489g/Cihfifej.html) 
hilft mir auch nicht weiter. Wie komme ich auf diesen Befehl und seine 
Parameterwerte? Was ist ein Coprozessor im Sinne einer ARM-CPU?

Was bedeuten die zwei Doppelpunkte und das "r"?

: Bearbeitet durch User
von ARM Spezi (Gast)


Lesenswert?

Hallo,

>Was ist ein Coprozessor im Sinne einer ARM-CPU?
Das ist typisch ARM und wieder völlig missverständlich.
Es handelt sich hier nicht um eine eigene CPU sondern um eine 
Erweiterung der ARM v6 CPU.
Das Coprozessor-Infterface stellt ein Register-Interface zum Ansrpechen 
der verschiedenen Subsysteme, die nicht direkt in der CPU eingebaut 
sind, bereit. Dazu zählen z.B. Memory-Protection, Interrupt Controller, 
Cache, ect. Dabei hat jedes Subsystem eine eigene 'Nummer'.

Welches Register sich hinter der 'Codierung' verbrigt muß man sich aus 
der ARM Doku zusammen suchen.

Jetzt zum ASM-Befehl:
>asm volatile("mcr p15, 0, %[addr], c12, c0, 0" : : [addr] "r" 
(&interrupt_vectors));

mcr (move to copro register):
P15 ist die Nummer des Coprozessors (in deinem Fall wohl der Interrupt 
Controller).
C12, C0 und die beiden 0 definieren das anzusprechende Register im 
Copro.

Für den Compiler ist asm volatile(...) wie ein Funktionsaufruf. Dieser 
kann Parameter und einen Return Wert haben. Der Compiler versteht den 
ASM-Code aber nicht. Daher muß ihm am Ende der ASM-Sequenz durch eine 
Liste mitgeteilt werden, welche Register die Eingangsparameter 
beinhalten und wo der Return-Wert abgelegt werden soll.

Die Syntax ist dabei
asm volatile("string mit asm instruktionen": Ausgangsreg: Liste mit 
Eingangswerten.
Dabei wird auch noch mit symbolischen Ersetzungen gearbeitet. %[addr] 
heißt, genau an dieser Stelle soll das "Symbol" addr aus der Liste 
genommen werden.

In der Liste sagt man, dass [addr] ein "r"-register ist das vorher mit 
dem C-Symbol &interrupt_vectors zu laden ist.

In Pseudo C-Code würde der Befehl so aussehen:

uint32 r = &interrupt_vectors;
asm_func(r)

void asm_func(uint8 r)
{
 *(Copro_x_Reg_y) = r;
}

Hier hilft ein Blick in das ARM-Compiler Manual.
(GCC macht das anders...)

Hoffe, das war einigermaßen richtig und verständlich.

von ARM Spezi (Gast)


Lesenswert?

hier noch ein Link wo die Syntax noch mal (besser) erklärt wird:
http://www.keil.com/support/man/docs/armclang_intro/armclang_intro_ddx1471430827125.htm

von Max M. (maxmicr)


Lesenswert?

Vielen Dank!

ARM Spezi schrieb im Beitrag #5364379:
> Hoffe, das war einigermaßen richtig und verständlich.

Definitiv, hab alles verstanden.

Gibt es in C eine bestimmte Syntax, so dass sich diese ASM-Funktion auch 
in C schreiben lässt?

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

ASM Funktionen in C nutzen nennt sich "intrinsics".
Das sieht dann aus wie ein C Funktionsaufruf, aber am Ende fällt ein asm 
Code raus.
So kann man zB manuell die x86 AVX Funktionen nutzen fürs 
Numbercrunchen.
(Bei ARM wäre das dann die NEON Engine)

Guckst du hier: 
https://github.com/gcc-mirror/gcc/blob/master/gcc/config/arm/arm_acle.h
Die Funktion heist "__arm_mcr".


Aber was noch nicht ganz geklärt ist, wozu der Befehl denn nun genutzt 
wird.
Die Zahlenkombination zeigt auf das Vector Base Address Register (VBAR).
Bei ARMv4 zB musste die Interrupttabelle noch an Adresse 0x0 sein oder 
als "High Vectors" an 0xFFFF0000.
Die Interrupttabelle enthält aber direkt ARM Befehle dessen 
Sprungreichweite begrenzt ist.
Daher musste man sich mit Doppelsprüngen aushelfen wenn der Speicher zB 
erst ab 0x20000000 eingebunden ist.
Mit dem VBAR Register wurde das geändert. Die Interrupttabelle kann man 
irgendwo 32Byte aligned in sein Programm werfen und dem ARM Kern dann 
einen Pointer darauf mitteilen.
-> Alle sind glücklich ;)

Hier noch ein paar Infos dazu:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0433c/CIHHDAIH.html

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.