Tuesday, 1 December 2015

Problems with Cortex-M0 SysTick_Handler interrupt function ? Did you extern "C" it ?

SysTick is a system ticker on the ARM Cortex-M3 and -M0.

It is an extremely handy timer that counts down from a set 24-bit value. When it reaches 0, an interrupt can be set to do something, for example increment a counter.

In my case, I wanted a counter that would count roughly 1 millisecond at a time.

To set up the counter (on the LPC11U68), I do the following:

void init_timer(void) {
    // to get 1000 interrupts per second the reload value should be 48000
    SysTick->LOAD = 48000-1;
    SysTick->VAL  = 0;
    SysTick->CTRL  = 4 | 2 | 1; //CLKSOURCE=CPU clock | TICKINT | ENABLE
    pt_count = 0;
}
SysTick->LOAD is the value that Systick counts down from. So for a clock speed of 48 MHz, a countdown from 48000 will give you 1000 interrupts per second. The -1 is needed, but I can't remember what was the reason for it.

Here is the interrupt handler function:

void SysTick_Handler(void) {
    //interrupt happens when systick has counted down to zero
    pt_count++;                        // increment counter
}
However, the interrupt was not firing, and the counter was not growing !

I was like what ?!!?? I could see by hardware debugging that SysTick->VAL was decreasing, so SysTick was running.

The reason was very simple. SysTick_Handler is declared in startup_LPC11U68.cpp as follows:
WEAK void SysTick_Handler(void);
In addition, there is a implementation of an empty SysTick_Handler in the same file:
AFTER_VECTORS void SysTick_Handler   (void) {}
IN ORDER FOR YOUR OWN SysTick_Handler TO REPLACE THIS EMPTY FUNCTION THE NAME MUST BE EXACTLY THE SAME

Now, in a .cpp file, the name of your SysTick_Handler WILL BE MANGLED !

Therefore you MUST use extern "C" if your handler is within a .cpp file !

Like so:

extern "C" {
void SysTick_Handler(void) {
    //interrupt happens when systick has counted down to zero
    pt_count++;                        // increment counter
}

}