Cortex-M4 vPortEnterCritical() altering BASEPRI register before vTaskStartScheduler()

In our design, before vTaskStartScheduler() is called, the system needs to use the systick interrupt for delays and timeouts. During the process of initialization, xQueueCreateStatic() is called, which ultimately calls xQueueGenericReset(). xQueueGenericReset() wraps it’s code block in a taskENTER_CRITICAL()/taskEXIT_CRITICAL() pair, the former of which ultimately calls vPortEnterCritical(). vPortEnterCritical() calls portDISABLE_INTERRUPTS(), who in turn calls vPortRaiseBASEPRI(), which sets PRIMASK to 0x50 (derived from configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY). The STM32 HAL library runs the systick interrupt at priority 15, so the systick interrupt is no longer generating interrupts. This will occur for any FreeRTOS call that uses taskENTER_CRITICAL(). Unless I am mistaken in that it’s “legal” to call functions like xQueueCreateStatic() and such before calling vTaskStartScheduler(), it seems that portDISABLE_INTERRUPTS() should include a check to see if the scheduler has been started yet, and if not, then not modify the BASEPRI register (or use __interrupt_disable()). The same would be true for portENABLE_INTERRUPTS()

Cortex-M4 vPortEnterCritical() altering BASEPRI register before vTaskStartScheduler()

Interrupts remain masked between any (or at least most) calls to FreeRTOS API functions and the scheduler being started. That behavior was introduced many years ago in response to a very common cause of support requests that resulted from interrupts trying to use kernel features before the kernel was changed. I don’t think we would be willing to check if the scheduler has been started or not on every call as that would have a negative impact on run time performance as the check would be made very frequently. However you can change this behavior by changing the line: static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; in port.c to static UBaseType_t uxCriticalNesting = 0x00;

Cortex-M4 vPortEnterCritical() altering BASEPRI register before vTaskStartScheduler()

I’m unclear how that should help. It looks like it will just skip throwing an configASSERT() until after xPortStartScheduler() has been called. It’s still going to change the BASEPRI value.

Cortex-M4 vPortEnterCritical() altering BASEPRI register before vTaskStartScheduler()

Did you try it?

Cortex-M4 vPortEnterCritical() altering BASEPRI register before vTaskStartScheduler()

One alternative is to configure the HAL to use a Timer Peripheral for its clock, and you can even give it a priority above configLIBRARYMAXSYSCALLINTERRUPTPRIORITY so that FreeRTOS will not disable it.