If there is a lot of code in the critical section, a long execution time will cause a delay interrupt. If the interrupt is not responded to in this way, it does not conform to the real-time operating system.
use case
void vTaskDelay( const TickType_t xTicksToDelay )
{
BaseType_t xAlreadyYielded = pdFALSE;
/* A delay time of zero just forces a reschedule. */
if( xTicksToDelay > ( TickType_t ) 0U )
{
configASSERT( uxSchedulerSuspended == 0 );
vTaskSuspendAll();
{
traceTASK_DELAY();
/* A task that is removed from the event list while the
scheduler is suspended will not get placed in the ready
list or removed from the blocked list until the scheduler
is resumed.
This task cannot be in an event list as it is the currently
executing task. */
prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
}
xAlreadyYielded = xTaskResumeAll();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Force a reschedule if xTaskResumeAll has not already done so, we may
have put ourselves to sleep. */
if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
Let's explain the specific underlying implementation of these two API functions
We know that the system performs task switching through the pendsv interrupt, so how is this variable connected to this interrupt?
in delay.c
In the M3 Definitive Guide
portNVIC_INT_CTRL_REG
is defined as a pointer to a register address. By assigning portNVIC_PENDSVSET_BIT
the value of (an integer) to this pointer, the value of the register is actually set to portNVIC_PENDSVSET_BIT
the bit pattern represented by .
back to delay.c
go to go in
Then
At this time, it is equivalent to the task scheduler being suspended, which is also a nested function
There is also a function to suspend the task scheduler. There are too many screenshots to take. You should be able to watch the video after reading the above.
Equal to 0 here means that the variable uxSchedulerSupended is equal to 0