Cortex-M4 vPortEnterCritical() altering BASEPRI register before vTaskStartScheduler()
Posted by
jcwren on March 15, 2019
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()
Posted by
rtel on March 15, 2019
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()
Posted by
jcwren on March 15, 2019
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()
Posted by
richarddamon on March 16, 2019
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.