Forum: Mikrocontroller und Digitale Elektronik Nested Interrupt Problem - LPC2148 - Yagarto


von Jansus (Gast)


Lesenswert?

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

von Andreas K. (a-k)


Lesenswert?

Mit dem Stand an präsentierter Information wird das nix. Und daher 
bringt auch eine Wiederholung der Frage nichts.

von Jansus (Gast)


Angehängte Dateien:

Lesenswert?

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

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

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

von Andreas K. (a-k)


Lesenswert?

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.

von Jansus (Gast)


Lesenswert?

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.

von Jansus (Gast)


Lesenswert?

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!

von Andreas K. (a-k)


Lesenswert?

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.

von Andreas K. (a-k)


Lesenswert?

=> "Setup a stack for each mode".

von Andreas K. (a-k)


Lesenswert?

> Dumme Frage: Was ist der SVC-Modus?

Manual Not Read Error.
RTFM.

von Jansus (Gast)


Lesenswert?

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.
1
MSR     CPSR_c, #ARM_MODE_USER|I_BIT|F_BIT /* Interrupts disabled */
2
ldr     SP, __stack_usr_end

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?

von Andreas K. (a-k)


Lesenswert?

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.

von Jansus (Gast)


Lesenswert?

Gibt's eigentlich einen Trick um zu verhindern, dass sich OpenOCD in 90% 
aller Startversuche aufhängt?

von Andreas K. (a-k)


Lesenswert?

Kenne ich so nicht.

von Jansus (Gast)


Lesenswert?

Dass es sich ständig aufhängt?

von Andreas K. (a-k)


Lesenswert?

Ja.

von Jansus (Gast)


Lesenswert?

Sorry. Meinte GDB. Wenn ich es starte, hängt sich entweder Eclipse auf, 
oder es kommt die Fehlermeldung "Stack is not available". Ziemlich 
frustrierend...

von Jansus (Gast)


Lesenswert?

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

von Jansus (Gast)


Lesenswert?

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!

von Jansus (Gast)


Angehängte Dateien:

Lesenswert?

Zur Ergänzung:

Linkerskript im Anhang.
Debugge im RAM. Flash ist leer.

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.