當前位置:首頁 > 單片機 > 單片機
[導讀]一、上篇回顧上一篇文章中,我們完成了兩個任務使用PendSV實現(xiàn)了互相切換的功能,下面我們接著其思路往下做。這次我們完成OS基本框架,即實現(xiàn)一個非搶占式(已經(jīng)調(diào)度的進程執(zhí)行完成,然后根據(jù)優(yōu)先級調(diào)度等待的進程)的

一、上篇回顧

上一篇文章中,我們完成了兩個任務使用PendSV實現(xiàn)了互相切換的功能,下面我們接著其思路往下做。這次我們完成OS基本框架,即實現(xiàn)一個非搶占式(已經(jīng)調(diào)度的進程執(zhí)行完成,然后根據(jù)優(yōu)先級調(diào)度等待的進程)的任務調(diào)度系統(tǒng),至于搶占式的,就留給大家思考了。上次代碼中Task_Switch實現(xiàn)了兩個任務的切換,代碼如下:


voidTask_Switch(){if(g_OS_Tcb_CurP==&TCB_1)g_OS_Tcb_HighRdyP=&TCB_2;elseg_OS_Tcb_HighRdyP=&TCB_1;OSCtxSw();}


我們把要切換任務指針付給跟_OS_Tcb_HighRdyP,然后調(diào)用OSCtxSw觸發(fā)PendSV異常,就實現(xiàn)了任務的切換。如果是多個任務,我們只需找出就緒任務中優(yōu)先級最大的切換之即可。

二、添加任務調(diào)度功能

為了實現(xiàn)這一目標我們至少需要知道任務的狀態(tài)和時間等數(shù)據(jù)。我們定義了一個任務狀態(tài)枚舉類型OS_TASK_STA,方便添加修改狀態(tài)。在OS_TCB結(jié)構(gòu)體中添加了兩個成員TimeDly和State,TimeDly是為了實現(xiàn)OS_TimeDly,至于State與優(yōu)先級一起是作為任務切換的依據(jù)。


typedefenumOS_TASK_STA{TASK_READY,TASK_DELAY,}OS_TASK_STA;typedefstructOS_TCB{OS_STK*StkAddr;OS_U32TimeDly;OS_TASK_STAState;}OS_TCB,*OS_TCBP;


說到任務切換,我們必須面對臨界區(qū)的問題,在一些臨界的代碼兩端不加臨界區(qū)進去和退出代碼,會出現(xiàn)許多意想不到的問題。以下地方需要特別注意,對關鍵的全局變量的寫操作、對任務控制塊的操作等。進入臨界區(qū)和退出臨界區(qū)需要關閉和開啟中斷,我們采用uCOS中的一部分代碼:


PUBLICOS_CPU_SR_SavePUBLICOS_CPU_SR_RestoreOS_CPU_SR_SaveMRSR0,PRIMASKCPSIDIBXLROS_CPU_SR_RestoreMSRPRIMASK,R0BXLR


#defineOS_USE_CRITICALOS_U32cpu_sr;#defineOS_ENTER_CRITICAL(){cpu_sr=OS_CPU_SR_Save();}#defineOS_EXIT_CRITICAL(){OS_CPU_SR_Restore(cpu_sr);}#defineOS_PendSV_Trigger()OSCtxSw()

一個OS至少要有任務表,我們可以用數(shù)組,當然也可以用鏈表。為了簡單,我們使用數(shù)組,使用數(shù)組下表作為優(yōu)先級。當然,必要的地方一定要做數(shù)組越界檢查。

#defineOS_TASK_MAX_NUM32OS_TCBPOS_TCB_TABLE[OS_TASK_MAX_NUM];

為了使OS更完整,我們定義幾個全局變量,OS_TimeTick記錄系統(tǒng)時間,g_Prio_Cur記錄當前運行的任務優(yōu)先級,g_Prio_HighRdy記錄任務調(diào)度后就緒任務中的最高優(yōu)先級。

OS_U32OS_TimeTick;OS_U8g_Prio_Cur;OS_U8g_Prio_HighRdy;

下面三個函數(shù)與PendSV一起實現(xiàn)了任務的調(diào)度功能。

OS_Task_Switch函數(shù)功能:找出已就緒最高優(yōu)先級的任務,并將其TCB指針賦值給g_OS_Tcb_HighRdyP,將其優(yōu)先級賦值g_Prio_HighRdy。注意其中使用了臨界區(qū)。


voidOS_Task_Switch(void){OS_S32i;OS_TCBPtcb_p;OS_USE_CRITICALfor(i=0;iState==TASK_READY)break;}OS_ENTER_CRITICAL();g_OS_Tcb_HighRdyP=tcb_p;g_Prio_HighRdy=i;OS_EXIT_CRITICAL();}


OS_TimeDly至當前任務為延時狀態(tài),并將延時時間賦值給當前TCB的TimeDly成員,并調(diào)用OS_Task_Switch函數(shù),然后觸發(fā)PendSV進行上下文切換。OS_Task_Switch找到就緒狀態(tài)中優(yōu)先級最高的,并將其賦值相關全局變量,作為上下文切換的依據(jù)。


voidOS_TimeDly(OS_U32ticks){OS_USE_CRITICALOS_ENTER_CRITICAL();g_OS_Tcb_CurP->State=TASK_DELAY;g_OS_Tcb_CurP->TimeDly=ticks;OS_EXIT_CRITICAL();OS_Task_Switch();OS_PendSV_Trigger();}


SysTick_Handler實現(xiàn)系統(tǒng)計時,并遍歷任務表,任務若是延時狀態(tài),就令其延時值減一,若減完后為零,就將其置為就緒狀態(tài)。


voidSysTick_Handler(void){OS_TCBPtcb_p;OS_S32i;OS_USE_CRITICALOS_ENTER_CRITICAL();++OS_TimeTick;for(i=0;iState==TASK_DELAY){--tcb_p->TimeDly;if(tcb_p->TimeDly==0)tcb_p->State=TASK_READY;}}OS_EXIT_CRITICAL();}


當所有任務都沒就緒怎么辦?這時就需要空閑任務了,我們把它設為優(yōu)先級最低的任務。WFE指令為休眠指令,當來中斷時,退出休眠,然后看看有沒有已就緒的任務,有則調(diào)度之,否則繼續(xù)休眠,這樣可以減小功耗哦。


voidOS_Task_Idle(void){while(1){asm("WFE");OS_Task_Switch();OS_PendSV_Trigger();}}


當一個任務只運行一次時(例如下面main.c的task1),結(jié)束時就會調(diào)用OS_Task_End函數(shù),此函數(shù)會調(diào)用OS_Task_Delete函數(shù)從任務表中刪除當前的任務,然后調(diào)度任務。


voidOS_Task_Delete(OS_U8prio){if(prio>=OS_TASK_MAX_NUM)return;OS_TCB_TABLE[prio]=0;}voidOS_Task_End(void){printf("TaskofPrio%dEndn",g_Prio_Cur);OS_Task_Delete(g_Prio_Cur);OS_Task_Switch();OS_PendSV_Trigger();}


三、OS實戰(zhàn)

下是完整的main.c代碼:


#include"stdio.h"#include"stm32f4xx.h"#defineOS_EXCEPT_STK_SIZE1024#defineTASK_1_STK_SIZE128#defineTASK_2_STK_SIZE128#defineTASK_3_STK_SIZE128#defineTASK_IDLE_STK_SIZE1024#defineOS_TASK_MAX_NUM32#defineOS_TICKS_PER_SECOND1000#defineOS_USE_CRITICALOS_U32cpu_sr;#defineOS_ENTER_CRITICAL(){cpu_sr=OS_CPU_SR_Save();}#defineOS_EXIT_CRITICAL(){OS_CPU_SR_Restore(cpu_sr);}#defineOS_PendSV_Trigger()OSCtxSw()typedefsignedcharOS_S8;typedefsignedshortOS_S16;typedefsignedintOS_S32;typedefunsignedcharOS_U8;typedefunsignedshortOS_U16;typedefunsignedintOS_U32;typedefunsignedintOS_STK;typedefvoid(*OS_TASK)(void);typedefenumOS_TASK_STA{TASK_READY,TASK_DELAY,}OS_TASK_STA;typedefstructOS_TCB{OS_STK*StkAddr;OS_U32TimeDly;OS_U8State;}OS_TCB,*OS_TCBP;OS_TCBPOS_TCB_TABLE[OS_TASK_MAX_NUM];OS_TCBPg_OS_Tcb_CurP;OS_TCBPg_OS_Tcb_HighRdyP;OS_U32OS_TimeTick;OS_U8g_Prio_Cur;OS_U8g_Prio_HighRdy;staticOS_STKOS_CPU_ExceptStk[OS_EXCEPT_STK_SIZE];OS_STK*g_OS_CPU_ExceptStkBase;staticOS_TCBTCB_1;staticOS_TCBTCB_2;staticOS_TCBTCB_3;staticOS_TCBTCB_IDLE;staticOS_STKTASK_1_STK[TASK_1_STK_SIZE];staticOS_STKTASK_2_STK[TASK_2_STK_SIZE];staticOS_STKTASK_3_STK[TASK_3_STK_SIZE];staticOS_STKTASK_IDLE_STK[TASK_IDLE_STK_SIZE];externOS_U32SystemCoreClock;externvoidOSStart_Asm(void);externvoidOSCtxSw(void);externOS_U32OS_CPU_SR_Save(void);externvoidOS_CPU_SR_Restore(OS_U32);voidtask_1(void);voidtask_2(void);voidtask_3(void);voidOS_Task_Idle(void);voidOS_TimeDly(OS_U32);voidOS_Task_Switch(void);voidOS_Task_Create(OS_TCB*,OS_TASK,OS_STK*,OS_U8);voidOS_Task_Delete(OS_U8);voidOS_Task_End(void);voidOS_Init(void);voidOS_Start(void);voidtask_1(void){printf("[%d]Task1Runing!!!n",OS_TimeTick);OS_Task_Create(&TCB_2,task_2,&TASK_2_STK[TASK_2_STK_SIZE-1],5);OS_Task_Create(&TCB_3,task_3,&TASK_3_STK[TASK_3_STK_SIZE-1],7);}voidtask_2(void){while(1){printf("[%d]Task2Runing!!!n",OS_TimeTick);OS_TimeDly(1000);}}voidtask_3(void){while(1){printf("[%d]Task3Runing!!!n",OS_TimeTick);OS_TimeDly(1500);}}voidOS_Task_Idle(void){while(1){asm("WFE");OS_Task_Switch();OS_PendSV_Trigger();}}voidOS_TimeDly(OS_U32ticks){OS_USE_CRITICALOS_ENTER_CRITICAL();g_OS_Tcb_CurP->State=TASK_DELAY;g_OS_Tcb_CurP->TimeDly=ticks;OS_EXIT_CRITICAL();OS_Task_Switch();OS_PendSV_Trigger();}voidOS_Task_Switch(void){OS_S32i;OS_TCBPtcb_p;OS_USE_CRITICALfor(i=0;iState==TASK_READY)break;}OS_ENTER_CRITICAL();g_OS_Tcb_HighRdyP=tcb_p;g_Prio_HighRdy=i;OS_EXIT_CRITICAL();}voidOS_Task_Delete(OS_U8prio){if(prio>=OS_TASK_MAX_NUM)return;OS_TCB_TABLE[prio]=0;}voidOS_Task_End(void){printf("TaskofPrio%dEndn",g_Prio_Cur);OS_Task_Delete(g_Prio_Cur);OS_Task_Switch();OS_PendSV_Trigger();}voidOS_Task_Create(OS_TCB*tcb,OS_TASKtask,OS_STK*stk,OS_U8prio){OS_USE_CRITICALOS_STK*p_stk;if(prio>=OS_TASK_MAX_NUM)return;OS_ENTER_CRITICAL();p_stk=stk;p_stk=(OS_STK*)((OS_STK)(p_stk)&0xFFFFFFF8u);*(--p_stk)=(OS_STK)0x01000000uL;//xPSR*(--p_stk)=(OS_STK)task;//EntryPoint*(--p_stk)=(OS_STK)OS_Task_End;//R14(LR)*(--p_stk)=(OS_STK)0x12121212uL;//R12*(--p_stk)=(OS_STK)0x03030303uL;//R3*(--p_stk)=(OS_STK)0x02020202uL;//R2*(--p_stk)=(OS_STK)0x01010101uL;//R1*(--p_stk)=(OS_STK)0x00000000u;//R0*(--p_stk)=(OS_STK)0x11111111uL;//R11*(--p_stk)=(OS_STK)0x10101010uL;//R10*(--p_stk)=(OS_STK)0x09090909uL;//R9*(--p_stk)=(OS_STK)0x08080808uL;//R8*(--p_stk)=(OS_STK)0x07070707uL;//R7*(--p_stk)=(OS_STK)0x06060606uL;//R6*(--p_stk)=(OS_STK)0x05050505uL;//R5*(--p_stk)=(OS_STK)0x04040404uL;//R4tcb->StkAddr=p_stk;tcb->TimeDly=0;tcb->State=TASK_READY;OS_TCB_TABLE[prio]=tcb;OS_EXIT_CRITICAL();}voidSysTick_Handler(void){OS_TCBPtcb_p;OS_S32i;OS_USE_CRITICALOS_ENTER_CRITICAL();++OS_TimeTick;for(i=0;iState==TASK_DELAY){--tcb_p->TimeDly;if(tcb_p->TimeDly==0)tcb_p->State=TASK_READY;}}OS_EXIT_CRITICAL();}voidOS_Init(void){inti;g_OS_CPU_ExceptStkBase=OS_CPU_ExceptStk+OS_EXCEPT_STK_SIZE-1;asm("CPSIDI");for(i=0;i

本站聲明: 本文章由作者或相關機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉