Compared with CM4 porting layer, I found in the function vPortSVCHandler() will set the basepri to zero before schedule to the 1st tarsk:
but why don’t need to do the same operation on cm33 porting layer
is there any one who knows the reason?
Compared with CM4 porting layer, I found in the function vPortSVCHandler() will set the basepri to zero before schedule to the 1st tarsk:
is there any one who knows the reason?
Thank you for pointing it out. This is a miss and we will fix it.
thanks for your quickly response,
I have a question about the affect of this coding defect on CM33 porting layer. In my view, if the basepri is not cleared in the 1st task scheduling, it will cause the scheduler cannot run normally to schedule other tasks, because on CM33, the scheduling is triggered by pendsv handler, which priority is lowest, and if the basepri is not zero, the pendsv handler cannot be issued, and also the task is cannot be switched… So it is really a serious bug… is there any thing wrong about my idea?
Yes I agree. The first task will start with BasePRI set, which will mask the tick interrupt. This has probably gone unnoticed because the first task to start is always the highest priority task, and as it is the highest priority task it must block if any other task is to run. When the task blocks, or calls any other FreeRTOS API function for that matter, BasePRI will get set to its intended value of 0. There would not be a context switch if the tick interrupt executed while the highest priority task was running, because the highest priority task is already running (other than a time slice to another at the same priority) - so any ticks occurring between the first task starting to run and that task calling an API function would remain pending until the API function executed (with a risk of missing a tick if a task went the whole time slice without calling any API functions).
Hi, Richard
When the task blocks, or calls any other FreeRTOS API function for that matter, BasePRI will get set to its intended value of 0.
–>OK, I think I got your point, in FreeRTOS API, the critical section use the taskENTER_CRITICAL and() and taskEXIT_CRITICAL(), the implementation is :
taskENTER_CRITICAL
|portENTER_CRITICAL
| vPortEnterCritical
|_ portDISABLE_INTERRUPTS
|_ ulCriticalNesting++
taskEXIT_CRITICAL
|_ portEXIT_CRITICAL
|_ vPortExitCritical
|_ uxCriticalNesting–
|_ portENABLE_INTERRUPTS if (uxCriticalNesting==0) => the basepri will be set to 0 at here
and also I know why it will crash in our porting, that’s because we add some error check code in taskENTER_CRITICAL, to do not permit to call FreeROS api when the basepri is not 0, which may cause system hang because the pendsv cannot be issued.
the code like this:
taskENTER_CRITICAL
|portENTER_CRITICAL
| vPortEnterCritical
|_ configASSERT(uxCriticalNesting || !get_BASEPRI()); => our porting
| portDISABLE_INTERRUPTS
| ulCriticalNesting++
so if the basepri is not cleared in the 1st task scheduling, the system will assert fail in our porting code.
I have no questions now, really thanks a lot for you and your team quickly response.
This has been fixed in the following PR: https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/214
Thank you again for bringing it to our attention.
-Gaurav