嵌入式学习笔记 - freeRTOS xTaskResumeAll( )函数解析

第一部分 移除挂起等待列表中的任务

while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )//循环寻找直到为空,把全部任务扫描一遍

{

pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );//获取挂起等待列表中的任务的控制块指针

( void ) uxListRemove( &( pxTCB->xEventListItem ) ); //从事件列表中删除

( void ) uxListRemove( &( pxTCB->xStateListItem ) );//从挂起列表中删除

prvAddTaskToReadyList( pxTCB ); //加入就绪列表

/* If the moved task has a priority higher than the current

task then a yield must be performed. */

if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )

{

xYieldPending = pdTRUE; //如果恢复的等待列表中的此任务优先级大于当前任务,使能切换

}

else

{

mtCOVERAGE_TEST_MARKER();

}

}

第二部分 补齐错过的systick计数以及相应的处理

UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */

if( uxPendedCounts > ( UBaseType_t ) 0U )

{

do

{

if( xTaskIncrementTick() != pdFALSE ) //xTaskIncrementTick()函数用于是否有延时到期的任务,并将其恢复到就绪列表,如果其优先级比当前任务高,则同时使能切换标志,注意仅仅是使能标志,未实际切换。并将切换标志返回

{

xYieldPending = pdTRUE; //需要任务切换

}

else

{

mtCOVERAGE_TEST_MARKER();

}

--uxPendedCounts;

} while( uxPendedCounts > ( UBaseType_t ) 0U ); //循环补齐systick计数,才能找到所有到期任务,因为循环一次xConstTickCount只能加一次,加到跟当前TickCount值相同才能找处所有xNextTaskUnblockTime到期的任务

uxPendedTicks = 0;

}

else

{

mtCOVERAGE_TEST_MARKER();

}

第三部分 判断是否需要切换任务

if( xYieldPending != pdFALSE ) //如果xYieldPending为1,在上面两部分得到的值

{

#if( configUSE_PREEMPTION != 0 )

{

xAlreadyYielded = pdTRUE; //感觉逻辑上应该把下一句切换移到这个条件编译里面,如果configUSE_PREEMPTION 定义为 0,就不进行任务切换同时xAlreadyYielded也不赋值为1,就是记录为没切换过,可能是因为这种情况下taskYIELD_IF_USING_PREEMPTION()未定义(如下图所示),默认为taskYIELD_IF_USING_PREEMPTION()不起作用,所以不对xAlreadyYielded进行赋值

另外我的理解configUSE_PREEMPTION 定义为 0时,xYieldPending 不可能等于pdTRUE?因为如果configUSE_PREEMPTION == 0任务不可能在延时列表,也不可能在挂起等待就绪列表,进入挂起等待就绪列表是从延时列表进入的

}

#endif

taskYIELD_IF_USING_PREEMPTION(); // 进行实际的任务切换,这一条很关键,也就是说xTaskResumeAll( )函数是能进行实际的任务切换的,不只是判断是否认该切换,上面有个#if并不是if,很容易理解成此语句不执行

}

else

{

mtCOVERAGE_TEST_MARKER();

}

}

}

else

{

mtCOVERAGE_TEST_MARKER();

}

}

taskEXIT_CRITICAL();

return xAlreadyYielded;// 返回是否切换过的标志,如果未切换过,出去后是一定要切换的,因为将当前任务加到等待插入列表,以及延时列表之后,当前任务要处于阻塞状态,是一定要切换到其他任务的

四 若未发生实际任务切换的处理

以下函数是xTaskResumeAll() 的调用函数,是将消息加入队列的一个函数

if( prvIsQueueFull( pxQueue ) != pdFALSE )
{
traceBLOCKING_ON_QUEUE_SEND( pxQueue );
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );

if( xTaskResumeAll() == pdFALSE ) //如果xTaskResumeAll()内未发生实际切换
{
portYIELD_WITHIN_API(); // 强制进行任务切换,也就是说一定要切换一次
}

相关推荐
知识分享小能手2 分钟前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
汇能感知2 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
阿巴Jun3 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
伴杯猫3 小时前
【ESP32-IDF】基础外设开发2:系统中断矩阵
c语言·单片机·嵌入式硬件·mcu·物联网·github
茯苓gao3 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾3 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT4 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
aaaweiaaaaaa4 小时前
HTML和CSS学习
前端·css·学习·html
ST.J4 小时前
前端笔记2025
前端·javascript·css·vue.js·笔记
Suckerbin4 小时前
LAMPSecurity: CTF5靶场渗透
笔记·安全·web安全·网络安全