xPortStartScheduler fails because BASEPRI is non-zero

Trying to run FreeRTOS on ESP32 ARM Cortex M4F, but it fails inside xPortStartScheduler.

static void prvPortStartFirstTask( void )
{
/* Start the first task.  This also clears the bit that indicates the FPU is
 * in use in case the FPU was used before the scheduler was started - which
 * would otherwise result in the unnecessary leaving of space in the SVC stack
 * for lazy saving of FPU registers. */
__asm volatile (
    " ldr r0, =0xE000ED08   \n"/* Use the NVIC offset register to locate the stack. */
    " ldr r0, [r0]          \n"
    " ldr r0, [r0]          \n"
    " msr msp, r0           \n"/* Set the msp back to the start of the stack. */
    " mov r0, #0            \n"
    " msr control, r0       \n"
    " cpsie i               \n"/* Globally enable interrupts. */
    " cpsie f               \n"
    " dsb                   \n"
    " isb                   \n"
    " svc 0                 \n"/* System call to start first task. */
    " nop                   \n"
    " .ltorg                \n"
    );
    }

The call to “svc 0” will fail because the BASEPRI is not zero.

When calling xTaskCreate() BASEPRI is set to configMAX_SYSCALL_INTERRUPT_PRIORITY and this is done before starting the scheduler. Should be ok.

I tried manually setting BASEPRI to 0 and this seems to fix the issue, but I have been using FreeRTOS in the past, and never had to do this “fix”. Also found solutions that proposed changing

static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;

to zero. But again this seems wrong, somehow.

So to sum up:

Init_stuff..
xTaskCreate(..);  // Sets BASEPRI = 0xA0 (configMAX_SYSCALL_INTERRUPT_PRIORITY)
vTaskStartScheduler();
-> xPortStartScheduler(...)
   -> prvPortStartFirstTask() // svc 0 fails because BASEPRI=0xA0

I’m guessing there is something important that I’m missing, where is BASEPRI suppose to be cleared ?

Hi Jakob,

The SVC exception should have highest priority, zero. That setting is found in register SHPR2, at address 0xE000ED1C, in the SCB. The most-significant byte of that 32-bit register sets the priority for SVC. What value is in that register in your system?

Hi Jeff,

Ahh, you where right.
The priority of the SVC exception is 0xA0, which is equal to configMAX_SYSCALL_INTERRUPT_PRIORITY.
Also noted that the priority of PendSV and SysTick is also 0xA0.

So SVC exception, should be set to zero. ?
What about the PendSV and SysTick ?

Can see that PendSV and SysTick are correct.
After looking into the code, I could see that the SVC prio was set in the system init modules, not related to freertos.
After setting the SVC to zero everything works.
Thank you.

Thank you for taking time to report back.

Note that PendSV should be set to the lowest priority (0xFF, or at least all implemented bits set to 1). Otherwise subtle errors can occur when PendSV preempts another ISR.

The CM4 port configures the PendSV priority according to configKERNEL_INTERRUPT_PRIORITY.