STM32 TIM capture interrupt halts task switch

guildernstern wrote on Thursday, January 10, 2013:

Hello all and thank you to whoever reads this.

I’m experiencing a problem with FreeRTOS port for STM32, here’s the background:

- STM32F100RB on custom hardware
- Keil compiler
- FreeRTOS V 6.1.1
- Standard FreeRTOS provided demos execute correctly on hardware
- application uses start up code from startup_stm32f10x_md_vl.s
- system task size is configured to 0x200 in startup_stm32f10x_md_vl.s
- application uses heap_1.c
- heap size is configured to 3 K bytes in FreeRTOSConfig.h
- application has 4 tasks:
  Task_A, priority 3, 64 bytes stack
  Task_d, priority 3, 32 bytes stack
  Task_N, priority 2, 128 bytes stack
  Task_T, priority 2, 64 bytes stack
- application has 4 interrupts:
  system tick (FreeRTOS sys tick handler)
  TIMER 2 (same for both capture and overflow)
  UART 1
  UART 2
- interrupt priorities:
  #define configKERNEL_INTERRUPT_PRIORITY         255
- priority group:
- all interrupts have been configured as:
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- timer 2 is configured to trigger an interrupt on input capture events and counter overflows.
  timer 2 is used to measure duration of pulses on input signal
- UART 1 is used to communicate with a radiomodem @ 57600 bps
- UART 2 is used to communicate with a GPS @ 4800 bps
- I2C is used to read data from MEMS sensors (no interrupt)

The problem:

Task switch halts when the frequency of the input capture signal is high (100 KHz ?).


- Hard fault handler is not called
- Enabling configCHECK_FOR_STACK_OVERFLOW to 1 or 2 doesn’t catch any stack overflow
- When halting the debugger, the code is always in the I2C routines.
  The code gets stuck in while (!I2C_CheckEvent()). This looks very similar to the problem mentioned here:
  The I2C routines have been tested without FreeRTOS and work well.
- The system tick interrupt keeps working, xPortSysTickHandler is called.
- The running task is always the same, i.e. Task_A.
- The input capture interrupt does not nest.
  This was tested with a global variable increased / decreased at every interrupt entry / exit.
- Nothing changes clearing the interrupt flags at the beginning or at the end of the interrupt routine.
- Nothing changes adding some instructions to read the interrupt register before extiting interrupt
  (suspected issue with pipeline races exiting the interrupt).


Anybody has an idea what I could try ?

Thank you.

rtel wrote on Sunday, January 13, 2013:

Thanks for providing such good information.  My apologies for not replying earlier, this one somehow passed me by.

From your information I understand that your application is executing correctly until the frequency of the input capture interrupt increases to somewhere around 100 KHz.

Can you provide more information what the capture interrupt is doing?  You say it measures the width of pulses, is that quick to do or does it require a long calculate?  What does it do with the measurement once it has calculated it?  Does it use any FreeRTOS API functions?

Do you have any way of measuring how much CPU time is taken servicing the interrupt?

When you stop the debugger and find the I2C code is running, is it always the same line that is executing (is is stuck in a polling loop, or is it apparently running normally)?