freeRTOS源碼解析4--tasks.c 5

来源:https://www.cnblogs.com/freeManX1807/p/18425725
-Advertisement-
Play Games

想著做個輪腿的機器人玩玩,但是如果光用PID做演算法,對於輪子加腿的結構似乎效果並不好,為了實現輪腿本身能夠飛坡在一定高度下能夠跳躍,我想著上個模擬模型來調試和學習LQR演算法 機器人模擬的軟體似乎挺多,我查到比較常用的有ROS套件的一個,還有就是webots 本著界面簡單,開源(還有校園網方便下載)的 ...


4.2.13 繼續任務--vTaskResume

介面:
void vTaskResume( TaskHandle_t xTaskToResume )
形參1:xTaskToResume ,想要繼續的任務handle;

首先是vTaskResume調用的一個內部函數:static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ),用於檢查任務是否是掛起狀態,只有掛起的任務才能繼續,否則是等待事件、通知等處於阻塞態,那就不能放到就緒列表,必須繼續等待。這個介面邏輯非常簡單,就直接看代碼即可。

 1 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
 2 {
 3     BaseType_t xReturn = pdFALSE;
 4     const TCB_t * const pxTCB = xTask;
 5 
 6     /* Accesses xPendingReadyList so must be called from a critical
 7      * section. */
 8 
 9     /* It does not make sense to check if the calling task is suspended. */
10     configASSERT( xTask );
11 
12     /* Is the task being resumed actually in the suspended list? */
13     /* 檢查任務是否在掛起列表, 不在則說明任務未掛起 */
14     if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
15     {
16         /* Has the task already been resumed from within an ISR? */
17         /* 任務在掛起列表裡, 但在調度器暫停時被移至等待就緒列表中, 則說明任務未掛起 */
18         if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
19         {
20             /* Is it in the suspended list because it is in the Suspended
21              * state, or because it is blocked with no timeout? */
22             /* 任務在掛起列表裡, 但在等待事件, 則說明任務未掛起 */
23             if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
24             {
25                 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
26                 {
27                     BaseType_t x;
28 
29                     /* The task does not appear on the event list item of
30                      * and of the RTOS objects, but could still be in the
31                      * blocked state if it is waiting on its notification
32                      * rather than waiting on an object.  If not, is
33                      * suspended. */
34                     /* 任務在掛起列表裡, 且未等待事件, 那麼如果在等待通知則未掛起, 否則掛起 */
35                     xReturn = pdTRUE;
36 
37                     for( x = ( BaseType_t ) 0; x < ( BaseType_t ) configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
38                     {
39                         if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
40                         {
41                             xReturn = pdFALSE;
42                             break;
43                         }
44                     }
45                 }
46                 #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
47                 {
48                     xReturn = pdTRUE;
49                 }
50                 #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
51             }
52             else
53             {
54                 mtCOVERAGE_TEST_MARKER();
55             }
56         }
57         else
58         {
59             mtCOVERAGE_TEST_MARKER();
60         }
61     }
62     else
63     {
64         mtCOVERAGE_TEST_MARKER();
65     }
66 
67     /* 總結下來就是任務若在掛起列表裡, 如果不是在等待事件或通知, 則是掛起狀態, 否則不是 */
68 
69     return xReturn;
70 }
prvTaskIsTaskSuspended
 1 void vTaskResume( TaskHandle_t xTaskToResume )
 2 {
 3     TCB_t * const pxTCB = xTaskToResume;
 4 
 5     /* It does not make sense to resume the calling task. */
 6     configASSERT( xTaskToResume );
 7 
 8     #if ( configNUMBER_OF_CORES == 1 )
 9         /* The parameter cannot be NULL as it is impossible to resume the
10          * currently executing task. */
11         if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) )
12     #endif
13     {
14         taskENTER_CRITICAL();
15         {
16             if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
17             {
18                 /* The ready list can be accessed even if the scheduler is
19                  * suspended because this is inside a critical section. */
20                 /* 只有任務處於掛起狀態才能繼續 */
21                 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
22                 prvAddTaskToReadyList( pxTCB );
23 
24                 /* This yield may not cause the task just resumed to run,
25                  * but will leave the lists in the correct state for the
26                  * next yield. */
27                 /* 保證各任務列表處於正常的狀態 */
28                 taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB );
29             }
30             else
31             {
32                 mtCOVERAGE_TEST_MARKER();
33             }
34         }
35         taskEXIT_CRITICAL();
36     }
37     else
38     {
39         mtCOVERAGE_TEST_MARKER();
40     }
41 }
vTaskResume

4.2.14 啟動調度--vTaskStartScheduler

 這個介面會創建空閑任務和軟定時器任務,之後就是允許第一個任務,這個介面永遠也不會返回,也是main中調用的最後一個介面。

 1 void vTaskStartScheduler( void )
 2 {
 3     BaseType_t xReturn;
 4 
 5     /* 創建空閑任務 */
 6     xReturn = prvCreateIdleTasks();
 7 
 8     #if ( configUSE_TIMERS == 1 )
 9     {
10         if( xReturn == pdPASS )
11         {
12             xReturn = xTimerCreateTimerTask();    // 創建軟定時器任務
13         }
14         else
15         {
16             mtCOVERAGE_TEST_MARKER();
17         }
18     }
19     #endif /* configUSE_TIMERS */
20 
21     if( xReturn == pdPASS )
22     {
23         /* Interrupts are turned off here, to ensure a tick does not occur
24          * before or during the call to xPortStartScheduler().  The stacks of
25          * the created tasks contain a status word with interrupts switched on
26          * so interrupts will automatically get re-enabled when the first task
27          * starts to run. */
28         /* 關閉中斷, 保證在調用xPortStartScheduler前不會發生tick中斷, 所有創建
29          * 的任務的棧中都包含一個中斷開啟的狀態字, 所以第一個任務運行時, 中斷
30          * 會自動開啟 */
31         /* 暫時沒看懂這個註釋的意思, 但這個介面只是設置了中斷優先順序屏蔽寄存器,
32          * 實際的中斷並未關閉, 系統中斷被屏蔽了 */
33         portDISABLE_INTERRUPTS();
34 
35         xNextTaskUnblockTime = portMAX_DELAY;
36         xSchedulerRunning = pdTRUE;
37         xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
38 
39         /* If configGENERATE_RUN_TIME_STATS is defined then the following
40          * macro must be defined to configure the timer/counter used to generate
41          * the run time counter time base.   NOTE:  If configGENERATE_RUN_TIME_STATS
42          * is set to 0 and the following line fails to build then ensure you do not
43          * have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
44          * FreeRTOSConfig.h file. */
45         portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
46 
47         /* Setting up the timer tick is hardware specific and thus in the
48          * portable interface. */
49 
50         /* The return value for xPortStartScheduler is not required
51          * hence using a void datatype. */
52         /* 真正的啟動調度器, 即啟動了第一個任務 */
53         ( void ) xPortStartScheduler();
54 
55         /* In most cases, xPortStartScheduler() will not return. If it
56          * returns pdTRUE then there was not enough heap memory available
57          * to create either the Idle or the Timer task. If it returned
58          * pdFALSE, then the application called xTaskEndScheduler().
59          * Most ports don't implement xTaskEndScheduler() as there is
60          * nothing to return to. */
61     }
62     else
63     {
64         /* This line will only be reached if the kernel could not be started,
65          * because there was not enough FreeRTOS heap to create the idle task
66          * or the timer task. */
67         configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
68     }
69 
70     /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
71      * meaning xIdleTaskHandles are not used anywhere else. */
72     ( void ) xIdleTaskHandles;
73 
74     /* OpenOCD makes use of uxTopUsedPriority for thread debugging. Prevent uxTopUsedPriority
75      * from getting optimized out as it is no longer used by the kernel. */
76     ( void ) uxTopUsedPriority;
77 }
vTaskStartScheduler

 

4.2.15 停止調度--vTaskEndScheduler

這個介面和上一個相對,而且這個介面一定是在某個任務中調用的,因為系統不會主動停止調度器,而正常運行中始終只有某個任務和系統在運行,所以必然是某個任務主動調用的。

 1 void vTaskEndScheduler( void )
 2 {
 3     #if ( INCLUDE_vTaskDelete == 1 )
 4     {
 5         BaseType_t xCoreID;
 6 
 7         #if ( configUSE_TIMERS == 1 )
 8         {
 9             /* Delete the timer task created by the kernel. */
10             /* 刪除軟定時器任務 */
11             vTaskDelete( xTimerGetTimerDaemonTaskHandle() );
12         }
13         #endif /* #if ( configUSE_TIMERS == 1 ) */
14 
15         /* Delete Idle tasks created by the kernel.*/
16         for( xCoreID = 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
17         {
18             vTaskDelete( xIdleTaskHandles[ xCoreID ] );    // 刪除空閑任務
19         }
20 
21         /* Idle task is responsible for reclaiming the resources of the tasks in
22          * xTasksWaitingTermination list. Since the idle task is now deleted and
23          * no longer going to run, we need to reclaim resources of all the tasks
24          * in the xTasksWaitingTermination list. */
25         /* 本應由空閑任務回收待刪除任務的資源, 但現在空閑任務被刪除了, 就在這裡處理 */
26         prvCheckTasksWaitingTermination();
27     }
28     #endif /* #if ( INCLUDE_vTaskDelete == 1 ) */
29 
30     /* Stop the scheduler interrupts and call the portable scheduler end
31      * routine so the original ISRs can be restored if necessary.  The port
32      * layer must ensure interrupts enable  bit is left in the correct state. */
33     /* 這跟啟動調度器時關中斷一樣的疑問 */
34     portDISABLE_INTERRUPTS();
35     xSchedulerRunning = pdFALSE;
36 
37     /* This function must be called from a task and the application is
38      * responsible for deleting that task after the scheduler is stopped. */
39     vPortEndScheduler();
40 }
vTaskEndScheduler

 

  好了,下一篇講xTaskAbortDelay和xTaskIncrementTick介面,這兩個介面較為複雜。

  下篇再見。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • 徒弟不懂git怎麼用, 於是寫了篇文章, 把本地git操作從頭寫了一遍, 自己去看吧! 0、基本概念 •Git是一個免費、開源的、分散式版本控制系統 •它使用一個特殊的叫做倉庫的資料庫來記錄文件的變化 •倉庫中的每個文件都有一個完整的版本歷史記錄 1)安裝 sudo apt-update sudo ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...