Forum: Mikrocontroller und Digitale Elektronik LPC2138 und UART mit Interrupts


von funker211 (Gast)


Lesenswert?

Hallo Community,

versuche grad die UART0 eines LPC2138 mit Interrupts in Betrieb zu 
nehmen, und obwohl mir das schon mal mit einem LPC2129 unter UART0 
erfolgreich gelungen ist, krieg ich's nicht hin...

Umgebung: Yagarto (Eclipse, arm-elf-gcc, arm-elf-gdb, OpenOCD und 
Amontec JTAGkey).

Kann mir jemand kurz sagen, was die typischen Fehler sind?

---
Ich nutze IRQ.
Im Startup Code daher:
1
_vectors:
2
  ldr pc, ResetAddr    // Reset
3
  ldr pc, UndefAddr    // Undefined instruction
4
  ldr pc, SWIAddr      // Software interrupt
5
  ldr pc, PAbortAddr    // Prefetch abort
6
  ldr pc, DAbortAddr    // Data abort
7
  ldr pc, ReservedAddr  // Reserved
8
  ldr pc, [pc, #-0xFF0]   // IRQ interrupt: jump to whatever VICVectAddr points to
9
  ldr pc, FIQAddr      // FIQ interrupt

VICVectAddr sollte von VicVectAddr0 geladen werden.

Code aus UART-Konfig:
1
// Clear any pending interrupts / Disable interrupts
2
VICINTENCLR = MASK_VIC_UART0;
3
    
4
// Make UART 0 Interrupt an IRQ Interrupt
5
VICINTSELECT &= (~MASK_VIC_UART0);
6
 
7
// Register UART ISR as vectored interrupt:
8
// Write IRQ Handler address to VICVECTRADDRx,
9
// write IRQ Channel to VICVECTCNTLx
10
VICVECTADDR0 = (DWORD)IoUart0Isr;
11
VICVECTCNTL0 = (DWORD)(VIC_CHANNEL_UART0 | VICVECTCTRL_IRQENA); 
12
    
13
// Enable UART 0 Interrupt Source
14
VICINTENABLE |= MASK_VIC_UART0;
15
    
16
// Enable specific interrupts:
17
// Receive Data Available (RDA) und
18
// Transmit Hold Register Empty (THRE) Interrupt
19
U0IER |= (MASK_UXIER_RDA | MASK_UXIER_THRE);

Und ISR:
1
void  __attribute__ ((interrupt ("IRQ"))) IoUart0Isr (void) {
2
3
  ... // Code weggelassen
4
    
5
  // Clear UART Interrupt by reading U0IIR
6
  counter = U0IIR;
7
    
8
  // Acknowledge IRQ
9
  VICVECTADDR = 0;
10
}


Das ganze läuft im RAM. Dazu habe ich das Memory Remapping per Debugger 
eingestellt (Skript für GDB):

monitor mww 0xE01FC040 0x02

Allerdings liefert mit obiges immer eine Fehlermeldung, scheint aber 
trotzdem zu funktionieren, denn wenn ich es weglasse, geht gar kein 
Debuggen, mit o.g. Befehl geht debuggen, aber im Falle eines Interrupts 
sprint das Ding sonst wohin...

von funker211 (Gast)


Lesenswert?

Ach, ist es nicht schön, wenn man beim Schreiben endlich beginnt, 
nachzudenken?

Das Memory Mapping scheint wohl tatsächlich nicht zu funktionieren, also
1
 monitor mww 0xE01FC040 0x02
ist tatsächlich nicht erfolgreich, wie ja die Meldung eigentlich auch 
sagt.

Also daher jetzt eine konkretere Frage:

Was kann die Ursache dafür sein, dass dieser Zugriff nicht funktioniert?

Hier meine gesamte GDB-Initialisierung:
1
target remote localhost:3333
2
monitor reset
3
monitor sleep 500
4
monitor poll
5
monitor soft_reset_halt
6
monitor sleep 500
7
monitor arm7_9 sw_bkpts enable
8
monitor debug_level 3
9
monitor sleep 500
10
monitor mww 0xE01FC040 0x02
11
monitor sleep 500
12
break main
13
load
14
continue

Lasse ich den Debugger starten, und mache dann später manuell den 
monitor mww trallalla-Befehl über eine telnet-Verbindung zu OpenOCD, 
dann klappt's.

Ist ggf. der ARM nicht im richtigen Zustand nach einem Reset, um in 
MEMMAP schreiben zu dürfen? Aber der müsste doch im ARM-Mode und 
Supervisor-Mode starten, oder, also mir alle Rechte einräumen, zumal 
über JTAG...

Irgendwelche Ideen?

von funker211 (Gast)


Lesenswert?

Lösung:
1
monitor soft_reset_halt
 auskommentiert.

Dafür weiter oben
1
monitor reset run_and_halt

Nun geht's, jetzt ist der Befehl
1
monitor mww 0xE01FC040 0x02
endlich erfolgreich.

Und kaum ist die Vektortabelle aus dem SRAM richtig in den Adressbereich 
0x00000000 gemappt, funktionieren auch die Interrupts.

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.