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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Max M. (maxmicr)


Bewertung
2 lesenswert
nicht 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)


Bewertung
3 lesenswert
nicht 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)


Bewertung
3 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
1 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.