This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

CPU crash when enable NVIC for timer

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.

  • 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?

    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.