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 }

 

 

 

 

 

留白


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM