freeRTOS 挂起、恢复任务

任务挂起:

它把所有挂起的任务加到 xSuspendedTaskList 中,

而且一旦调用 vTaskSuspend() 函数挂起一个任务,该任务就将从所有它原先连入的链表中删除(包括就绪表,延时表和它等待的事件链表【两类列表都要清掉】),

也就是说,一旦一个任务被挂起,它将取消先前它的延时和对事件的等待。

 

相反的唤醒就是把任务从xSuspendedTaskList中删除,加到对应的就绪链表中(根据任务的优先级),然后如果唤醒的任务优先级高于当前任务优先级,则调度。

 1     void vTaskSuspend( TaskHandle_t xTaskToSuspend )
 2     {
 3     TCB_t *pxTCB;
 4 
 5         taskENTER_CRITICAL();
 6         {
 7             /* If null is passed in here then it is the running task that is
 8             being suspended. */  如果为空,说明是挂起自己。
 9             pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
10 
11             traceTASK_SUSPEND( pxTCB );
12 
13             /* Remove task from the ready/delayed list and place in the
14             suspended list. */
15             if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )  从ready/delay列表中删除,返回列表中item个数
16             {
17                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );  更新最高优先级变量“TopReadyPrior” ##1
18             }
19             else
20             {
21                 mtCOVERAGE_TEST_MARKER();
22             }
23 
24             /* Is the task waiting on an event also? */
25             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )  container是某个信号量 或 事件队列的WaitToSend列表或WaitToRcv列表。
26             {
27                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );  看后边图。
28             }
29             else
30             {
31                 mtCOVERAGE_TEST_MARKER();
32             }
33 
34             vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );  将任务状态项,加入到挂起列表中。
35         }
36         taskEXIT_CRITICAL();
37 
38         if( xSchedulerRunning != pdFALSE )
39         {
40             /* Reset the next expected unblock time in case it referred to the
41             task that is now in the Suspended state. */
42             taskENTER_CRITICAL();
43             {
44                 prvResetNextTaskUnblockTime();  这个和删除任务的时候一样,见删除任务章节中的##5
45             }
46             taskEXIT_CRITICAL();
47         }
48         else
49         {
50             mtCOVERAGE_TEST_MARKER();
51         }
52 
53         if( pxTCB == pxCurrentTCB )
54         {
55             if( xSchedulerRunning != pdFALSE )
56             {
57                 /* The current task has just been suspended. */
58                 configASSERT( uxSchedulerSuspended == 0 );
59                 portYIELD_WITHIN_API();  调度器在运行时,如果这个挂起的任务是当前任务,立即切换任务。
60             }
61             else
62             {
63                 /* The scheduler is not running, but the task that was pointed
64                 to by pxCurrentTCB has just been suspended and pxCurrentTCB
65                 must be adjusted to point to a different task. */
66                 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )  ##见后,原子资料
67                 {
68                     /* No other tasks are ready, so set pxCurrentTCB back to
69                     NULL so when the next task is created pxCurrentTCB will
70                     be set to point to it no matter what its relative priority
71                     is. */
72                     pxCurrentTCB = NULL;  如果所有的任务都被挂起了,则CurrentTCB只能指向NULL,等待新的任务创建再指向这个新的任务。
73                 }
74                 else
75                 {
76                     vTaskSwitchContext();  有其他任务,则切换到其他任务。在这个章节:任务切换,搜TaskSwitchContex
77                 }
78             }
79         }
80         else
81         {
82             mtCOVERAGE_TEST_MARKER();
83         }
84     }

 

 

 

##  原子资料:

(7)、 pxCurrentTCB 指向正在运行的任务,但是正在运行的任务要挂起了,所以必须给pxCurrentTCB 重新找一个“对象”。

也就是查找下一个将要运行的任务,本来这个工作是由任务切换函数来完成的,但是程序运行到这一行说明任务调度器被挂起了

任务切换函数也无能为力了,必须手动查找下一个要运行的任务

调用函数 listCURRENT_LIST_LENGTH()判断一下系统中所有的任务是不是都被挂起了,

也就是查看列表 xSuspendedTaskList 的长度是不是等于 uxCurrentNumberOfTasks

如果等于的话就说明系统中所有的任务都被挂起了(实际上不存在这种情况,因为最少有一个空闲任务是可以运行的,

空闲任务执行期间不会调用任何可以阻塞或者挂起空闲任务的 API 函数,为的就是保证系统中永远都有一个可运行的任务)

 

 ##1   taskRESET_READY_PRIORITY( pxTCB->uxPriority ); 

删除任务”分析里面,也会调用这个API,目的是维护一个变量,

这个变量的功能:

1. 在使用通用方法找到最高优先级任务时,它用来记录最高优先级任务的优先级。

2. 在使用硬件方法找到最高优先级任务时,它的每一位(共32bit)的状态代表这个优先级上边,有没有就绪的任务。

找到最高优先级任务的方法,见“任务切换”一节。

 

 

 

================================================================

任务恢复函数有两个 vTaskResume() 和 xTaskResumeFromISR() 。

但基本原理是差不多的。

 1 void vTaskResume( TaskHandle_t xTaskToResume )
 2 {
 3 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
 4 
 5     /* It does not make sense to resume the calling task. */
 6     configASSERT( xTaskToResume );
 7 
 8     /* The parameter cannot be NULL as it is impossible to resume the
 9     currently executing task. */
10     if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )  肯定不是空,而且不会是当前任务..
11     {
12         taskENTER_CRITICAL();
13         {
14             if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )  这个任务是被挂起的
15             {
16                 traceTASK_RESUME( pxTCB );
17 
18                 /* As we are in a critical section we can access the ready
19                 lists even if the scheduler is suspended. */
20                 ( void ) uxListRemove(  &( pxTCB->xStateListItem ) );  将要恢复的任务从列表中删除(列表是哪个呢? 可以从Item得到它的Container!!!21                 prvAddTaskToReadyList( pxTCB );                       加入到就绪列表
22 
23                 /* We may have just resumed a higher priority task. */
24                 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
25                 {
26                     /* This yield may not cause the task just resumed to run,
27                     but will leave the lists in the correct state for the
28                     next yield. */
29                     taskYIELD_IF_USING_PREEMPTION();  刚好加入就绪的任务优先级高的话,立即切换任务。
30                 }
31                 else
32                 {
33                     mtCOVERAGE_TEST_MARKER();
34                 }
35             }
36             else
37             {
38                 mtCOVERAGE_TEST_MARKER();
39             }
40         }
41         taskEXIT_CRITICAL();
42     }
43     else
44     {
45         mtCOVERAGE_TEST_MARKER();
46     }
47 }

 

 

 

 

 

留白

posted @ 2017-11-17 20:25  为民除害  阅读(5574)  评论(0编辑  收藏  举报