Forum: Mikrocontroller und Digitale Elektronik ARM7 LPC2148 und UART Interrupt


von Arne (Gast)


Angehängte Dateien:

Lesenswert?

Moin zusammen,

ich quäl mich gerade mit einem LPC2148 rum.
Compiler ist IAR EWARM 5.4 mit Segger J-Link.

Und zwar bin ich momentan am UART. Senden (gepollt) funktioniert, nun 
will
ich den Empfang per IRQ lösen. Vermutlich habe ich die Interruptstruktur 
des ARM7
noch nicht so ganz geschnallt, daher hier mal ein Auszug aus dem 
cstartup.s von IAR:
1
; The module in this file are included in the libraries, and may be
2
; replaced by any user-defined modules that define the PUBLIC symbol
3
; __iar_program_start or a user defined start symbol.
4
;
5
; To override the cstartup defined in the library, simply add your
6
; modified version to the workbench project.
7
8
        SECTION .intvec:CODE:NOROOT(2)
9
10
        PUBLIC  __vector
11
        PUBLIC  __vector_0x14
12
        PUBLIC  __iar_program_start
13
        EXTERN irq_handler,fiq_handler
14
15
        ARM
16
__vector:
17
        ;;
18
        ldr   pc,[pc,#+24]              ;; Reset
19
        B   .                           ;; Undefined instructions
20
        B   .                           ;; Software interrupt (SWI/SVC)
21
        B   .                           ;; Prefetch abort
22
        B   .                           ;; Data abort
23
__vector_0x14:
24
        DC32  0                         ;; RESERVED
25
        ldr   pc,[pc,#+24]              ;; IRQ
26
        ldr   pc,[pc,#+24]              ;; FIQ
27
28
        DC32  __iar_program_start       ;; Reset
29
        DC32  0                         ;; Undefined instructions
30
        DC32  0                         ;; Software interrupt (SWI/SVC)
31
        DC32  0                         ;; Prefetch abort
32
        DC32  0                         ;; Data abort
33
        DC32  0                         ;; RESERVED
34
        DC32  irq_handler               ;; IRQ
35
        DC32  fiq_handler               ;; FIQ
Das sollte der interessante Teil in cstartup.s sein (sonst wird es zu 
lang.
__iar_program_start ist weiter unten definiert (MAM-Init usw.)

In main habe ich:
1
/*************************************************************************
2
 * Function Name: irq_handler
3
 * Parameters: void
4
 * Return: void
5
 *
6
 * Description: IRQ subroutine
7
 *
8
 *************************************************************************/
9
__irq __arm extern void irq_handler (void)
10
{
11
  void (*interrupt_function)();
12
  uint32 vector;
13
14
  vector = VICVectAddr;    /* Get interrupt vector.        */
15
  interrupt_function = (void(*)())vector;
16
  (*interrupt_function)();  /* Call vectored interrupt function.  */
17
  VICVectAddr = 0;
18
}
19
20
/*************************************************************************
21
 * Function Name: fiq_handler
22
 * Parameters: void
23
 * Return: void
24
 *
25
 * Description: FIQ subroutine
26
 *
27
 *************************************************************************/
28
__fiq __arm extern void fiq_handler (void)
29
{
30
  void (*interrupt_function)();
31
  uint32 vector;
32
33
  vector = VICVectAddr;    /* Get interrupt vector.        */
34
  interrupt_function = (void(*)())vector;
35
  (*interrupt_function)();  /* Call vectored interrupt function.  */
36
  VICVectAddr = 0;
37
}

Damit ich nicht zuviel wirres Zeug schreibe, mal die beiden Screenshots 
der Register für VIC und UART anbei. Die ISR für UART 0 liegt bei 
0x000008c8 (lt Mapfile). In CPSR sind I-Bit und F-Bit 0.

Habe in irq_handler() einen Breakpoint gestellt und er läuft nicht 
drauf, wenn ich über TeraTerm Zeichen sende (9600 8N1).

Any idea?

thanx, Arne

von Arne (Gast)


Lesenswert?

Keiner 'ne Idee? Rettet meinen Sonntag! ;-)

von Wilhelm F. (Gast)


Lesenswert?

Die Hardware scheint ja schon zu funktionieren, wenn du damit, 
allerdings ohne Interrupt, schon gearbeitet hast.

Wo der VIC-Controller initialisiert wird, sehe ich so direkt nicht...

Hattest du schon mal einen anderen Interrupt als den UART zum laufen 
bekommen?

von Arne (Gast)


Lesenswert?

> Wo der VIC-Controller initialisiert wird, sehe ich so direkt nicht...
Vector #6 in cstartup.s verweist auf irq_handler, in irq_handler zieht 
er sich den ausgelösten INT über
1
vector = VICVectAddr;
und springt dann mittels Funktionspointer
1
(*interrupt_function)();
 in die eigentlich Behandlungsroutine.

Was müsste ich sonst noch initialisieren?
Enabled ist der IRQ (s. Screenshot VIC.gif) sowohl in VICIntEnable, als 
auch in VICVectCntl6.
Globale INTs in CPSR sind auch enabled (I/F-Bit beide auf 0).

> Hattest du schon mal einen anderen Interrupt als den UART zum laufen
bekommen?
Nein, habe eben ein Testprg hochgezogen, das auf Buttondruck den EINT1 
auslöst - kein Erfolg. :-(
PINSEL0 ist auch entsprechend gesetzt (0x8000 für EINT1).

von Wilhelm F. (Gast)


Lesenswert?

Der IAR-Code ist für mich etwas ungewohnt, da ich mit Keil arbeitete. Es 
ist manches auf andere Art gelöst. Aber das sollte letztendlich doch 
gehen.

Das sieht aber ansonsten alles vernünftig aus. Ich schau aber nochmals 
drüber.

Geht das Programm jetzt gar nicht mehr, macht es nur die Interrupts 
nicht, oder was macht es noch?

von Arne (Gast)


Lesenswert?

Der IAR Debugger hat mich wohl in die Irre geführt - die Demo zum 
Auslösen des EINT1 per Button funktioniert jetzt.
In meinem Init-code habe ich jetzt ein VICVectAddr = 0 eingefügt. Damit 
klappt der EINT-Test. Der UART weigert sich weiterhin. Am Prg.anfang 
springt er ab und an in den Handler für meinen UART, aber U0IIR.IP ist 
'1'?!?!

Die Handler für die Interrupts in meinem API muss ich ja nicht mit 
"__irq __arm" markieren? Das passiert ja schon über irq_handler - 
richtig?

von Arne (Gast)


Lesenswert?

Wilhelm Ferkes schrieb:
> Geht das Programm jetzt gar nicht mehr, macht es nur die Interrupts
> nicht, oder was macht es noch?

Also ich sende am Anfang 10 Char - die kommen in TeraTerm auch an. Nur 
Empfang per INT funktioniert nicht. Sonst baue ich erstmal was ein, dass 
Empfang per Polling macht...

von Wilhelm F. (Gast)


Lesenswert?

Arne schrieb:

>Sonst baue ich erstmal was ein, dass
>Empfang per Polling macht...

Schnell genug wäre der ARM ja meist auch für Polling. Das ist aber keine 
ernsthaft saubere Lösung.

>Damit klappt der EINT-Test. Der UART weigert sich weiterhin.

Na prima. Dann funktioniert die Interruptsache schon mal generell.

>Am Prg.anfang springt er ab und an in den Handler für meinen UART,
>aber U0IIR.IP ist '1'?!?!

Ich schau nochmal nach, wie das in meinem Sourcecode war, hatte den UART 
auch schon am laufen, allerdings im LPC2129. Die µC sind aber da 
prinzipiell gleich.

Zum Debuggen sollte auch die Codeoptimierung des Compilers auf Null bzw. 
deaktiviert sein. Nur als Randbemerkung. Da hab ich auch schon seltsame 
Dinge erlebt.

von Arne (Gast)


Lesenswert?

Wilhelm Ferkes schrieb:
> Zum Debuggen sollte auch die Codeoptimierung des Compilers auf Null bzw.
> deaktiviert sein.

Ist meine erste 'Amtshandlung' bei IAR Projekten, da der die 
Debug-Projekte per default auf Optimierungsstufe 'Low' stellt :-/

UART Empfang funktioniert jetzt zumindest soweit, dass die ISR 
aufgerufen wird. Ich hatte als INT-Quelle U0IER.RXLSIE gesetzt statt 
U0IER.RDAIE.
Jetzt rennt er zwar auf den Breakpoint in der ISR, aber U0LSR.DR ist 
'0'!
Wie passt das zusammen? Er empfängt was, meint in der ISR aber (bevor 
ich U0RBR anfasse), dass er eigentlich nix empfangen hat.

von Arne (Gast)


Lesenswert?

Scheint jetzt zu funktionieren!

Der Debugger verar***t mich. Wenn ich einen Breakpoint in die ISR setze, 
dann verhält sich das ganze System anders, als wenn ich den Breakpoint 
rausnehme! Ich krieg die Krätze!
Aber Danke für Deine Hilfe. Schönen Sonntag noch.

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.