Weird thing is going on here.
I have LPC1788 board and I just started writing a simple application. If I initialize timer like this, code seems to be executed, but of course my timer interrupt is not called.
void initTimer (void) { LPC_TIM_TypeDef *timer = LPC_TIM1; LPC_SC->PCONP |= (0x1<<2); timer->TC = 0x00; //Clear Timer Counter timer->PR = 0x00; //No prescaler timer->MCR = 0x3; //enable interrupt timer->MR0 = 0x02710; //interrupt every 1ms //NVIC_EnableIRQ(TIMER1_IRQn); timer->TCR = 0x02; //reset timer timer->TCR = 0x01; //enable timer counter } void TIMER1_IRQHandler(void) { LPC_TIM1->IR = (1u<<0); // Reset the MR0 Interrupt; Writing a zero has no effect. decrementFlags(); }
As soon as I enable NVIC IRQ, my code crash and points to Default_Handler PROC in startup.s. Deducing R15(PC) with -8 and use U 0xXXX, I end up in SVC_Handler part. My Timer1_IRQ never got called.
There is really nothing going on in the code besides this. As I just started writing program and hit the wall...
Any idea what else could I try, to debug this ?
Thanks.
Wouldn't it be logical to configure the VIC before you enable the timer interrupt?
Well, yes it makes sense, but it doesnt fix the issue. Interrupt wouldnt be called in next 2 processor cycles anyway, so it is just a minor flaw. CPU seems to crash after a while. I tried to step into with debugger, but it takes ages to crash so I just quit after few hundred steps. It is as if it doesnt see the Handler or something ...
So are you getting a Hard Fault and, thence, ending up in the Default Handler?
Search here for info & references on debugging a Hard Fault...
Don't bet on any 2 clock cycles.
Remember that your code does
timer->MCR = 0x3; //enable interrupt timer->MR0 = 0x02710; //interrupt every 1ms
after you have told the timer to run - and to interrupt and reset on match. Have you considered what value MR0 has before you assign to it?
What if you have counter=0, match register=0 - how long would the timer then need to decide it's time to generate an interrupt and reset the timer?
In general, it is always best to evaluate what operation depends on what registers. And make sure they have been given proper values before their value is needed. Having an "interrupt now" configuration for the timer, where it every clock cycle would match the interrupt condition would be a good way to try to keep the interrupt subsystem busy.
Well, I thought that interrupt will not actually execute before the timer been started, and that happens after setting the NVIC.
timer->MCR = 0x3; //enable interrupt NVIC_EnableIRQ(TIMER1_IRQn); //enable handler timer->TCR = 0x01; //enable timer counter
I dont really end up in Hard Fault when I break the execution. It points to the Default Handler part of startup code. As I said, it looks like that if I havent defined the IRQ handler.
How would that stop the interrupt occurring? wouldn't it just mean that the interrupt gets called earlier than expected?
The timer does not care about what you do with the NVIC. It's the reverse - you need to make sure the NVIC is ready when the timer needs it.
The timer starts when you order it to start. So the timer starts when you make your assign to T0TCR.
But I don't think the timer needs to start. When you write T0MCR = 3, you explicitly enable match control register 0. And with T0TC = 0 and T0MR0 = 0 - why shouldn't the hardware comparator then instantly see a match without waiting for you to turn on the counter with the final T0TCR assign?
If out with a gun, it's best to aim first and then fire. When initializing processor hardware, it's best to do all preparations before you start to activate any enable bits. Never arm a mouse trap with your fingers still in the trap :)
I dont really end up in Hard Fault when I break the execution. It points to the Default Handler part of startup code. As I said, it looks like that if I havent defined the IRQ handler. Then are you sure that the actual definition is provided is Startup assembly file? that might be just a misspelling problem for TIMER1_IRQHandler
I am using default startup file from Keil. But I did check that handler is there, and I did defined it in my project.
We haven't seen any new post with code that initializes the VIC before the timer may start to create interrupts.
This is the whole code.. I changed to Timer0 but it crashes as well ...
#include <LPC177x_8x.H> void TIMER0_IRQHandler(void); void SystemInit() { } int main (void) { NVIC_EnableIRQ(TIMER0_IRQn); LPC_SC->PCONP |= 1 << 1; LPC_SC->PCLKSEL |= 1 << 2; LPC_TIM0->MR0 = 1 << 23; LPC_TIM0->MCR |= 1 << 0; LPC_TIM0->MCR |= 1 << 1; LPC_TIM0->TCR |= 1 << 1; LPC_TIM0->TCR &= ~(1 << 1); LPC_TIM0->TCR |= 1 << 0; while (1) {} return 0; } void TIMER0_IRQHandler(void) { if ( (LPC_TIM0->IR & 0x01) == 0x01 ) { LPC_TIM0->IR |= 1 << 0; } }
Is this in a .CPP file?
Does the name for the IRQ match exactly with what is in the startup_arch.s file's vector table?
It points to the Default Handler part of startup
And guess what that Default Handler is for: it's where interrupts end up that didn't have a handler set up, at the time they fired.
So, in the light of this: are you still sure that your setting up of interrupt handlers was done early enough, and correctly?
It is the .cpp file. Apart from the code above which is in main.cpp file, i only have startup_LPC177x_8x.s file in the project.
No need to paste whole .s file ... this is only the part of Default handler and vectors in which timer is defined ... rest is removed from the post (but it exists in the project code).
__Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD TIMER0_IRQHandler ; 17: Timer0 DCD TIMER1_IRQHandler ; 18: Timer1 DCD TIMER2_IRQHandler ; 19: Timer2 DCD TIMER3_IRQHandler ; 20: Timer3 IF :LNOT::DEF:NO_CRP AREA |.ARM.__at_0x02FC|, CODE, READONLY CRP_Key DCD 0xFFFFFFFF ENDIF AREA |.text|, CODE, READONLY Default_Handler PROC EXPORT WDT_IRQHandler [WEAK] EXPORT TIMER0_IRQHandler [WEAK] EXPORT TIMER1_IRQHandler [WEAK] EXPORT TIMER2_IRQHandler [WEAK] EXPORT TIMER3_IRQHandler [WEAK] EXPORT PLL1_IRQHandler [WEAK] WDT_IRQHandler TIMER0_IRQHandler TIMER1_IRQHandler TIMER2_IRQHandler TIMER3_IRQHandler PLL1_IRQHandler B . ENDP ALIGN
But it is the standard startup file that is included when the project is created. Havent modify anything from it.