(學習日記)2024.03.02:UCOSIII第四節:創建任務

寫在前面:
由于時間的不足與學習的碎片化,寫博客變得有些奢侈。
但是對于記錄學習(忘了以后能快速復習)的渴望一天天變得強烈。
既然如此
不如以天為單位,以時間為順序,僅僅將博客當做一個知識學習的目錄,記錄筆者認為最通俗、最有幫助的資料,并盡量總結幾句話指明本質,以便于日后搜索起來更加容易。


標題的結構如下:“類型”:“知識點”——“簡短的解釋”
部分內容由于保密協議無法上傳。


點擊此處進入學習日記的總目錄

2024.03.02

  • 九、UCOSIII:創建任務
    • 1、任務的定義
    • 2、定義任務棧
    • 3、定義任務函數
    • 4、定義任務控制塊TCB
    • 5、任務創建函數
    • 6、任務棧初始化函數
    • 7、將任務添加到就緒列表
    • 8、全局變量的聲明方法

九、UCOSIII:創建任務

1、任務的定義

在裸機系統中,系統的主體就是main函數里面順序執行的無限循環,這個無限循環里面CPU按照順序完成各種事情。
在多任務系統中,我們根據功能的不同,把整個系統分割成一個個獨立的且無法返回的函數,這個函數我們稱為任務。

void task_entry (void *parg)
{/* 任務主體,無限循環且不能返回 */for (;;){/* 任務主體代碼 */}
}

2、定義任務棧

在這里插入圖片描述

/*
************************************************************************************************************************
*                                                  TCB & STACK & 任務聲明
************************************************************************************************************************
*/
#define  TASK1_STK_SIZE       20
#define  TASK2_STK_SIZE       20static   CPU_STK   Task1Stk[TASK1_STK_SIZE];
static   CPU_STK   Task2Stk[TASK2_STK_SIZE];static   OS_TCB    Task1TCB;
static   OS_TCB    Task2TCB;void     Task1( void *p_arg );
void     Task2( void *p_arg );

在多任務系統中,有多少個任務就需要定義多少個任務棧。

任務棧的大小由宏定義控制,在μC/OS-III中, 空閑任務的棧最小應該大于128,那么我們這里的任務的棧也暫且配置為128。
(但是代碼里任務棧數量為20)

任務棧其實就是一個預先定義好的全局數據,數據類型為CPU_STK。
在μC/OS-III中,凡是涉及數據類型的地方, μC/OS-II都會將標準的C數據類型用typedef重新取一個類型名,命名方式則采用見名之義的方式命名且統統大寫。

3、定義任務函數

任務是一個獨立的函數,函數主體無限循環且不能返回。
任務的代碼示意如下:

/* flag 必須定義成全局變量才能添加到邏輯分析儀里面觀察波形
** 在邏輯分析儀中要設置以 bit 的模式才能看到波形,不能用默認的模擬量
*/
uint32_t flag1;
uint32_t flag2;/* 任務1 */
void Task1( void *p_arg )(2)
{
for ( ;; ) {flag1 = 1;delay( 100 );flag1 = 0;delay( 100 );}//任務是一個獨立的、無限循環且不能返回的函數。
}/* 任務2 */
void Task2( void *p_arg )(3)
{
for ( ;; ) {flag2 = 1;delay( 100 );flag2 = 0;delay( 100 );}
}

4、定義任務控制塊TCB

在這里插入圖片描述

/*
************************************************************************************************************************
************************************************************************************************************************
*                                                  數據類型
************************************************************************************************************************
************************************************************************************************************************
*/typedef  struct  os_rdy_list         OS_RDY_LIST;
typedef  void                        (*OS_TASK_PTR)(void *p_arg);
typedef  struct  os_tcb              OS_TCB;
/*
------------------------------------------------------------------------------------------------------------------------
*                                                   就緒列表
------------------------------------------------------------------------------------------------------------------------
*/
struct os_rdy_list
{OS_TCB        *HeadPtr;OS_TCB        *TailPtr;
};

在裸機系統中,程序的主體是CPU按照順序執行的。而在多任務系統中,任務的執行是由系統調度的。

系統為了順利的調度任務, 為每個任務都額外定義了一個任務控制塊TCB(Task ControlBlock),這個任務控制塊就相當于任務的身份證, 里面存有任務的所有信息,比如任務的棧,任務名稱,任務的形參等。

有了這個任務控制塊之后, 以后系統對任務的全部操作都可以通過這個TCB來實現。
TCB是一個新的數據類型, 在os.h這個頭文件中聲明,使用它可以為每個任務都定義一個TCB實體。
目前TCB里面的成員還比較少,只有棧指針和棧大小。其中為了以后操作方便,我們把棧指針作為TCB的第一個成員。

5、任務創建函數

在這里插入圖片描述

#include "os.h"void OSTaskCreate (OS_TCB        *p_tcb, OS_TASK_PTR   p_task, void          *p_arg,CPU_STK       *p_stk_base,CPU_STK_SIZE  stk_size,OS_ERR        *p_err)
{CPU_STK       *p_sp;p_sp = OSTaskStkInit (p_task,p_arg,p_stk_base,stk_size);p_tcb->StkPtr = p_sp;p_tcb->StkSize = stk_size;*p_err = OS_ERR_NONE;
}

任務的棧,任務的函數實體,任務的TCB最終需要聯系起來才能由系統進行統一調度。

那么這個聯系的工作就由任務創建函數 OSTaskCreate來實現,該函數在os_task.c中定義,所有跟任務相關的函數都在這個文件定義。

  • OSTaskCreate函數遵循μC/OS-III中的函數命名規則,以大小的OS開頭,表示這是一個外部函數,可以由用戶調用,以OS_開頭的函數表示內部函數,只能由μC/OS-III內部使用。緊接著是文件名,表示該函數放在哪個文件,最后是函數功能名稱。
  • p_tcb是任務控制塊指針。
  • p_task 是任務函數名,類型為OS_TASK_PTR,原型聲明在os.h中

在這里插入圖片描述
在這里插入圖片描述

  • p_arg是任務形參,用于傳遞任務參數。 p_stk_base 用于指向任務棧的起始地址。 stk_size 表示任務棧的大小。
  • p_err 用于存錯誤碼,μC/OS-III中為函數的返回值預先定義了很多錯誤碼,
    錯誤碼是枚舉類型的數據,在os.h中定義 OSTaskStkInit()是任務棧初始化函數。 當任務第一次運行的時候, 加載到CPU寄存器的參數就放在任務棧里面,在任務創建的時候,預先初始化好棧。
  • OSTaskStkInit()函數在os_cpu_c.c中定義
  • p_tcb->StkPtr = p_sp;
    將剩余棧的棧頂指針p_sp保存到任務控制塊TCB的第一個成員StkPtr中。
  • p_tcb->StkSize = stk_size;
    將任務棧的大小保存到任務控制塊TCB的成員StkSize中。
  • *p_err = OS_ERR_NONE;
    函數執行到這里表示沒有錯誤,即OS_ERR_NONE。

6、任務棧初始化函數

在這里插入圖片描述

#include "os.h"/* 任務堆棧初始化 */
CPU_STK *OSTaskStkInit (OS_TASK_PTR  p_task,void         *p_arg,CPU_STK      *p_stk_base,CPU_STK_SIZE stk_size)
{CPU_STK  *p_stk;p_stk = &p_stk_base[stk_size];/* 異常發生時自動保存的寄存器                              */*--p_stk = (CPU_STK)0x01000000u;                        /* xPSR的bit24必須置1                                     */*--p_stk = (CPU_STK)p_task;                             /* 任務的入口地址                                         */*--p_stk = (CPU_STK)0x14141414u;                        /* R14 (LR)                                               */*--p_stk = (CPU_STK)0x12121212u;                        /* R12                                                    */*--p_stk = (CPU_STK)0x03030303u;                        /* R3                                                     */*--p_stk = (CPU_STK)0x02020202u;                        /* R2                                                     */*--p_stk = (CPU_STK)0x01010101u;                        /* R1                                                     */*--p_stk = (CPU_STK)p_arg;                              /* R0 : 任務形參                                          *//* 異常發生時需手動保存的寄存器                            */*--p_stk = (CPU_STK)0x11111111u;                        /* R11                                                    */*--p_stk = (CPU_STK)0x10101010u;                        /* R10                                                    */*--p_stk = (CPU_STK)0x09090909u;                        /* R9                                                     */*--p_stk = (CPU_STK)0x08080808u;                        /* R8                                                     */*--p_stk = (CPU_STK)0x07070707u;                        /* R7                                                     */*--p_stk = (CPU_STK)0x06060606u;                        /* R6                                                     */*--p_stk = (CPU_STK)0x05050505u;                        /* R5                                                     */*--p_stk = (CPU_STK)0x04040404u;                        /* R4                                                     */return (p_stk);
}
  • p_task是任務名,指示著任務的入口地址,在任務切換的時候,需要加載到R15, 即PC寄存器,這樣CPU就可以找到要運行的任務。

  • p_arg 是任務的形參,用于傳遞參數,在任務切換的時候,需要加載到寄存器R0。R0寄存器通常用來傳遞參數。

  • p_stk_base 表示任務棧的起始地址。

  • stk_size 表示任務棧的大小, 數據類型為CPU_STK_SIZE,在Cortex-M3內核的處理器中等于4個字節,即一個字。

  • p_stk = &p_stk_base[stk_size];
    獲取任務棧的棧頂地址,ARMCM3處理器的棧是由高地址向低地址生長的。所以初始化棧之前, 要獲取到棧頂地址,然后棧地址逐一遞減即可。

  • /* 異常發生時自動保存的寄存器 */ 下面的八行
    任務第一次運行的時候,加載到CPU寄存器的環境參數我們要預先初始化好。初始化的順序固定, 首先是異常發生時自動保存的8個寄存器,即xPSR、R15、R14、R12、R3、R2、R1和R0。其中xPSR寄存器的位24必須是1, R15PC指針必須存的是任務的入口地址,R0必須是任務形參,剩下的R14、R12、R3、R2和R1為了調試方便,填入與寄存器號相對應的16進制數。

  • /* 異常發生時需手動保存的寄存器 */ 下面的八行
    剩下的是8個需要手動加載到CPU寄存器的參數,為了調試方便填入與寄存器號相對應的16進制數。

  • 返回棧指針p_stk,這個時候p_stk指向剩余棧的棧頂。

7、將任務添加到就緒列表

任務創建好之后,我們需要把任務添加到一個叫就緒列表的數組里面,表示任務已經就緒,系統隨時可以調度。

在這里插入圖片描述

在這里插入圖片描述

int main(void)
{	OS_ERR err;/* 初始化相關的全局變量 */OSInit(&err);/* 創建任務 */OSTaskCreate ((OS_TCB*)      &Task1TCB, (OS_TASK_PTR ) Task1, (void *)       0,(CPU_STK*)     &Task1Stk[0],(CPU_STK_SIZE) TASK1_STK_SIZE,(OS_ERR *)     &err);OSTaskCreate ((OS_TCB*)      &Task2TCB, (OS_TASK_PTR ) Task2, (void *)       0,(CPU_STK*)     &Task2Stk[0],(CPU_STK_SIZE) TASK2_STK_SIZE,(OS_ERR *)     &err);/* 將任務加入到就緒列表 */OSRdyList[0].HeadPtr = &Task1TCB;OSRdyList[1].HeadPtr = &Task2TCB;/* 啟動OS,將不再返回 */				OSStart(&err);
}

把任務TCB指針放到OSRDYList數組里面。
OSRdyList定義如下
在這里插入圖片描述
OS_CFG_PRIO_MAX是一個定義,表示這個系統支持多少個優先級(剛開始暫時不支持多個優先級,往后章節會支持), 目前這里僅用 來表示這個就緒列表可以存多少個任務的TCB指針。

具體的宏在os_cfg.h中定義
在這里插入圖片描述

OSRdyList是一個類型為OS_RDY_LIST的全局變量, 在os.h中定義

μC/OS-III中中會為每個數據類型重新取一個大寫的名字。

OS_RDY_LIST里面目前暫時只有兩個TCB類型的指針,一個是頭指針,一個是尾指針。

需要使用頭尾指針來將TCB串成一個雙向鏈表。
在這里插入圖片描述

8、全局變量的聲明方法

在μC/OS-III中,需要使用很多全局變量,這些全局變量都在os.h這個頭文件中定義,但是os.h會被包含進很多的文件中, 那么編譯的時候,os.h里面定義的全局變量就會出現重復定義的情況,而我們要的只是os.h里面定義的全局變量只定義一次, 其他包含os.h頭文件的時候只是聲明。

通常我們的做法都是在C文件里面定義全局變量,然后在頭文件里面加extern聲明,哪里需要使用就在哪里加extern聲明。
但是μC/OS-III中,文件非常多,這種方法可行,但不現實。所以就有了現在在os.h頭文件中定義全局變量, 然后在os.h文件的開頭加上 代碼清單:任務-17 的宏定義的方法。

但是到了這里還沒成功, μC/OS-III再另外新建了一個os_var.c的文件,在里面包含os.h, 且只在這個文件里面定義OS_GLOBALS這個宏

如果沒有定義OS_GLOBALS這個宏,那么OS_EXT就為空,否則就為extern。
在這里插入圖片描述
經過這樣處理之后,在編譯整個工程的時候,只有var.c里面的os.h的OS_EXT才會被替換為空,即變量的定義, 其他包含os.h的文件因為沒有定義OS_GLOBALS這個宏,則OS_EXT會被替換成extern,即變成了變量的聲明。 這樣就實現了在頭文件中定義變量。
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/719427.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/719427.shtml
英文地址,請注明出處:http://en.pswp.cn/news/719427.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

js 精確計算(解決js四則運算精度缺失問題)

js的小數的運算,可能會得到一個不精確的結果,因為所有的運算都要轉換成二進制去計算,然而,二進制無法精確表示1/10。 var a 0.1 0.2; console.log(a); //打印結果:0.30000000000000004因此需要使用以下方法實現精確…

這是開玩笑嗎?加個工具,WPS與Excel表格變成了應用系統

表格處理數據簡單快捷,是個人用戶的首選。然而,當企業長期使用,成本表、客戶表、銷售表等堆積如山,尋找所需表格如同大海撈針,稍有不慎便可能導致數據丟失、混亂。即便使用WPS和Excel這樣的表格軟件,處理大…

代碼隨想錄算法訓練營第三十六天 | LeeCode 435. 無重疊區間 ,763.劃分字母區間 , 56. 合并區間

435. 無重疊區間 - 力扣&#xff08;LeetCode&#xff09; class Solution { private:static bool cmp(const vector<int> &a,const vector<int> &b){if(a[0]b[0]) return a[1]<b[1];return a[0]<b[0];} public:int eraseOverlapIntervals(vector&l…

C#進階高級語法之LINQ:查詢操作的便利性與效率提升

引言&#xff1a; 在C#編程中&#xff0c;LINQ&#xff08;Language-Integrated Query&#xff09;是一種強大的查詢語言&#xff0c;它被集成在.NET框架中&#xff0c;允許開發者對各種數據源進行查詢和操作。LINQ的出現&#xff0c;極大地提升了C#在數據處理方面的能力&#…

回溯難題(算法村第十八關黃金挑戰)

復原 IP 地址 93. 復原 IP 地址 - 力扣&#xff08;LeetCode&#xff09; 有效 IP 地址 正好由四個整數&#xff08;每個整數位于 0 到 255 之間組成&#xff0c;且不能含有前導 0&#xff09;&#xff0c;整數之間用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 &q…

IDEA中使用git提交代碼時,有.class文件怎么避免

在IDEA中使用git提交代碼時&#xff0c;git把.class文件都給我放進來了&#xff0c;而我并不想要提交.class文件 我要提交的是.java文件 應該怎么設置呢 解決方案&#xff0c;點擊整個項目的生命周期中的clean之前&#xff0c;你會發現git提交欄的.class文件都不見了。

常用LDO型號

常用LDO型號 常用LDO型號-國產&進口 常用的LDO&#xff08;低壓差線性穩壓器&#xff09;型號有以下這些&#xff1a; LM2937及LM2937-N&#xff1a;這兩款是TI&#xff08;德州儀器&#xff09;的產品&#xff0c;其中LM2937-N為低噪聲版本&#xff0c;適用于對噪聲敏感…

vue是如何監聽對象和數組變化的

Vue框架通過其響應式系統來監聽對象和數組的變化。這個系統的核心在于追蹤依賴關系&#xff0c;并在數據變化時通知所有依賴于該數據的觀察者。 1. 對象監聽 Vue使用Object.defineProperty方法來劫持各個屬性的getter和setter。當組件中的數據被讀取時&#xff0c;會觸發gette…

ROS2服務通信的實現

文章目錄 1.服務通信的概念及應用場景1.1概念1.2 應用場景 2.準備工作3.服務通信的實現3.1 服務通信接口消息3.2 服務端實現3.3 客戶端實現3.4 編譯及運行3.4.1 修改CMakeLists3.4.2 服務端運行結果3.4.2 客戶端運行結果 1.服務通信的概念及應用場景 1.1概念 服務通信也是ROS…

抖店0元入駐不交錢會怎么樣?個人店和個體店的利弊分析,開店必看

我是王路飛。 現在的抖店是可以開通個人店的。 也就是不需要營業執照、直接使用個人身份證就可以在抖音開店&#xff0c;而且也不需要繳納店鋪保證金就能開店運營了。 但真實情況是怎么樣的呢&#xff1f;新手0元入駐抖店不交這個保證金會怎么樣呢&#xff1f; 今天給想在抖…

AI大預言模型——ChatGPT在地學、GIS、氣象、農業、生態、環境應用

原文鏈接&#xff1a;AI大預言模型——ChatGPT在地學、GIS、氣象、農業、生態、環境應用 一開啟大模型 1 開啟大模型 1)大模型的發展歷程與最新功能 2)大模型的強大功能與應用場景 3)國內外經典大模型&#xff08;ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diff…

ios App 發送廣播失敗解決

記錄開發 ios App 使用 c 混編時遇到的問題&#xff1a; 開發環境 macOS Sonoma&#xff08;最新版本14.3.1&#xff09; Xcode Version 15.2 ipadOS&#xff08;最新版本17.3.1&#xff09; 問題&#xff1a;在mac 上 和 ipad上測試&#xff0c;當 udp 發送廣播&#xff…

跨域引起的兩個接口的session_id不是同一個

來源場景&#xff1a; RequestMapping(“/captcha”)接口設置了SESSION_KEY&#xff0c;也能獲取到&#xff0c;但是到了PostMapping(“/login”)接口就是空的&#xff0c;由于跨域導致的兩個session_id不是同一個 /*** 系統用戶 前端控制器*/ Controller CrossOrigin(origins…

【數據結構和算法初階(C語言)】雙向循環帶頭鏈表的增刪查改詳解(天才設計的鏈表結構,應用簡單逆天!!!!!)

目錄 ?編輯?編輯 1.雙向鏈表的定義&#xff1a;前赴后繼 2.帶頭鏈表的定義-----哨兵位 3.增刪查改 3.1創建新節點函數----方便后續增加節點調用 3.2創建哨兵位----創建頭結點 3.3增加節點&#xff0c;尾部插入數據 3.4尾刪除 3.5查找函數----遍歷對比&#xff…

AcWing 562.壁畫

咱先看一眼算法標簽&#xff0c;發現是思維題、枚舉、前綴和 Buttt其實我們根據上訴的樣例解釋部分就會發現&#xff0c;其實這就是一個長度為?n/2?&#xff08;向上取整哦&#xff09;的連續子數組的最大和。 這題我也用暴力法試過啦&#xff0c;很明顯會TLE 如果你對dp題…

Mac M系列芯片如何重新安裝系統

使用可引導安裝器重新安裝&#xff08;可用于安裝非最新的 Mac OS&#xff0c;系統降級&#xff0c;需要清除所有數據&#xff0c;過程確保連接上網絡&#xff0c;雖然這種方式不會下載 Mac OS&#xff0c;但是需要下載固件等信息&#xff09; 插入制作好的可引導安裝器&#x…

【使用imgaug庫調整圖像大小并修改對應的XML標簽框】

使用imgaug庫可以方便地進行圖像增強操作&#xff0c;包括調整圖像大小。以下是使用imgaug庫調整圖像大小并修改對應的XML標簽框的示例腳本&#xff1a; 注意修改輸入文件夾路徑、輸出文件夾路徑和目標尺寸為自己內容。 input_folder "path/to/your/input_folder" …

kalibr標定ZED2i雙目加imu

一、錄制bag 本人使用的zed2i相機。 rosbag record -O 32 /zed2i/zed_node/imu/data /zed2i/zed_node/imdata_raw /zed2i/zed_node/left/image_rect_color /zed2i/zed_node/right/image_rect_color /zed2i/zed_node/left_raw/image_raw_color /zed2i/zed_node/right_raw/ima…

Matlab|【免費】基于合作博弈的綜合能源系統利益分配優化調度

目錄 主要內容 部分代碼 結果一覽 下載鏈接 主要內容 該程序實現的模型為綜合能源系統利益分配優化調度&#xff0c;采用合作博弈方法&#xff0c;模型針對IES系統的P2G、電解槽、甲烷反應器、儲氫罐、CHP和燃氣鍋爐等設備進行建模&#xff0c;實現基于合作博弈的…

std::shared_from_this注意事項:exception bad_weak_ptr

1.不可以在構造函數中調用shared_from_this() 因為它的實現是&#xff1a; _LIBCPP_INLINE_VISIBILITYshared_ptr<_Tp> shared_from_this(){return shared_ptr<_Tp>(__weak_this_);}也就是它依賴的__weak_this_此時還未創建完成。 2.一定要public繼承 class MyTy…