Interruptions on LPC2148 (logomatic V2) with GCC

Hi all,

I am trying to use the reception interrupt on UART0 for the LPC2148 and I seem to have an issue.

Apparently it properly calls my ISR but also the spurrious handler and this guy never returns.

I am using the irq.c/h library that came with the logomatic code.

(I tried loading the registers manually to the same effect.)

Here is the log I get, in bold, commented in italics:

The bootloader calls the firmware - from there on there is my console kicking in, this time trying to react to UART0 interruptions upon characters:
Calling firmware…
Console initialized
Means that the main commands are registered and will be understood.
this is higher level and irrelevant to my problem.
As soon as it is initialized, it dumps the value of the main registers:
VIC main registers:
VICIRQStatus = 00000000
VICFIQStatus = 00000000
VICRawIntr = 00003008
VICIntSelect = 00000000
VICIntEnable = 00000040
VICSoftInt = 00000000
VICProtection = 00000000
VICVectAddr = 0001029C
VICDefVectAddr = 0001029C
VIC vectors - VICVectAddr[0-15]:
0 = 0001169C
1 = 00000000
2 = 00000000
3 = 00000000
4 = 00000000
5 = 00000000
6 = 00000000
7 = 00000000
8 = 00000000
9 = 00000000
10 = 00000000
11 = 00000000
12 = 00000000
13 = 00000000
14 = 00000000
15 = 00000000
VIC IRQ control registers - VICVectCntl[0-15]:
0 = 00000026
1 = 00000000
2 = 00000000
3 = 00000000
4 = 00000000
5 = 00000000
6 = 00000000
7 = 00000000
8 = 00000000
9 = 00000000
10 = 00000000
11 = 00000000
12 = 00000000
13 = 00000000
14 = 00000000
15 = 00000000
UART 0 registers:
U0RBR = 00000000
U0THR = 00000000
U0DLL = 00000000
U0DLM = 00000001
U0IER = 00000001
U0IIR = 000000C1
U0FCR = 000000C1
U0LCR = 00000003
U0MCR = 00000000
U0LSR = 00000000
U0MSR = 00000000
U0SCR = 00000000
Timer 0 registers:
T0IR = 00000000
T0TCR = 00000000
T0TC = 00000000
T0PR = 00000000
T0PC = 00000000
T0MCR = 00000000
T0MR0 = 00000000
T0MR1 = 00000000
T0MR2 = 00000000
T0MR3 = 00000000
T0CCR = 00000000
T0CR0 = 00000000
T0CR1 = 00000000
T0CR2 = 00000000
T0CR3 = 00000000
T0EMR = 00000000
GPIO registers:
IOPIN0 = 7E1FFFFE
IODIR0 = 80000884
IOPIN1 = FFFF0000
IODIR1 = 00000000
Then it finishes the initialization sequence:
- Announces the code version
- Attempts to open a script file (fed to the consoel as if it were from the teraterm on the PC)
Flight Controller v0.1
Auto-executing script: FlightControlAuto.script
*** Could not open the script “FlightControlAuto.script”
The script file was not found (normal: there is none!)
Then I type any character onto the console.
The ISR is defined as follows:
void UART0_ISR(void) attribute ((interrupt(“IRQ”)));
void UART0_ISR(void)
{
IOPIN0 ^= (1 << 2);
Console_ASR();

// A read is required to clear the interrupt
rprintf(“U0IIR = %08x\n”, U0IIR);
// Dummy write to signal the end of interrupt
VICVectAddr = 0;
}
And we observe
- The charater I typed (‘c’) is properly resent to the console (by the Console_ASR() funtion)
- The U0IIR has been read (since it got dumped here)
cU0IIR = 000000C1
…And then right away the spurrious interuption handler, which also dumps the registers.
I went through all the registers and I don’t see what I missed…
Default VIC Stop
VIC main registers:
VICIRQStatus = 00000000
VICFIQStatus = 00000000
VICRawIntr = 00003008
VICIntSelect = 00000000
VICIntEnable = 00000040
VICSoftInt = 00000000
VICProtection = 00000000
VICVectAddr = 0001029C
VICDefVectAddr = 0001029C
VIC vectors - VICVectAddr[0-15]:
0 = 0001169C
1 = 00000000
2 = 00000000
3 = 00000000
4 = 00000000
5 = 00000000
6 = 00000000
7 = 00000000
8 = 00000000
9 = 00000000
10 = 00000000
11 = 00000000
12 = 00000000
13 = 00000000
14 = 00000000
15 = 00000000
VIC IRQ control registers - VICVectCntl[0-15]:
0 = 00000026
1 = 00000000
2 = 00000000
3 = 00000000
4 = 00000000
5 = 00000000
6 = 00000000
7 = 00000000
8 = 00000000
9 = 00000000
10 = 00000000
11 = 00000000
12 = 00000000
13 = 00000000
14 = 00000000
15 = 00000000
UART 0 registers:
U0RBR = 00000000
U0THR = 00000000
U0DLL = 00000000
U0DLM = 00000001
U0IER = 00000001
U0IIR = 000000C1
U0FCR = 000000C1
U0LCR = 00000003
U0MCR = 00000000
U0LSR = 00000000
U0MSR = 00000000
U0SCR = 00000000
Timer 0 registers:
T0IR = 00000000
T0TCR = 00000000
T0TC = 00000000
T0PR = 00000000
T0PC = 00000000
T0MCR = 00000000
T0MR0 = 00000000
T0MR1 = 00000000
T0MR2 = 00000000
T0MR3 = 00000000
T0CCR = 00000000
T0CR0 = 00000000
T0CR1 = 00000000
T0CR2 = 00000000
T0CR3 = 00000000
T0EMR = 00000000
GPIO registers:
IOPIN0 = 7E9FE7FA
IODIR0 = 80000884
IOPIN1 = FFFF0000
IODIR1 = 00000000
Attempting to exit the default handler…
…And the spurrious handler runs and runs and runs and runs…
Default VIC Stop
VIC main registers:
VICIRQStatus = 00000000
VICFIQStatus = 00000000
VICRawIntr = 00003008
VICIntSelect = 00000000
VICIntEnable = 00000040
VICSoftInt = 00000000
VICProtection = 00000000
VICVectAddr = 0001029C
VICDefVectAddr = 0001029C

That’s it.

Can anyone point me to the stupid thing I missed in the registers?

The Console_ASR works just fine when I am polling: it slurps any character that shows up in the buffer and it works just fine when just polling on its own, however I need the cranking power of the ARM for more than just handling the console and I will need a working interruptions mechanism…

Thansk and best regards to all you LPCers out there.

Is it licit to call a function from an ISR?

I do that a lot with other compilers (IAR EWARM), but how about with gcc?

…Apparently this is not the problem: just toggling the LED, reading U0IIR and writing VICVectAddr gives the same result.

Found!

My bad: looking into Startup.S it appears that there is an interruption wrapper that calls the vector returned by the VIC.

This means my ISR should not return from interrupt but just a simple return from function, i.e. ISRs are normal functions that should not be declared specially - how much simpler.

I did not modify the startup.s at all, meaning the ISRs still have to write a 0 at VICVectAddr before returning, after clearing the individual interrupt cause.