STM32WB55 FreeRTOS systick not firing

Hi,

I realise that this might be a ST Micro question. But, then again, it might not…

I’m working with the STM32WB55 Nucleo board (and using STM32CubeIDE) and have just upgraded the SDK to STM32Cube_FW_WB_V1.11.0 from STM32Cube_FW_WB_V1.10.1. Firing up a sample application that uses Bluetooth and FreeRTOS, I see that FreeRTOS is not scheduling.

There is a note in FreeRTOSConfig.h that says:
“…/* IMPORTANT: After 10.3.1 update, Systick_Handler comes from NVIC (if SYS timebase = systick), otherwise from cmsis_os2.c */…”

Checking the vector table and the SysTick interrupt vector at 0x0000 003C correctly points to the SysTick_Handler function in cmsis_o2.c. However, setting a breakpoint in that routine never gets hit.

Checking the SysTick STCSR register - it has a value of 7 which means that the interrupt is enabled.

This suggests that the clock itself isn’t reaching SysTick but I don’t know where to go from here (and whether this a FreeRTOS issue or a ST Micro issue).

Any suggestions and comments are welcome.

Regards,
AC

Hi there,

are your interrupts globally enabled? Which port are you using? In your port’s prvPortStartFirstTask() implementation, there should be an instruction

cpsie i

which would enable interrupts.

Hi,

Thanks for your response.

are your interrupts globally enabled?
Yes. prvPortStartFirstTask does have a cpsie i instruction and the timer tick for HAL via timer 17 is running fine. The port is for M4.

Regards,
ac

ok, I would make a few sanity checks first:

  • set a “hard” bp onto your sys tick handler, eg

asm(" BKPT");

Sometimes optimization and inlining does not give you reliable break points.

  • Also, set a bp at your HAL timer handler (which I assume runs above MAX_SYSCALL prio) and inspect the basepri register when you get there. Maybe you are stuck in a critical section with low pri ints disabled.

set a “hard” bp onto your sys tick handler
Done. The breakpoint is not hit…

Also, set a bp at your HAL timer handler (which I assume runs above MAX_SYSCALL prio)
The HAL timer interrupt is set at priority 0; SysTick is set at priority 15. When the bp in the timer handler is hit, the basepri register has a value of 0.

I didn’t mention this in my earlier message but the symptoms I’m seeing is that a delay in the default task never returns:

void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN 5 */
//osStatus status;
//uint32_t delayTime;

//delayTime = 1000;
  /* Infinite loop */
 for(;;)
 {
 /* status = osDelay(delayTime);
  if ( status != SUCCESS)
  {
	  __asm__("NOP");
  }
  */
  vTaskDelay((TickType_t)1000); <-- Never returns...

  HAL_GPIO_TogglePin(GPIOB, LD1_Pin);
  HAL_GPIO_TogglePin(GPIOB, LD2_Pin);
  HAL_GPIO_TogglePin(GPIOB, LD3_Pin);
  }
  /* USER CODE END 5 */
}

yes, that would be consistent with your assumption that the sys tick handler doesn’t execute. Very likely xTickCount in tasks.c remains at 0 (which is yet another way of stating the same thing). My first point was just to make sure we don’t bark up a wrong tree (Cortex and breakpoints is a very speical issue).

Now as for the second remark: Your HAL timer operates, so interrupts are not completly disabled. Ok. But again, the HAL timer most likely executes above syscall priority but the sys tick by definition runs below that, so there is still a possibility that some code enters but never releases the critical section, which would explain your behavior. Can you check that (eg via basepri as I outlined)?

the HAL timer most likely executes above syscall priority but the sys tick by definition runs below that
It doesn’t look like that is the case. It looks like syscall and HAL timer tick run at the same priority/sub-pri. Here’s the config:
System svc call via SWI instruction: Pre-empt prio 0/Sub-prio 0
System tick: Pre-empt prio 15/Sub-prio 0
Timebase - Timer 17: Pre-empt prio 0/Sub-prio 0

Can you check that (eg via basepri as I outlined)
Sorry, but I don’t quite follow you here. I checked the value of basepri at the instant the bp in the timer callback is hit and it has a value of 0. Is this what you meant or something else?

Ah! My mistake. Svc Call is interrupt vector 11 and SysTick is 15 so Svc Call runs at a higher priority. Those pre-empt prio/sub prio only refer to arbitration within the same priority level (I guess)…

careful please, vector numbers and interrupt priorities are different things on the M4, as I’m sure you know… you want the service call handler to always have lowest priority, but that doesn’t explain your timer not firing problem.

Have you made any modifications to the port? The STM32WB55 has four relevant bits in the interrupt level byte, I’m sure you have configured that accordingly?

No. This is a sample application lifted straight from the SDK. The only mod that I have made is adding the LED flash code so that I could see the task switching working. The same code works fine with the prior version of the SDK.

The priority levels are set in the MX UI - I haven’t modified anything in the generated code. I see from the code that sets up the timer interrupt that the group priority is being set to NVIC_PRIORITYGROUP_4 (so no sub-priority).

When I put a bp in the default task, just prior to calling vTaskDelay(…), I checked the SysTick registers and everything looks fine there: Control reg: clk source is AHB clock (32MHz), interrupt on count-to-zero, enabled; Reload reg: 32000 (so a 1kHz tick)…

Not sure what else to look at…

me neither. You can monitor the SYST_CVR register and check whether that one changes at all…

Yes, it does. It is at 0x6d16 when the bp hit…

I’ll refer this to ST now. Many thanks for your assistance…

Been a pleasure. Please let us know your resolution!

Edit:

https://community.st.com/s/question/0D50X0000B8hnwC/stm32wb55-haldelay-function

It looks like there are some similarities with your issue here…

Seems fishy. I would try telling CubeIDE to use CMSIS-RTOS v1 instead of CMSIS-RTOS v2. Even better if CubeIDE would allow you to drop CMSIS-RTOS altogether, but at least you can use the native FreeRTOS API in all the code you write yourself.

I think I can do that anyway. You don’t have to use the CMSIS interface…

Anyway, I tried that for the delay call and the code gets stuck in vTaskDelay(…) as well as osDelay(…)

ac

Hi Andrew - you should still try having CubeIDE generate code for CMSISv1. It uses a completely different config for the OS tick.

Also you should change the HAL tick source when using CMSISv1. Use something other than SysTick.

image

Hi Jeff,

Many thanks for your comments.

I am using TIM17 for the HAL tick. For the CMSIS interface, CMSIS v1 is greyed out so I can’t select it.

Regards,
ac

Andrew, were you able to get some assistance from ST on firing the timer interrupt?

Not yet, I’m afraid… Still waiting…