Hi everyone,
I am currently learning FreeRTOS on ARM Cortex-M. I have a question about the interrupt mask in the Pendable Service interrupt handler.
I understand that the Pendable Service interrupt handler is used by the RTOS to perform a context switch. To protect the critical section used for the context switch, the code in xPortPendSVHandler() function disables interrupts whose priority levels are below “configMAX_SYSCALL_INTERRUPT_PRIORITY”. The code of Pendable Service interrupt handler for Cortex-M3/M4/M7 is shown below:
void xPortPendSVHandler( void )
{
/* This is a naked function. */
__asm volatile
(
" mrs r0, psp \n"
" isb \n"
" \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
" it eq \n"
" vstmdbeq r0!, {s16-s31} \n"
" \n"
" stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
" stmdb sp!, {r0, r3} \n"
" mov r0, %0 \n"
" msr basepri, r0 \n"
" dsb \n"
" isb \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" ldmia sp!, {r0, r3} \n"
" \n"
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldr r0, [r1] \n"
" \n"
" ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */
" \n"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */
" it eq \n"
" vldmiaeq r0!, {s16-s31} \n"
" \n"
" msr psp, r0 \n"
" isb \n"
" \n"
" \n"
" bx r14 \n"
" \n"
" .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
);
}
As shown, before the vTaskSwitchContext() function called, the BASEPRI is set to mask the interrupt priority to disable interrupts whose priority levels are below the “configMAX_SYSCALL_INTERRUPT_PRIORITY”. Then, the BASEPRI is cleared to enable interrupts when the switch context task is finished. The lines that perform this job are:
" mov r0, %0 \n"
" msr basepri, r0 \n"
" dsb \n"
" isb \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
My questions are:
(1) Why the BSEPRI is not set to disable interrupts at the beginning of the xPortPendSVHandler() function, and why the BASEPRI is not cleared to enable interrupts at the end of the xPortPendSVHandler() function?
(2) Does it mean that the code sections before setting BASEPRI and after clearing BASEPRI don’t need to be protected? Why?
(3) What do the code sections before setting BASEPRI and after clearing BASEPRI do?
Thanks.
Liu