Hallo!
Ich habe leider mal wieder Schwierigkeiten, die ich nicht alleine lösen
kann.
Ich arbeite mit einem LPC2148 unter Eclipse mit GNU-ARM-Compiler.
Ich möchte Nested Interrupts enablen. Ich habe die dazu nötigen
Assemblerroutinen in mein Projekt eingebunden. Funktioniert prinzipiell
alles.
Leider landet mein µC bei der Befehlszeile "MSR CPSR_c, #0x1F" im
Aborthandler. Ich habe allerdings im ARM Instruction Set gelesen, dass
es möglich ist direkt HEX-Zahlen mit MSR zu verschieben. Das wird ja
auch von vielen so genutzt. Was mir aber sehr zu denken gibt ist die
Tatsache, dass mein Code nach dem # grün
eingefärbt wird, was ja bei vielen IDEs bedeutet, dass es als Kommentar
gesehen wird. Dementsprechend lade ich dann ja nix in CPSR_c rein und
somit wäre der Absturz gerechtfertigt.
Ich finde nur leider nirgends einen anderen Ansatz wie ich 0x1F direkt
ins PSR bekomme.
Weiß jemand eine Lösung für mein Problem?
Bin für alle Tipps und Tricks dankbar!
Mfg
Jansus
Hmm, ja war schon bisschen mager. Sorry!
Was ist denn alles von nöten, um was sagen zu können?
Hier das Assembler-File, mein Startup-File ist im Anhang:
.section .text ,"ax"
.arm
.global nested_irq_enable
.global nested_irq_disable
.func nested_irq_enable
nested_irq_enable: /* Nested Interrupts Entry*/
STMFD SP!, {R0} /* stelle ein Register zur
Verfügung*/
MOV R0, LR /* sichere darin die
Returnadresse*/
MRS LR, SPSR /* sichere SPSR_irq über
LR_irq*/
STMFD SP!, {LR} /* auf dem IRQ Stack*/
MSR CPSR_c, #0x1F /* Modewechsel IRQ - SYS,
Freigabe IRQ*/
STMFD SP!, {LR} /* Sichere LR_sys auf dem User
Stack*/
BX R0 /* Return zur IRQ-ISR*/
.endfunc
.func nested_irq_disable
nested_irq_disable: /* Nested Interrupts Exit*/
MOV R0, LR /* sichere Returnadresse in
Register*/
LDMFD SP!, {LR} /* stelle LR_sys vom User Stack
wieder her*/
MSR CPSR_c, #0x92 /* Modewechsel SYS - IRQ,
Sperrung IRQ*/
LDMFD SP!, {LR} /* Wiederherstellung*/
MSR SPSR_cxsf, LR /* des SPSR_irq*/
MOV LR, R0 /* lade Rücksprungadresse*/
LDMFD SP!, {R0} /* stelle R0 wieder her*/
BX LR /* Return zur IRQ-ISR*/
.endfunc
Mein GNU-Port der NXP-Beispielsammlung ist möglicherweise hilfreich.
Download von
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/lpc2k_bundle_port/index.html
von Interesse dürfte v.a. der Code in Startup.S sein.
Ansonsten wie Andreas Kaiser schon schrieb: zu wenig Information. Am
Besten Minimalbeispiel erstellen, das das Fehlverhalten demonstriert.
Mit allen notwendigen Dateien (linker-script, makefile, Quellcode)
irgendwo auf einen Server legen oder als Attachment zu einem
Forenbeitrag hier.
Martin Thomas
In crt.s kann ich keine Initialisierung vom Sys/Usr Modus erkennen. Der
Code läuft also im SVC-Modus. Wenn der Handler dann in den Sys-Modus
wechselt ist kein gültiger Stack vorhanden.
PS: Code ist als Anhang lesbarer, alternativ als avrasm taggen. Der
Umbruch stört halt sehr.
In meinem Programm wird per Interrupt folgende Funktion aufgerufen:
void extint0(void) {
EXTINT = 0x00000001;
nested_irq_enable();
extintcounter++; // hochzählen
nested_irq_disable();
VICVectAddr = 0;
}
Hier die Funktion nested_irq_enable (so hier im Forum gefunden):
nested_irq_enable: /* Nested Interrupts Entry*/
STMFD SP!, {R0} /* stelle ein Register zur
Verfügung*/
MOV R0, LR /* sichere darin die
Returnadresse*/
MRS LR, SPSR /* sichere SPSR_irq über
LR_irq*/
STMFD SP!, {LR} /* auf dem IRQ Stack*/
MSR CPSR_c, #0x1F /* Modewechsel IRQ - SYS,
Freigabe IRQ*/
STMFD SP!, {LR} /* Sichere LR_sys auf dem User
Stack*/
BX R0 /* Return zur IRQ-ISR*/
In der Zeile MSR CPSR_c, #0x1F hängt sich mein Controller auf.
Dumme Frage: Was ist der SVC-Modus? Und wie kann ich die einzelnen Modi
im Startup initialisieren?
P.S.: Der nächste Code folgt ordentlich. Verprochen!
Apropos aufhängen: Debugging per JTAG ist ganz nett, aber manchmal sind
LEDs als Statusanzeige hilfreicher. Speziell dann, wenn nicht sicher
ist, ob das Problem genau da liegt wo es angezeigt wird, oder man
möglicherweise von einer Interferenz zwischen Debugger und System
geleimt wird.
An dem MSR kann ich nämlich kein Problem erkennen. Aber dieser Befehl
ermöglicht weitere Interrupts (eben das nesting), was den Schluss
nahelegt, dass eher dort das Problem liegt.
Hmm, da hast Du mich erwischt! Hab das Manual schon gelesen. Nur nach
den 3xx Seiten weiß ich auch nimmer alles. Supervisor Mode, oder?
Ich habe also für den User Mode den Stack initialisiert.
Keine Sorge, den dafür nötigen Rest habe ich auch erledigt.
Leider funktionieren jetzt überhaupt keine Interrupts mehr. Ich dachte
mit den Zeilen hier hätte ich Interrupts angeschaltet.
[avrasm]MRS r0, CPSR
BIC r0, r0, #I_BIT | F_BIT /* Enable FIQ and IRQ interrupt */
MRS CPSR, r0
[/arvasm]
Ist das jetzt nutzlos geworden?
Wäre es auch denkbar, dass ich gleich bei der Initialisierung die
Interrupts enable, also I_BIT und F_BIT nicht setzte? Oder ist es
sinnvoller wie in den Beispielen von Martin Thomas das erst im laufenden
Betrieb zu machen?
Zwei Möglichkeiten hattest du. Eine richtige, eine falsche...
Im User-Mode kannst du die Interrupts nicht kontrollieren. Keine Rechte.
Ich pflege Interrupts erst einzuschalten, wenn die Initialisierung durch
ist. Vermeidet Überraschungen. Die meisten anderen scheinen es ebenso zu
halten.
Sorry. Meinte GDB. Wenn ich es starte, hängt sich entweder Eclipse auf,
oder es kommt die Fehlermeldung "Stack is not available". Ziemlich
frustrierend...
In einem Anflug von Funktion konnte ich mal wieder debuggen. Und siehe
da, es klappt ohne Absturz!
Und wiedereinmal kann ich nur sagen: Vielen Dank! Echt klasse!
Hoffentlich komme ich bei zukünftigen Problemen mal selbst drauf.
Gibt es eigentlich noch mehr Tücken, die sich im Startup verstecken?
Wegen dem ständigen Aufhängen. Ich verwende diesen Befehlssatz
(vielleicht ist das dran schuld?):
target remote localhost:3333
monitor reset
monitor sleep 500
monitor poll
monitor soft_reset_halt
monitor arm7_9 sw_bkpts enable
monitor mww 0xE01FC040 0x0002
monitor mdw 0xE01FC040
break main
load
continue
So, habe alles neu installiert und jetzt klappt's.
Ich habe nun folgendes Rätsel:
Wenn ich einen Breakpoint an den Anfang meiner Interruptroutine setze,
erlebe ich den Einsprung und anschließend läuft mein Programm auch
völlig normal weiter.
Wenn ich den Breakpoint nun weglasse, den Interrupt auslöse und dann im
Debugger nachsehe, wo ich gelandet bin, stelle ich fest, dass ich im
PAbortHandler stecke.
Das kann doch irgendwie nicht sein, oder?
Wenn es mal wieder so ein Anfängererror (vgl. Manual) sein sollte, sagt
mir das bitte, aber irgendwie bin ich ratlos.
Habe bisher nur C16x programmiert und solche Erlebnisse waren da
irgendwie nicht an der Tagesordnung.
Bin wie immer für alle Ratschläge dankbar!