Hallo Leute!
Jetzt drehe ich mich schön langsam im Kreis....
Ich versuche die verschiedensten Beispiele zum Thema ARM7 und Vectored
Interrupts aus, doch entweder mault mich mein Compiler an oder der
Controller bleibt hängen. Oft ist bei den Beispielen kein Makefile
dabei, mir unbekannt für welchen Compiler das Codestück geschrieben ist
oder kein startup-code dabei.
Wie zeichnet gcc die Interrupt-Funktionen aus?
Die Fehlermeldung, die ich immer wieder bekomme:
Wer weis hier Rat oder ein feines, kleines, komplettes Beispiel eines
NXP ARM7 Controllers mit Makefile für arm-elf-gcc.
mit der Bitte um Hilfe
Gabriel
Das hat nichts mit dem gcc zu tun. Der ARM7 hat eine Vektortabelle bei
Adresse 0 in der Sprünge zu den Handler-Funktionen stehen. Der
Interrupt-Handler ist so eine Funktion. Da dieser nicht im User-Mode
sondern im Protected-Mode läuft, muss dieser in Assembler geschrieben
werden. Der Interrupt-Handler prüft die Interrupt-Nummer, z.B. Timer0,
und springt dann zur Timer0-Interrupt-Funktion. Die kann dann in C
programmiert werden.
Für ein Beispiel würde ich einen kommerziellen Compiler als Demo
installieren, Keil oder IAR, und da den Code raus kopieren. Beim z.B.
ARM7TDMI wären das startup.s, irq.s, irq.c
Beim Nachfolger CortexM3 ist das geändert worden, hier gibt es bei
Adresse 0 eine Adressentabelle für alle Interrupt-Nummern. Hier kann
dann z.B. die Timer0-Interrupt-Funktion in C programmiert werden.
So schwer ist das nicht, wenn ich nachher mal bissel zeit habe schnipsel
ich da mal etwas Code von hier zusammen.
Übrigens ARM hat keine Vektortabelle, sondern da müssen Befehle in die
IRQ Tabelle.
Welchen IC hasten genau?
@über mir:
aber natürlich kann man alle Interruptbehandler in C schreiben, es
benötigt nur einen kleinen ASM Teil drumrum zum Register retten ;)
Hallo Gabriel,
vor dem gleichen Problem stand ich vor einigen Wochen auch, als ich
versucht habe, die Hintergründe zur Lern-Betty auf der Basis des LPC2220
zu verstehen. Siehe hier:
Beitrag "die Betty-Fernbedienung von Pollin als ARM-Eval Board"
Dieses Projekt ist eine Interessante Basis für mich gewesen. Mir fehlte
allerdings die gewünschte Kontrolle und ohne eigene Beschäftigung ist
der Lerneffekt sehr gering.
Mit diesem Projekt und jeder Menge Zeit über den Jahreswechsel, dieser
Seite
http://www.freddiechopin.info/en/download/category/6-examples
und natürlich mit der NXP Doku zur CPU habe ich mittlerweile für die
Betty TV Umgebung auch FeeRTOS laufen. Zurzeit ist die Doku - speziell
die Copyright Zuordnung - nicht für eine allgemeine Weitergabe geeignet.
Als Compiler verwende ich Yargarto bzw. aktuell auch
https://launchpad.net/gcc-arm-embedded/+milestone/4.7-2012-q4-major
weil diese Toolchain auch für MacOS X angeboten wird. Ich verwende
keinen Thumb-Code. Meine Übersetzung erfolgt mit diesen Parametern
/Users/xyz/arm-toolchain/gcc-arm-none-eabi-4_7-2012q4/bin/arm-none-eabi-
gcc -c -mcpu=arm7tdmi-s -O3 -ffunction-sections -fdata-sections -Wall
-Wstrict-prototypes -Wextra -std=gnu99 -g -ggdb3 -fverbose-asm
-Wa,-ahlms=out/main.lst -MD -MP -MF out/main.d -I. main.c -o
out/main.o
Ich bin kein großer gcc Experte, vermute aber, dass Dein Problem in
-mthumb-interwork begründet ist.
Vielleicht hilft Dir mein Beitrag...
Gruß
swausd
Ich hab das LPC2478-STK von Olimex vor mir und bekomme zwar ein Bild auf
dem Display aber keinen Interrupt.
Ich fürchte schon, das das so langsam mit meinem GCC zu tun hat.
Hab gerade ein Paar Beispiele, die zu den Olimex-ARM7-Prints angeboten
werden heruntergeladen. Da ist auch ein Makefile dabei. In der main.c
stehen die Interrupt-Funktionen drinnen:
Du hast vollkommen recht, der CortexM3 ist da viel gutmütiger und
geradliniger zu programmieren! In Zukunft werde ich die ARM7 altes Eisen
sein lassen und mit den Cortex cores arbeiten.
Den Code für den Cortex übersetzt der Compiler brav und gut.
Ich hab mir nochmal die ./configure Einstellungen angesehen und nichts
verdächtiges dabei herausgefunden.
Wir hamms ja aufm ARMv4 geproggt, wenne den Code trotzdem sehen willst,
dann sag bescheid.
Da ist allerdings alles zu Fuß gemacht, also Vektortabelle in ASM
anlegen, Stacks initialisieren, Register retten.
Nur der IRQ selber ist dann C.
Gabriel Wegscheider schrieb:> Jetzt drehe ich mich schön langsam im Kreis....
Schön ruhig bleiben.
Das Interrupt-Geschehen beim ARM7TDMI geht etwa so:
- das Init-Programm lädt die Adresse der gewünschten Interruptroutine in
den Interruptcontroller. Das gilt für vektorisierte Interrupts. Der FIQ
läuft anders, die Softwareinterrupts auch und alle freigegebenen
Interrupts, die von dir keinen Vektor abbekommen haben, landen in einem
Sammelinterrupt.
- erfolgt ein Interrupt, dann schaltet die Hardware auf einen anderen
Stack um, geht in den ARM Modus und startet ein winziges Programm, das
zumeist nur eines macht:
LDR PC,[PC, #-0x0FF0] ; 18h IRQ, HandlerAddr-->PC
Damit wird die im Interrupt-Controller gespeicherte Anfangsadresse der
Serviceroutine angesprungen.
Merke: Hier sind wir im ARM-Modus und deine Int-Serviceroutine MUSS
ebenfalls im Arm-Modus compiliert sein. Blöderweise versteht der GCC die
dafür nötigen Pragmas nicht, weswegen du zwangsweise die
Interruptroutinen in eine separat zu übersetzende Quelle auslagern mußt.
Anders geht das beim GCC nicht. Mit dem Keil hat man dieses Problem
nicht, aber die diversen Diskussionen darüber und über andere Dinge
(SVC, Thumb mode usw) hatte wir schon mal. SVC geht nur per Wrapper, für
Thumb in Assembler muß man .thumb und zusätzlich .thumb_func schreiben
und so weiter. Wahrscheinlich bin ich bei der Lernbetty noch längst
nicht über alle GCC-Fallstricke gestolpert. Lies dich dort mal ein, da
kannst du sehen, wie diverse Sachen so im Detail funktionieren.
Gabriel Wegscheider schrieb:> oder ein feines, kleines, komplettes Beispiel eines> NXP ARM7 Controllers mit Makefile für arm-elf-gcc.
Tja, die Lernbetty ist so ein kleines, feines Beispiel (eben genau dazu
gedacht) - aber halte dich nicht so sehr an irgendwelchen Makefiles
fest, sondern guck daß du ohne ein solches der Sache erstmal echt zu Fuß
auf den Grund gehst. Wenn dir dann alles klar ist, kannst du immer noch
mit Makefiles arbeiten.
W.S.
Wie der Interrupt theoretisch funktioniert ist mir soweit klar, doch wie
sag ich's meinem Compiler.
Stimmt die Auszeichnung
1
__attribute__((interrupt("IRQ")))
für den Vectored interrupt beim GCC?
Müssen die Interrupts vor der Benutzung aktiviert werden oder sind die
aktiv sobald die Handler-adressen und Prioritäten eingetragen sind?
Mein Compiler will aber offenbar nicht im ARM-Mode übersetzen....
Dieser ist selbst laut Beschreibung übersetzt und ich hab oben mal die
config beschrieben.
Gruß
Gabriel
Gabriel Wegscheider schrieb:> Mein Compiler will aber offenbar nicht im ARM-Mode übersetzen....
Nochmal: Schau dir die Lernbetty an, Rubrik Codesammlung.
Natürlich kann auch der GCC im Arm-Mode, du mußt es ihm bloß sagen. Ich
hab wirklich nicht umsonst geschrieben, daß du besser für den Anfang
ohne IDE, ohne Makefile und ohne sonstigen Krimskrams compilieren
solltest. Wenn du dann weißt, wie es geht, hast du auch nen besseren
Blick auf das, was sich da in deiner IDE, Makefile etc. so herumtummelt.
"Müssen die Interrupts vor der Benutzung aktiviert werden oder sind die
aktiv sobald die Handler-adressen und Prioritäten eingetragen sind?"
Da gehört mehr dazu:
- Adresse in den Slot deiner wahl eintragen (wg. Priorisierung),
- Quelle im Slot eintragen
- Zuordnung FIQ, INT, Sammelint im Slot eintragen
- Peripherie aufsetzen und dort die Interrupt-Erzeugung freischalten
Jaja, ist ne komplexe Sache.
Martin Wende schrieb:> Weis jetz nich was dein Compiler macht, abern nachm Reset ist bit7 im> SPSR gesetzt (IRQs aus).
Und? Was soll das?
Der Startupcode ist auch dazu da, die diversen Stacks und Modi
aufzusetzen. Dazu gehört eben auch, daß er schlußendlich in den Usermode
geht, wo alle Interrupts CPU-mäßig freigegeben sind. Das heißt aber noch
lange nicht, daß der Interruptcontroller selbige ebenfalls freigegeben
hat oder gar die Peripherie selbige erzeugt.
Es gibt je nach ARM-Version und Hersteller unterschiedliche
Interrupt-Controller. Deswegen MUSS!!! man das Manual zum Chip in dieser
Angelegenheit gründlich lesen. Glaub's mir.
W.S.
Hallo W.S.
Ich fürchte, der Code der Lernbetty hilft mir nicht weiter.
Mein Problem scheint in der Kombination von ARM7 + Interrupt + "meinem
GCC" liegen.
W.S. schrieb:> Gabriel Wegscheider schrieb:>> Mein Compiler will aber offenbar nicht im ARM-Mode übersetzen....>> Nochmal: Schau dir die Lernbetty an, Rubrik Codesammlung.> Natürlich kann auch der GCC im Arm-Mode, du mußt es ihm bloß sagen. Ich> hab wirklich nicht umsonst geschrieben, daß du besser für den Anfang> ohne IDE, ohne Makefile und ohne sonstigen Krimskrams compilieren> solltest. Wenn du dann weißt, wie es geht, hast du auch nen besseren> Blick auf das, was sich da in deiner IDE, Makefile etc. so herumtummelt.
Ich verwende keine IDE. Meine Programme werden von der Konsole aus via
make kompiliert. Mit Makefile bin ich gut genug vertraut und kann diese
- solange sie nicht mit automake generiert wurden - auch lesen und
schreiben.
W.S. schrieb:> "Müssen die Interrupts vor der Benutzung aktiviert werden oder sind die> aktiv sobald die Handler-adressen und Prioritäten eingetragen sind?">> Da gehört mehr dazu:> - Adresse in den Slot deiner wahl eintragen (wg. Priorisierung),> - Quelle im Slot eintragen> - Zuordnung FIQ, INT, Sammelint im Slot eintragen> - Peripherie aufsetzen und dort die Interrupt-Erzeugung freischalten> Jaja, ist ne komplexe Sache.>>> Martin Wende schrieb:>> Weis jetz nich was dein Compiler macht, abern nachm Reset ist bit7 im>> SPSR gesetzt (IRQs aus).>> Und? Was soll das?>> Der Startupcode ist auch dazu da, die diversen Stacks und Modi> aufzusetzen. Dazu gehört eben auch, daß er schlußendlich in den Usermode> geht, wo alle Interrupts CPU-mäßig freigegeben sind. Das heißt aber noch> lange nicht, daß der Interruptcontroller selbige ebenfalls freigegeben> hat oder gar die Peripherie selbige erzeugt.>> Es gibt je nach ARM-Version und Hersteller unterschiedliche> Interrupt-Controller. Deswegen MUSS!!! man das Manual zum Chip in dieser> Angelegenheit gründlich lesen. Glaub's mir.
Das werd' ich mir ansehen, aber da liegt mein Hund nicht begraben
>> W.S.
Gruß Gabriel
Wie schon gesagt, ich dreh mich im Kreis... und komme immer wieder bei
den selben Fakten vorbei.
Jetzt zu einem Minimal-Beispiel das mein Dilemma zeigen soll:
Wie bekomme ich folgenden C-Code mit arm-elf-gcc in gültigen ARM-Code?
CodeSourcery frisst diesen Code (ohne das Include) anstandslos. Wär also
die Frage, was für ein GCC das ist bzw. wie der so vergewaltigt wurde,
dass er ohne Angabe von -mthumb dennoch Thumb Code erzeugt.
$ arm-none-eabi-gcc -mcpu=arm7tdmi -I./ -c -O0 -g irq7.c
OK
$ arm-none-eabi-gcc -mcpu=arm7tdmi -mthumb -I./ -c -O0 -g irq7.c
irq7.c: In function 'IRQ_Routine':
irq7.c:16:1: error: interrupt Service Routines cannot be coded in Thumb
mode
gcc version 4.6.3 (Sourcery CodeBench Lite 2012.03-56)
Danke A.K. !
Damit hast Du mir geholfen.
Ich glaub, ich hab den Fehler:
Beim Erstellen der Toolchain ist der Switch
1
--with-mode=thumb
in der configure des gcc. --> Default Thumb. Wenn ich jetzt -marm als
Argument mitgebe kompiliert er mir mal meinen Code anstandslos - das hab
ich auch gerade bemerkt.
Wieso lpc21xx ?
Dieser Code stammt ursprünglich aus der Softwaresammlung der
Olimex-Platinen, ist definitiv für den GCC geschrieben und zeigte den
Compile-Fehler auch schon. In einer Eierlegenden-Wollmilchsau sah ich
keine Chancen, dem Fehler auf den Grund zu gehen.
... jetzt kann ich mich wieder komplexeren Beispielen zuwenden
Gruß Gabriel
Es gibt bei den LPC2000 eigentlich nur einen Grund, den Thumb-Mode zu
verwenden: wenn der Platz im ROM sonst nicht reicht. Anders als bei
manchen anderen ARM7 µCs ist die Flash-Bandbreite der LPC2000 gross
genug für den ARM-Mode.