STM32 SysTick Interrupts

I’m missing something obvious in trying to get systick interrupts working on an Olimex STM32-P103 board with an ARM-USB-OCD jtag probe and am wondering if anyone has seen something similar or sees where I went wrong?

I’m using the STM32 StdPeriph_Lib_V3.1.2 to do the setup with

SysTick_Config(SystemFrequency / 500) for 2ms ticks.

I placed a function call in the stm32f10x_it.c SysTick_Handler to call my timer routine which currently just pulses a GPIO pin.

The pin never pulses and the interrupt is never invoked. I verified that the handler is installed by dumping the memory at 0x0000_003C and that address does point to the SysTick_Handler. Disassembling SysTick_Handler shows a bl to my function call, so I think the vector table is properly loaded and contains valid calls.

Next, I added a poll of the SysTick control register in my main loop and pulse the GPIO pin when the CountFlag goes high. Sure enough, I get a pulse every 2ms and the Systick works as expected with the auto-reload functioning and the timebase is as expected. Still no interrupt called though, even though the systick control register interrupt enable is set.

The systick example in StdPeriph_Lib does no other setup other than the one call to SysTick_Config().

Any thoughts?

Jim

A few things to check;

The definition SystemFrequency, that exists and is at 72000000 (72MHz) or similar?

You have “.word SysTickHandler” in your statup script file?

Are you calling “SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);”?

I had to comment this out to get SysTick to work for me.

Last thing “SysTick_Config(SystemFrequency / 100);” gives me 10mS “ticks”, so your “… / 500” should be correct.

Hi

It sounds as though interrupts are not enabled.

  1. Enable the SYSTICK interrupt by writing its priority to 0xe000ed20

SYSTEM_HANDLER_12_15_PRIORITY_REGISTER |= (SYSTICK_PRIORITY << 24); // enter the SYSTICK priority

  1. Enable interrupts globally - assembler is something like:

asm(“cpsie i”);

Regards

Mark

Thanks for the suggestions, but still no luck.

Priority is set with NVIC_SetPriority(SysTick_IRQn, Priority);

where SysTick_IRQn = -1.

When the requested irq is negative, this function sets the core interrupt priority:

if(IRQn < 0) {

SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */

I also had previously tried __enable_irq(); with no effect and I also tried __enable_fault_irq(); with no effect.

As mentioned earlier, mem dumps and disassembly show that the vectors are loaded correctly and my function is called from within the SysTick_Handler.

This is so strange.

Jim

Hi

Maybe it is getting to your interrupt once.

Assuming that the interrupt may arrive there, have you then cleared the SYSTICK interrupt?

INT_CONT_STATE_REG = PENDSTCLR; // reset interrupt

0x40004d04 written with 0x02000000

Without clearing the interrupt it would probably re-enter again immediately (port output would then toggle very fast), or maybe it doesn’t come back in ever again (?)

Regards

Mark

I added

SCB->ICSR = SCB_ICSR_PENDSTCLR;

to the handler, but it (the handler) does not get invoked even once. My scope is set to normal triggering and the GPIO port never toggles even once.

Again, if I poll the control register 0xE000E010 and test the COUNTFLAG, toggling the GPIO bit when set, I get the expected pulse at the desired 2ms interval. The SysTick is functioning, but not the interrupt.

The control register setup reads back 0x7,

CLKSOURCE = 1

TICKINT = 1

ENABLE = 1

Hi

But if the interrupt is arriving it will either jump to your routine (which it seemingly isn’t) or jump somewhere else. If that somewhere else is not defined it will result in a crash.

It may be that the code is crashing or it may be that the interrupt is being handled by a default handler - is it possible to identify this?

Furthermore, are you running from FLASH or SRAM? When running from FLASH the default interrupt vector table at 0x00000000 is correct. When running from SRAM the vector table may need to be moved by writing VTOR: offset 0xd08 in the Cortex M3 registers.

I haven’t used the ST32 but have developed low level code for the Luminary Micro and LPC17X Cortex M3 parts - I would expect the ST32 to be identical in this area (the only difference I had with the ones I have used was to do with the vector table mapping since the LPC17XX doesn’t fully respect the Cortex M3 memory layout. This was only an issue when the vector table was relocated to SRAM).

Regards

Mark

www.uTasker.com

Running from flash. There is something fundamental going wrong here.

Here is a dump of the vectors, with SysTick being the 15th pointing to 0x080007e1. A disassembly of that address shows the SysTick_Handler that calls my routine. I also tried the GPIO toggle here in this routine but it never gets called.

x /16 0
0x00:	0x20005000	0x0800010c	0x08000791	0x0800079d
0x10:	0x080007a5	0x080007ad	0x080007b5	0x00000000
0x20:	0x00000000	0x00000000	0x00000000	0x080007bd
0x30:	0x080007c9	0x00000000	0x080007d5	0x080007e1

disassemble 0x080007e1
Dump of assembler code for function SysTick_Handler:
0x080007e0 <SysTick_Handler+0>:	push	{r7, lr}
0x080007e2 <SysTick_Handler+2>:	add	r7, sp, #0
0x080007e4 <SysTick_Handler+4>:	bl	0x8000450 <SysTickInterrupt>
0x080007e8 <SysTick_Handler+8>:	mov	sp, r7
0x080007ea <SysTick_Handler+10>:	pop	{r7, pc}
End of assembler dump.

As I mentioned, there is something fundamental wrong. I also tried implementing the timer with a peripheral timer and that one also refuses to generate interrupts.

I don’t know if it is in the tools, OpenOCD, or in the startup assembly.

Jim

Hi Jim

If neither SYSTICK or another timer is generating interrupts it either means that the global interrupt is masked or that the timers haven’t been set up correctly to generate interrupts.

Check these:

  1. The SYSTICK configuration (this example is for 50ms from a 96MHz clock)
    SYSTICK_RELOAD = 0x00493dff; // set reload value to determine the period
    SYSTEM_HANDLER_12_15_PRIORITY_REGISTER |= (SYSTICK_PRIORITY << 24);  // enter the SYSTICK priority
    SYSTICK_CSR = (SYSTICK_CORE_CLOCK | SYSTICK_ENABLE | SYSTICK_TICKINT); // enable timer and its interrupt - value is 0x00000007

Make sure that the interrupt bit has also been set so that it will also interrupt on reload and not just count.

  1. Check the PRIMASK in the core registers [CORTEX_M3_REGS.ulPRIMASK] It must be 0. If it is 1, all interrupts are masked.

The vector table configuration looks fine so I don’t think that this has anything to do with the problem.

If you are still convinced that interrupts are occurring there is a simple test; set the vector base address to an invalid area of memory. The NVIC will always try to read the vector from this area and will fail with a hardware access error. Normally this will result in the fault interrupt being called, but is not possible since the fault is due to a vector table access and will fail itself. This will thus set the VECTTBL bit in the Cortex M3 HSFR register, signaling that a fault occurred on attempted NVIC read from the vector table. If you can detect that this bit is being set (the system is also in a crashed state now) it will confirm that an interrupt really occurred since there is no other possibility of setting it.

Regards

Mark

[www.uTasker.com](http://www.uTasker.com)

Finally.

As I suspected, there was an issue in the startup assembly file. The closest supplied startup file with the ST peripheral library was for the Raisonance RIDE toolset. I switched back to the startup file and linker script from an example on Freddie Chopin’s web site for my yagarto/eclipse/openocd setup.

SysTick interrupts now work as expected with just the few CMSIS calls as per the ST examples.

I suspect it had to do with the MSR setup for both main and process stacks, but I’m not sure and I need to move on for now.

Thanks for the help!

Jim