Forums

Timer0 interrupt problem in LPC21XX

Started by Barış January 26, 2010
Hi all,
I'm new in ARM CPUs and I've just started programming LPC series.I have a problem with Timer0s interrupt.

I am trying hitex's lpc2000 sample code with lpc2104 and comparing lpc2014 registers with sample code.It seems true but it doesn't work in keil's uvision.It doesnt enter ISR.Can anybody help me?

This is the code.
#include

void T0isr (void) __irq
{
T0IR|=1;
VICVectAddr=0;
}

int main ()
{
VPBDIV=2;
T0PR=4;
T0TCR=2;
T0MCR=3;
T0MR0`00;

VICVectAddr4=(unsigned)T0isr;
VICVectCntl4=0x24;
VICIntEnable |=0x10;

T0TCR=1;

while(1)
{

}
}

An Engineer's Guide to the LPC2100 Series

--- In l..., Barış wrote:
>
> Hi all,
> I'm new in ARM CPUs and I've just started programming LPC series.I have a problem with Timer0s interrupt.
>
> I am trying hitex's lpc2000 sample code with lpc2104 and comparing lpc2014 registers with sample code.It seems true but it doesn't work in keil's uvision.It doesnt enter ISR.Can anybody help me?
>
>

We've been talking about this all day! Are you certain that global interrupts are enabled in your startup code?

You should enable them just before branching to main():

MSR CPSR_c,#MODE_SVC /* enable interrupts */
b main /* Enter the C code */

I haven't used the Hitex code so I don't know what the startup file looks like.

Richard

Sorry for this newbie question but I'm new in this issue as I said.I have searched before writing but I didn't find usefull things.

Im using keil's uvision with RealView MDK-ARM version 4.02 toolchain.I'm creating new LPC2104 project with philips's standart "startup.s" code.When debugging, interrupt is generated but flow doesn't jump isr function.

Where I must write "MSR CPSR_c,#Mode_SVC" exactly?Here?

; Enter IRQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size

Do I have to change "#Mode_IRQ:OR:I_Bit:OR:F_Bit" with "#Mode_SVC"?
> We've been talking about this all day! Are you certain that global interrupts are enabled in your startup code?
>
> You should enable them just before branching to main():
>
> MSR CPSR_c,#MODE_SVC /* enable interrupts */
> b main /* Enter the C code */
>
> I haven't used the Hitex code so I don't know what the startup file looks like.
>
> Richard
>

--- In l..., Barış wrote:
>
> Sorry for this newbie question but I'm new in this issue as I said.I have searched before writing but I didn't find usefull things.
>
> Im using keil's uvision with RealView MDK-ARM version 4.02 toolchain.I'm creating new LPC2104 project with philips's standart "startup.s" code.When debugging, interrupt is generated but flow doesn't jump isr function.
>
> Where I must write "MSR CPSR_c,#Mode_SVC" exactly?Here?
>
> ; Enter IRQ Mode and set its Stack Pointer
> MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
> MOV SP, R0
> SUB R0, R0, #IRQ_Stack_Size
>
> Do I have to change "#Mode_IRQ:OR:I_Bit:OR:F_Bit" with "#Mode_SVC"?
>

No, this is far too early in the startup file (usually). You need to read farther along until just before it branches to main().

But, you can see now how the startup file is disabling interrupts: see that :OR:I_Bit:OR:F_Bit? When those bits are set the standard IRQ and FIQ are disabled. On the ARM, turning a bit ON disables the interrupt.

So, when you get to just before the branch to main(), you will omit the disable bits and this will leave the interrupts enabled.


> > MSR CPSR_c,#MODE_SVC /* enable interrupts */
> > b main /* Enter the C code */

The added 'MSR CPSR_c,#MODE_SVC' puts the chip in supervisor mode with the interrupts enabled just before 'b main' jumps to your C code.

Your code might not use 'b main' but there should be some comment that indicates that it is about to occur. If not, post the startup file and we can all take a look.

You can experiment later with running in Supervisor versus User mode. Most of the code I see just puts the chip in Supervisor mode and leaves it that way. At least on this small chips...

Richard

Hi Richard,
Thank you for your help.I did what you say.I changed the startup code like this but nothing changed.

; Enter the C code
MSR CPSR_c,#Mode_SVC

IMPORT __main
LDR R0, =__main
BX R0
I set a breakpoint in isr function and I want to set P0.1 bit at this point(line 32).But flow never jump this isr.It is counting in while loop.Here is the debugging screenshot
http://img168.imageshack.us/img168/56/debug.jpg

My main.c and Startup.s files
http://www.kayakburada.com/filez/main.c
http://www.kayakburada.com/filez/Startup.txt (.s changed to .txt)

> No, this is far too early in the startup file (usually). You need to read farther along until just before it branches to main().
>
> But, you can see now how the startup file is disabling interrupts: see that :OR:I_Bit:OR:F_Bit? When those bits are set the standard IRQ and FIQ are disabled. On the ARM, turning a bit ON disables the interrupt.
>
> So, when you get to just before the branch to main(), you will omit the disable bits and this will leave the interrupts enabled.
>
>
> > > MSR CPSR_c,#MODE_SVC /* enable interrupts */
> > > b main /* Enter the C code */
>
> The added 'MSR CPSR_c,#MODE_SVC' puts the chip in supervisor mode with the interrupts enabled just before 'b main' jumps to your C code.
>
> Your code might not use 'b main' but there should be some comment that indicates that it is about to occur. If not, post the startup file and we can all take a look.
>
> You can experiment later with running in Supervisor versus User mode. Most of the code I see just puts the chip in Supervisor mode and leaves it that way. At least on this small chips...
>
> Richard
>

--- In l..., Barış wrote:
>
> Hi Richard,
> Thank you for your help.I did what you say.I changed the startup code like this but nothing changed.
>
> ; Enter the C code
> MSR CPSR_c,#Mode_SVC
>
> IMPORT __main
> LDR R0, =__main
> BX R0
>
>
> I set a breakpoint in isr function and I want to set P0.1 bit at this point(line 32).But flow never jump this isr.It is counting in while loop.Here is the debugging screenshot
> http://img168.imageshack.us/img168/56/debug.jpg
>
> My main.c and Startup.s files
> http://www.kayakburada.com/filez/main.c
> http://www.kayakburada.com/filez/Startup.txt (.s changed to .txt)
>

VICVectCntl0 = 0x00000020;

should be:

VICVectCntl0 = 0x00000024;

This will assign the Timer0 interrupt to this channel. See Table 48 (in my LPC2148 User Manual which may not be identical to what you are using).

The startup file looks ok (except that it doesn't have the fix we were talking about and it needs it!) but there are a lot of IFDEF's (or equivalent) that I hope are defined correctly. For example, there is no External Memory Controller. Among other things...
This is my setup code for Timer0:

// set up Timer 0
TIMER0_TC = 0; // clear the timer count
TIMER0_PR = 1; // prescale divide by 2
TIMER0_MR0 = 14400; // divide by 14400 to get 2048 ints per second
TIMER0_MCR = 0x03; // interrupt on match, reset on match
TIMER0_TCR = 0x01; // start the timer

// set up VIC
VICVectCntl3 = 0x00000024; // set priority 3 for Timer 0
VICVectAddr3 = (unsigned long) T0_ISR;
VICIntEnable = (1 << T0_IntEnBit);

I'm not sure what clock you are running but your value for MR0 seems really low. What interrupt rate are you expecting?

I run at 14.7456 MHz (crystal) * 4 or 58.9824 MHz with PCLK = CCLK.

So:
58982400 / 2 (prescale) = 29491200
29491200 / 14400 (MR0) = 2048 interrupts per second.

Richard

Thank you Richard.I have done all things you said but it didn't work again.What an easy code but it doesn't work.It makes me crazy.I have searched google and I tried different methods.They didn't work too.
I am using uvision4.02 32k code limited evaluation version.Does this be a reason?

--- In l..., "rtstofer" wrote:
>
>
>
> --- In l..., Barış wrote:
> >
> > Hi Richard,
> > Thank you for your help.I did what you say.I changed the startup code like this but nothing changed.
> >
> > ; Enter the C code
> > MSR CPSR_c,#Mode_SVC
> >
> > IMPORT __main
> > LDR R0, =__main
> > BX R0
> >
> >
> > I set a breakpoint in isr function and I want to set P0.1 bit at this point(line 32).But flow never jump this isr.It is counting in while loop.Here is the debugging screenshot
> > http://img168.imageshack.us/img168/56/debug.jpg
> >
> > My main.c and Startup.s files
> > http://www.kayakburada.com/filez/main.c
> > http://www.kayakburada.com/filez/Startup.txt (.s changed to .txt)
> >
>
> VICVectCntl0 = 0x00000020;
>
> should be:
>
> VICVectCntl0 = 0x00000024;
>
> This will assign the Timer0 interrupt to this channel. See Table 48 (in my LPC2148 User Manual which may not be identical to what you are using).
>
> The startup file looks ok (except that it doesn't have the fix we were talking about and it needs it!) but there are a lot of IFDEF's (or equivalent) that I hope are defined correctly. For example, there is no External Memory Controller. Among other things...
>
>
> This is my setup code for Timer0:
>
> // set up Timer 0
> TIMER0_TC = 0; // clear the timer count
> TIMER0_PR = 1; // prescale divide by 2
> TIMER0_MR0 = 14400; // divide by 14400 to get 2048 ints per second
> TIMER0_MCR = 0x03; // interrupt on match, reset on match
> TIMER0_TCR = 0x01; // start the timer
>
> // set up VIC
> VICVectCntl3 = 0x00000024; // set priority 3 for Timer 0
> VICVectAddr3 = (unsigned long) T0_ISR;
> VICIntEnable = (1 << T0_IntEnBit);
>
> I'm not sure what clock you are running but your value for MR0 seems really low. What interrupt rate are you expecting?
>
> I run at 14.7456 MHz (crystal) * 4 or 58.9824 MHz with PCLK = CCLK.
>
> So:
> 58982400 / 2 (prescale) = 29491200
> 29491200 / 14400 (MR0) = 2048 interrupts per second.
>
> Richard
>

--- In l..., Barış wrote:
>
> Thank you Richard.I have done all things you said but it didn't work again.What an easy code but it doesn't work.It makes me crazy.I have searched google and I tried different methods.They didn't work too.
> I am using uvision4.02 32k code limited evaluation version.Does this be a reason?
>

I doubt it.

I use GNUARM on Linux which I build from source:
http://www.gnuarm.org/support.html

On Windows XP (x86 machine) I use YAGARTO (www.yagarto.de). Both are free with only the usual open source GPL licensing problems.

I posted a file LPC2106_BlinkingLED.zip to the Files folder. It uses interrupts to toggle an LED on the Olimex LPC2106 Prototype board. The LED is on P0.7

This code will build using GNUARM but you might get some troubleshooting ideas by looking through it.

Richard