C++ class initialisation lockup

terrybarnaby wrote on Tuesday, May 27, 2014:

We are using an in house C++ class library that sits on top of FreeRTOS for use on the STM32F4 platform (Tasks, IO devices etc). This works well, but there is an issue if you try and use something like pvPortMalloc() before the FreeRTOS scheduler is started (probably from a object creation constructor (creating semaphores etc etc)).
Code like this eventually calls: vPortEnterCritical() then vPortExitCritical(). The GCC/ARM_CM4F port uses a variable uxCriticalNesting to determine if interrupts should be re-enabled in vPortExitCritical(). However before the scheduler is started uxCriticalNesting is set to 0xaaaaaaaa. Thus when the C++ initialises things before the scheduler is started, interrupts end up by being disabled. Unfortunately we are using interrupts at that time for certain functionality (debugging printf’s through USB for example).
Now we can set uxCriticalNesting to 0 in port.c and this works, but are there implications of doing this and generally in calling FreeRTOS functions (apart from the obvious ones !) before the scheduler is started ?

rtel wrote on Tuesday, May 27, 2014:

What you are seeing is intentional and not related to C++. You will have the same effect calling any FreeRTOS API functions that use critical sections, not just pvPortMalloc().

A context switch cannot be performed prior to the scheduler being started. Interrupts are intentionally left disabled (in fact, just masked in this case) during the initialisation phase to ensure any interrupts that use the FreeRTOS API that are pre-installed or installed during the initialisation phase cannot execute while the scheduler is in an inconsistent state. Interrupts are enabled again automatically when the first task starts to run.

On STM32 platforms interrupts are not actually globally disabled, only masked upto configMAX_SYSCALL_INTERRUPT_PRIORITY, so if you set your UART interrupt to a priority above that (which means a lower numeric value on Cortex-M parts) then the interrupt will remain enabled - however the interrupt must not attempt to use the FreeRTOS API and its priority must be lowered again to be equal to or below configMAX_SYSCALL_INTERRUPT_PRIORITY if it is going to use the FreeRTOS API after the scheduler has been started.


terrybarnaby wrote on Tuesday, May 27, 2014:

Many thanks for the reply.
That makes sense, shame I have to change interrupt priorities during the initialisation phase, but I can see the sense of this to save odd issues in some usage cases. Cheers.

dumarjo wrote on Tuesday, May 27, 2014:


One thing that we have done here to protect against the malloc, is we test how many task exist. If at least 1 task exist, we presume that the sheduler is started. This don’t prevent the problem with the interrupt, but At least this correct the problem of global object creation.


rtel wrote on Tuesday, May 27, 2014:

This might be helpful as an alternative to checking the number of tasks:

Richard Barry.