I’m having trouble getting a simple LED flasher program to run. My actual applications are more complex, but I've had to back out to something trivial because no interrupt code that I write will run. I'm stuck with the 2138 platform for specific reasons.
I build on Crossworks with GCC for ARM, and load a bin file into the target flash or RAM via JTAG through Segger Jlink – AFAIAA the code is running pretty much on the metal, but with ARM it seems difficult to be sure what else might be going on lower down. The program uses timer0 (have also tried Timer1), a polled version runs perfectly, but a counterpart using timer interrupts doesn’t. When the program runs, the ISR doesn’t appear to get called, and if I force a program exit by incorporating a DI pin in the main() wait loop, the CPU seems to be in some sort of locked state – I have to do a PDPU to get it back.
There's nothing else loaded on the target. Flash and RAM loads behave the same. I’ve tried every combination of the MEMMAP settings so that isn’t the problem.
I’ve spent endless hours with the chip manual. I’ve also searched extensively, the web brings up some reports on ISR problem with the LPC2138, but they are all vague enough to be of minimal use. I’m wondering if there’s something lower down, may be in the C primitive (.s) that Crossworks automatically adds to the project, and which needs to be ‘tweaked’ for some reason. That’s an area I’d prefer not to get into.
Can any ARM gurus see an obvious problem?
Here’s the ISR version code. Aside from the ISR handling, it’s identical to the polled version, which works.
// Standard Crossworks includes for LPC213*.
#include <targets/LPC2000.h>
#include <intrinsics.h>
char d ; // LED state
void T0ISR() __attribute__ ((interrupt ("IRQ")));
void T0ISR()
{
long int Regval ;
Regval = T0IR ;
if (d == 0)
{
d = 1 ;
IO0SET = 0x80010000; // LED on
}
else
{
d = 0 ;
IO0CLR = 0x80010000; // LED off
}
T0MR0 = 1000000; // reset timer
T0IR = Regval ; // reset interrupt flag
VICVectAddr = 0 ;
}
int main(void)
{
char c ;
MEMMAP = 2 ; // Have tried every possible value
PINSEL2 = 0 ; // Ensure debug mode off
PCONP = 2 ; // TMR0 on
IO0DIR = 0x80000000; // turn on the LED driver (P0.31)
// Set up timer (works on polled version)
T0TC = 0 ;
T0PR = 2 ; // 1uS to main counter
T0MR0 = 1000000 ;
T0MCR = 3 ;
T0TCR = 1 ; // start timer
// Set up interrupt handling here
VICVectAddr0 = (unsigned long) T0ISR ;
VICIntSelect = 0 ; // All interrupts set as IRQ (not fast)
VICVectCntl0 = (0x20 | 4 ); // 20 = enable slot. 4 = T0
VICIntEnable |= (1UL << 4); // Enable T0 Interrupt
d = 0 ;
T0TCR = 1 ; // start timer
__enable_interrupt() ;
while(1)
{
}
return 0 ;
}