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

回到顶部