二:利用宏实现任务切换 portYIELD_WITHIN_API();
#define portYIELD_WITHIN_API portYIELD
#defineportYIELD() vPortYieldFromISR()
利用PendSV异常实现任务切换
void vPortYieldFromISR( void )
{
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
}
出现portYIELD_WITHIN_API的地方有以下几处:
2.1:任务创建,如果创建的任务优先级比正在运行的高,进行切换
if( xSchedulerRunning != pdFALSE )
{
if(pxCurrentTCB->uxPriority < uxPriority)
{
portYIELD_WITHIN_API();
}
}
2.2:任务删除(删除自己)
if( xSchedulerRunning !=pdFALSE )
{
if( ( void *) pxTaskToDelete == NULL )
{
portYIELD_WITHIN_API();
}
}
2.3:任务延时vTaskDelayUntil vTaskDelay
如果延时时间没有到,强迫切换
if( !xAlreadyYielded )
{
portYIELD_WITHIN_API();
}
2.4:任务优先级设置vTaskPrioritySet
2.4.1:
The priority of another task is being raised,
其他某个任务优先级变高.
xYieldRequired= pdTRUE;标志变量。
2.4.2: 设置自己的优先级变低。
xYieldRequired= pdTRUE; 标志变量
判断标志变量的数值:
if( xYieldRequired == pdTRUE )
{
portYIELD_WITHIN_API();
}
2.5:任务挂起 vTaskSuspend 只能挂起自己
if( pxTaskToSuspend == pxCurrentTCB )
{
pxTaskToSuspend= NULL;
}
if( ( void * ) pxTaskToSuspend== NULL )
{
portYIELD_WITHIN_API();
}
2.6:任务唤醒 只能唤醒其他任务 vTaskResume
if(pxTCB->uxPriority >=pxCurrentTCB->uxPriority )
{
portYIELD_WITHIN_API();
}
2.7:xTaskResumeAll
while(( pxTCB = ( tskTCB * )listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * )&xPendingReadyList ) ) ) != NULL )
{
vListRemove(&( pxTCB->xEventListItem ) );
vListRemove(&( pxTCB->xGenericListItem ));
prvAddTaskToReadyQueue(pxTCB );
if(pxTCB->uxPriority >=pxCurrentTCB->uxPriority )
{
xYieldRequired= pdTRUE;
}
}
if(uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
{
while(uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
{
vTaskIncrementTick();
--uxMissedTicks;
}
#ifconfigUSE_PREEMPTION == 1
{
xYieldRequired= pdTRUE;
}
#endif
}
if(( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) )
{
xAlreadyYielded= pdTRUE;
xMissedYield= pdFALSE;
portYIELD_WITHIN_API();
}
}
} |