日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

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

一、上篇回顧

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


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,然后調用OSCtxSw觸發(fā)PendSV異常,就實現了任務的切換。如果是多個任務,我們只需找出就緒任務中優(yōu)先級最大的切換之即可。

二、添加任務調度功能

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


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ū)進去和退出代碼,會出現許多意想不到的問題。以下地方需要特別注意,對關鍵的全局變量的寫操作、對任務控制塊的操作等。進入臨界區(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至少要有任務表,我們可以用數組,當然也可以用鏈表。為了簡單,我們使用數組,使用數組下表作為優(yōu)先級。當然,必要的地方一定要做數組越界檢查。

#defineOS_TASK_MAX_NUM32OS_TCBPOS_TCB_TABLE[OS_TASK_MAX_NUM];

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

OS_U32OS_TimeTick;OS_U8g_Prio_Cur;OS_U8g_Prio_HighRdy;

下面三個函數與PendSV一起實現了任務的調度功能。

OS_Task_Switch函數功能:找出已就緒最高優(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成員,并調用OS_Task_Switch函數,然后觸發(fā)PendSV進行上下文切換。OS_Task_Switch找到就緒狀態(tài)中優(yōu)先級最高的,并將其賦值相關全局變量,作為上下文切換的依據。


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實現系統計時,并遍歷任務表,任務若是延時狀態(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指令為休眠指令,當來中斷時,退出休眠,然后看看有沒有已就緒的任務,有則調度之,否則繼續(xù)休眠,這樣可以減小功耗哦。


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


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


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

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

在嵌入式開發(fā)中,STM32的時鐘系統因其靈活性和復雜性成為開發(fā)者關注的焦點。然而,看似簡單的時鐘配置背后,隱藏著諸多易被忽視的陷阱,輕則導致系統不穩(wěn)定,重則引發(fā)硬件損壞。本文從時鐘源選擇、PLL配置、總線時鐘分配等關鍵環(huán)...

關鍵字: STM32 時鐘系統

在嵌入式系統開發(fā)中,STM32系列微控制器的內部溫度傳感器因其低成本、高集成度特性,廣泛應用于設備自檢、環(huán)境監(jiān)測等場景。然而,受芯片工藝差異和電源噪聲影響,其原始數據存在±1.5℃的固有誤差。本文從硬件配置、校準算法、軟...

關鍵字: STM32 溫度傳感器

在能源效率與智能化需求雙重驅動下,AC-DC轉換器的數字控制技術正經歷從傳統模擬方案向全數字架構的深刻變革?;赟TM32微控制器的PFM(脈沖頻率調制)+PWM(脈沖寬度調制)混合調制策略,結合動態(tài)電壓調整(Dynam...

關鍵字: AC-DC STM32

當前智能家居產品需求不斷增長 ,在這一背景下 ,對現有澆花裝置缺陷進行了改進 ,設計出基于STM32單片機的全 自動家用澆花機器人。該設計主要由機械結構和控制系統構成 ,機械結構通過麥克納姆輪底盤與噴灑裝置的結合實現機器...

關鍵字: STM32 麥克納姆輪 安全可靠 通過性強

用c++編程似乎是讓你的Arduino項目起步的障礙嗎?您想要一種更直觀的微控制器編程方式嗎?那你需要了解一下Visuino!這個圖形化編程平臺將復雜電子項目的創(chuàng)建變成了拖動和連接塊的簡單任務。在本文中,我們將帶您完成使...

關鍵字: Visuino Arduino ESP32 STM32

基于STM32與LoRa技術的無線傳感網絡憑借其低功耗、廣覆蓋、抗干擾等特性,成為環(huán)境監(jiān)測、工業(yè)自動化等場景的核心解決方案。然而,如何在復雜電磁環(huán)境中實現高效休眠調度與動態(tài)信道優(yōu)化,成為提升網絡能效與可靠性的關鍵挑戰(zhàn)。本...

關鍵字: STM32 LoRa

在實時控制系統、高速通信協議處理及高精度數據采集等對時間敏感的應用場景中,中斷響應延遲的優(yōu)化直接決定了系統的可靠性與性能上限。STM32系列微控制器憑借其靈活的嵌套向量中斷控制器(NVIC)、多通道直接內存訪問(DMA)...

關鍵字: STM32 DMA

數字電源技術向高功率密度、高效率與高動態(tài)響應方向加速演進,STM32微控制器憑借其基于DSP庫的算法加速能力與對LLC諧振變換器的精準控制架構,成為優(yōu)化電源動態(tài)性能的核心平臺。相較于傳統模擬控制或通用型數字控制器,STM...

關鍵字: STM32 數字電源

STM32微控制器憑借其針對電機控制場景的深度優(yōu)化,成為高精度、高可靠性驅動系統的核心選擇。相較于通用型MCU,STM32在電機控制領域的核心優(yōu)勢集中體現在FOC(磁場定向控制)算法的硬件加速引擎與PWM死區(qū)時間的動態(tài)補...

關鍵字: STM32 電機控制

無線充電技術加速滲透消費電子與汽車電子領域,基于Qi協議的無線充電發(fā)射端開發(fā)成為智能設備能量補給的核心課題。傳統模擬控制方案存在響應滯后、參數調整困難等問題,而基于STM32的數字PID控制結合FOD(Foreign O...

關鍵字: STM32 無線充電
關閉