FreeRTOS学习记录
(一)任务删除函数详解
直接上代码!
void vTaskDelete( TaskHandle_t xTaskToDelete ){TCB_t
*pxTCB;taskENTER_CRITICAL();
{
/* 获取要删除任务的任务控制块,参数是任务句柄,如果参数为当前正在执行的任务句柄,那么返回值为null */pxTCB
= prvGetTCBFromHandle( xTaskToDelete );/* 将任务从就绪列表中删除 */if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ){
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
}
else{
mtCOVERAGE_TEST_MARKER();
}
/* 查看任务是否在等待某个事件信号量,队列等,并将其从相应的列中删除 */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ){
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
}
else{
mtCOVERAGE_TEST_MARKER();
}
uxTaskNumber++;
/* 如果要删除的是当前正在运行的任务 */
if( pxTCB == pxCurrentTCB ){
/* 把任务添加到等待删除的任务列表中,并在空闲任务中删除 */
vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
/* 记录有多少个任务需要释放内存 */
++uxDeletedTasksWaitingCleanUp;
/* 任务删除钩子函数---需要用户自己实现*/
portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
}
else{
/* 要删除的是别的任务 */
--uxCurrentNumberOfTasks;
prvDeleteTCB( pxTCB );
/* 重新计算还要多长时间执行下一个任务 */
prvResetNextTaskUnblockTime();
}
traceTASK_DELETE( pxTCB );
}
/* 退出临界段 */
taskEXIT_CRITICAL();
/* 如果任务调度器开启 */
if( xSchedulerRunning != pdFALSE ){
/* 如果是删除任务本身,马上进行任务调度)*/
if( pxTCB == pxCurrentTCB ){
configASSERT( uxSchedulerSuspended == 0 );
portYIELD_WITHIN_API();
}
else{
mtCOVERAGE_TEST_MARKER();
}
}
}
具体的结构框图如下所示:
(二)任务挂起函数详解
直接上代码!
void vTaskSuspend(TaskHandle_t xTaskToSuspend){TCB_t
*pxTCB;taskENTER_CRITICAL();
{
/* 获取任务控制块,若为NULL则挂起自身 */pxTCB
= prvGetTCBFromHandle(xTaskToSuspend);/* 将任务从就绪列表、阻塞列表等中移除 */if(uxListRemove(&(pxTCB->xStateListItem)) == (UBaseType_t)0){
taskRESET_READY_PRIORITY(pxTCB->uxPriority);
}
else{
mtCOVERAGE_TEST_MARKER();
}
/* 查看任务是否在等待某个事件,如是则将其从事件列表中移除 */
if(listLIST_ITEM_CONTAINER(&(pxTCB->xEventListItem))!=NULL){
(void) uxListRemove(&(pxTCB->xEventListItem));
}
else{
mtCOVERAGE_TEST_MARKER();
}
/* 将任务添加到挂起任务列表表尾 */
vListInsertEnd(&xSuspendedTaskList, &(pxTCB->xStateListItem));
}
taskEXIT_CRITICAL();
if(xSchedulerRunning != pdFALSE){ //如果任务调度器开启
/* 重新计算还要多长时间执行下一个任务 */
taskENTER_CRITICAL();
{
prvResetNextTaskUnblockTime();
}
taskEXIT_CRITICAL();
}
else{
mtCOVERAGE_TEST_MARKER();
}
if(pxTCB == pxCurrentTCB){
if(xSchedulerRunning != pdFALSE){
/* 若刚挂起的是正在运行的任务,且任务调度器运行正常,则强制进行一次任务切换 */
configASSERT( uxSchedulerSuspended == 0 );
portYIELD_WITHIN_API();
}
else{
/* 若任务调度器没有开启,则读取当前任务挂起列表的长度,判断所有任务是否都被挂起*/
if(listCURRENT_LIST_LENGTH(&xSuspendedTaskList) == uxCurrentNumberOfTasks){
/* 若所有任务都被挂起,把当前的任务控制块赋值为NULL */
pxCurrentTCB = NULL;
}
else{
/* 若还有没被挂起的任务,则获取下一个要运行的任务 */
vTaskSwitchContext();
}
}
}
else{
mtCOVERAGE_TEST_MARKER();
}
}
可见任务挂起和任务删除函数有许多共同之处。
结构图如下,仔细分析哦
(三)任务恢复函数详解
直接上代码!
void vTaskResume(TaskHandle_t xTaskToResume){/* 获取要恢复的任务控制块 */TCB_t
* const pxTCB = (TCB_t *) xTaskToResume;configASSERT( xTaskToResume );
/* 任务控制块不能为NULL和当前任务 */if(( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB )){
taskENTER_CRITICAL();
{
/* 判断要恢复的任务是否已经被挂起 */
if(prvTaskIsTaskSuspended(pxTCB) != pdFALSE){
/* 从挂起列表中移除 */
(void) uxListRemove(&( pxTCB->xStateListItem));
/* 添加到就绪列表中 */
prvAddTaskToReadyList( pxTCB );
/* 要恢复的任务优先级高于当前正在运行的任务优先级 */
if(pxTCB->uxPriority >= pxCurrentTCB->uxPriority){
/* 完成一次任务切换 */
taskYIELD_IF_USING_PREEMPTION();
}
else{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
}
else{
mtCOVERAGE_TEST_MARKER();
}
}
首先要保证要恢复的任务不能是空并且不能是当前正在运行的任务,不然不需要恢复了,然后看下面的结构图,比对着代码就行了。
好!本章就先介绍到这里,下章介绍任务切换!
以上是 FreeRTOS学习记录 的全部内容, 来源链接: utcz.com/z/520321.html