<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STM32 uC/OS_II 實(shí)踐 之 任務(wù)調(diào)度過(guò)程理解及查詢式事件

          STM32 uC/OS_II 實(shí)踐 之 任務(wù)調(diào)度過(guò)程理解及查詢式事件

          作者: 時(shí)間:2016-12-03 來(lái)源:網(wǎng)絡(luò) 收藏
          先把入口函數(shù)main給貼出來(lái),就從這里開(kāi)始,來(lái)自文件main.c

          /*******************************************************************************
          * Function Name : main
          * Description : 主函數(shù),對(duì)系統(tǒng)以及硬件初始化,建立主函數(shù)并開(kāi)啟系統(tǒng)
          * Input : None
          * Output : None
          * Return : None
          *******************************************************************************/
          int main(void)
          {
          CPU_IntDis(); // 禁止CPU中斷 連接到匯編
          OSInit(); // uCOS系統(tǒng)初始化
          BSP_Init(); // 硬件初始化


          OSTaskCreate //建立主任務(wù), 優(yōu)先級(jí)最高 建立這個(gè)任務(wù)另外一個(gè)用途是為了以后使用統(tǒng)計(jì)任務(wù)
          (
          (void (*) (void *)) App_TaskStart, //指向任務(wù)代碼的指針
          (void *) 0,//任務(wù)開(kāi)始執(zhí)行時(shí),傳遞給任務(wù)的參數(shù)的指針
          (OS_STK *) &App_TaskStartStk[APP_TASK_START_STK_SIZE - 1], //分配給任務(wù)的堆棧的棧頂指針,從(INT8U) APP_TASK_START_PRIO //分配給任務(wù)的優(yōu)先級(jí)
          );

          OSTimeSet(0);
          OSStart();

          return(0);
          }

          本文引用地址:http://www.ex-cimer.com/article/201612/325149.htm

          在開(kāi)始 uC/OS_II 的調(diào)度之前,我們需要調(diào)用函數(shù)OSInit(),他負(fù)責(zé)建立任務(wù)控制塊鏈表,就緒任務(wù)表等數(shù)據(jù)結(jié)構(gòu),然后初始化全局變量。然后把需要用的外部設(shè)備進(jìn)行初始化,主要是時(shí)鐘初始化,中斷嵌套初始化,端口初始化,調(diào)用函數(shù)BSP_Init(),uC/OS_II規(guī)定在任務(wù)調(diào)度開(kāi)始前至少有一個(gè)任務(wù)已經(jīng)建立,所以我們建立一個(gè)任務(wù)APP_TaskStart,并且給這個(gè)任務(wù)分配優(yōu)先級(jí)以及堆棧等資源這是必須的啦,然后我們用OSTimeSet(0)函數(shù)初始化系統(tǒng)的時(shí)鐘節(jié)拍數(shù)后,就調(diào)用OSStart()函數(shù)開(kāi)始任務(wù)調(diào)度,任務(wù)就會(huì)從所有建立的任務(wù)里最高優(yōu)先級(jí)開(kāi)始執(zhí)行。
          大家還記得剛才建立了一個(gè)APP_TaskStart任務(wù),在系統(tǒng)開(kāi)始任務(wù)調(diào)度的時(shí)候,系統(tǒng)里除了默認(rèn)的優(yōu)先級(jí)最低的空閑任務(wù)外只有這一個(gè)任務(wù)被注冊(cè)了,自然就會(huì)運(yùn)行這個(gè)任務(wù),我們先來(lái)看下他的相關(guān)源代碼來(lái)自文件task.c:

          /*******************************************************************************
          * Function Name : App_TaskStart
          * Description : 主任務(wù)
          * Input : None
          * Output : None
          * Return : None
          *******************************************************************************/
          void App_TaskStart(void* p_arg)
          {
          (void) p_arg;

          OS_CPU_SysTickInit(); // 初始化系統(tǒng)心跳

          #if (OS_TASK_STAT_EN > 0)
          OSStatInit(); // 統(tǒng)計(jì)任務(wù)初始化函數(shù)
          #endif

          App_TaskCreate(); // 創(chuàng)建新的用戶任務(wù)

          while(1)
          {
          LED4_HIGH;
          OSTimeDlyHMSM(0,0,1,0);
          LED4_LOW;
          OSTimeDlyHMSM(0,0,1,0);
          }

          }

          /*******************************************************************************
          * Function Name : App_TaskCreate
          * Description : 建立用戶任務(wù)
          * Input : None
          * Output : None
          * Return : None
          *******************************************************************************/
          void App_TaskCreate(void)
          {
          //===================================================================// 測(cè)試任務(wù)1
          OSTaskCreateExt(
          Task_Test1,// 指向任務(wù)代碼的指針,也就是任務(wù)函數(shù)名
          (void *)0,// 任務(wù)開(kāi)始執(zhí)行時(shí)傳遞給任務(wù)的參數(shù)
          (OS_STK *)&Task_Test1Stk[Task_Test1_STK_SIZE-1],//分配給任務(wù)堆棧的棧頂指針,自頂向下
          Task_Test1_PRIO,// 分配給任務(wù)的優(yōu)先級(jí)
          Task_Test1_PRIO,// 預(yù)備給以后版本的標(biāo)識(shí)符,現(xiàn)在同任務(wù)優(yōu)先級(jí)
          (OS_STK *)&Task_Test1Stk[0], // 指向任務(wù)堆棧的棧底指針,用于堆棧的檢驗(yàn)
          Task_Test1_STK_SIZE, // 指定堆棧的容量,用于堆棧檢驗(yàn)
          (void *)0, // 指向用戶附加數(shù)據(jù)域的指針,用來(lái)擴(kuò)展任務(wù)控制塊
          OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR // 任務(wù)選項(xiàng):使能堆棧檢測(cè) 和 創(chuàng)建任務(wù)時(shí)清空堆棧
          );
          //===================================================================// 測(cè)試任務(wù)2
          OSTaskCreateExt(
          Task_Test2,
          (void *)0,
          (OS_STK *)&Task_Test2Stk[Task_Test2_STK_SIZE-1],
          Task_Test2_PRIO,
          Task_Test2_PRIO,
          (OS_STK *)&Task_Test2Stk[0],
          Task_Test2_STK_SIZE,
          (void *)0,
          OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR
          );
          //===================================================================// 測(cè)試任務(wù)3
          OSTaskCreateExt(
          Task_Test3,
          (void *)0,
          (OS_STK *)&Task_Test3Stk[Task_Test3_STK_SIZE-1],
          Task_Test3_PRIO,
          Task_Test3_PRIO,
          (OS_STK *)&Task_Test3Stk[0],
          Task_Test3_STK_SIZE,
          (void *)0,
          OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR
          );
          }

          同時(shí)給出任務(wù)的優(yōu)先級(jí)及堆棧大小等信息來(lái)自文件app_cfg.h
          //任務(wù)優(yōu)先級(jí)
          #define APP_TASK_START_PRIO 10

          #define Task_Test1_PRIO 7
          #define Task_Test2_PRIO 8
          #define Task_Test3_PRIO 9

          //任務(wù)堆棧大小
          #define APP_TASK_START_STK_SIZE 64

          #define Task_Test1_STK_SIZE 128
          #define Task_Test2_STK_SIZE 128
          #define Task_Test3_STK_SIZE 128
          可以看到,任務(wù)APP_TaskStart的優(yōu)先級(jí)最低,所以在這個(gè)任務(wù)里創(chuàng)建其他的任務(wù)的時(shí)候他就會(huì)被更高優(yōu)先級(jí)的任務(wù)把CPU的占有權(quán)搶去,在uC/OS_II里每建立一個(gè)任務(wù)后都會(huì)產(chǎn)生一次任務(wù)的調(diào)度,如果這個(gè)建立的任務(wù)優(yōu)先級(jí)更高,則系統(tǒng)就會(huì)去執(zhí)行這個(gè)剛創(chuàng)立的任務(wù),如果低就只能等著了。所以在建立Task_Test1任務(wù)后,就會(huì)跳轉(zhuǎn)執(zhí)行此任務(wù),現(xiàn)在我們來(lái)看下這三個(gè)測(cè)試任務(wù)的源代碼來(lái)自文件app.c    

          /*******************************************************************************
          * Function Name : Task_Test1
          * Description : 任務(wù)1
          * Input : None
          * Output : None
          * Return : None
          *******************************************************************************/
          void Task_Test1(void* p_arg)
          {
          (void) p_arg ;
          while(1)
          {
          if(KEY_WKUP == 0)
          {
          LED1_HIGH;
          }
          else
          {
          LED1_LOW;
          }
          OSTimeDlyHMSM(0,0,0,100); // 延時(shí),為其他低優(yōu)先級(jí)的任務(wù)執(zhí)行留有空間
          }
          }
          /*******************************************************************************
          * Function Name : Task_Test2
          * Description : 任務(wù)2
          * Input : None
          * Output : None
          * Return : None
          *******************************************************************************/
          void Task_Test2(void* p_arg)
          {
          (void) p_arg ;
          while(1)
          {
          LED2_HIGH;
          OSTimeDlyHMSM(0,0,0,500);
          LED2_LOW;
          OSTimeDlyHMSM(0,0,0,500);
          }
          }
          /*******************************************************************************
          * Function Name : Task_Test3
          * Description : 任務(wù)3
          * Input : None
          * Output : None
          * Return : None
          *******************************************************************************/
          void Task_Test3(void* p_arg)
          {
          (void) p_arg ;
          while(1)
          {
          LED3_HIGH;
          OSTimeDlyHMSM(0,0,0,500);
          LED3_LOW;
          OSTimeDlyHMSM(0,0,0,500);
          }
          }

          剛才說(shuō)到哪里了?對(duì),現(xiàn)在開(kāi)始執(zhí)行Task_Test1的任務(wù)了,很顯然,這個(gè)任務(wù)是對(duì)一個(gè)按鍵的檢測(cè),檢測(cè)完成后進(jìn)入一個(gè)100ms的延時(shí)函數(shù),在uC/OS_II里延時(shí)函數(shù)的作用要比以前的大得多,在uC/OS_II里任務(wù)中調(diào)用了延時(shí)函數(shù)時(shí),該任務(wù)就被退出了任務(wù)就緒表,然后調(diào)用一次系統(tǒng)調(diào)度OS_Sched(),重新尋找最高優(yōu)先級(jí)的任務(wù)去執(zhí)行,這個(gè)時(shí)候咱們的系統(tǒng)只注冊(cè)了兩個(gè)任務(wù),這樣就只能繼續(xù)執(zhí)行任務(wù)APP_TaskStart了,剛才在這個(gè)函數(shù)里建立第一個(gè)測(cè)試任務(wù)就被搶去了CPU的占用權(quán),現(xiàn)在回來(lái)繼續(xù)創(chuàng)建Task_Test2第二個(gè)測(cè)試任務(wù),這第二個(gè)測(cè)試任務(wù)優(yōu)先級(jí)也比開(kāi)始任務(wù)高,所以自然的它又被人搶去了CPU的占用權(quán),在第二個(gè)測(cè)試任務(wù)里大家又會(huì)看到有延時(shí)函數(shù),功能肯定是相同的,以此類(lèi)推第三個(gè)測(cè)試任務(wù)也就清晰的多了。這時(shí)還有一個(gè)問(wèn)題就是延時(shí)結(jié)束后系統(tǒng)操作,剛才測(cè)試任務(wù)1進(jìn)入延時(shí)后,不會(huì)被系統(tǒng)調(diào)用,他的延時(shí)變量OSTCBDly是隨著系統(tǒng)的心跳進(jìn)行遞減的,如果有兩個(gè)任務(wù)同時(shí)在延時(shí)中只要他們的任務(wù)控制塊里的延時(shí)變量不是0就會(huì)在心跳中斷服務(wù)函數(shù)里減1,等到他被減為0,系統(tǒng)會(huì)把這個(gè)任務(wù)重新放到任務(wù)就緒表里,并且運(yùn)行一次系統(tǒng)調(diào)度函數(shù)OS_Sched(),通過(guò)這種機(jī)制來(lái)保證系統(tǒng)始終在運(yùn)行著最高優(yōu)先級(jí)的任務(wù)。這樣系統(tǒng)的調(diào)度問(wèn)題就解釋完了,在后面關(guān)于中斷和信號(hào)量使用時(shí),他們對(duì)系統(tǒng)的執(zhí)行順序也是有影響的,他們是如何參與到系統(tǒng)的調(diào)度里,就看后面的講解了。

          剛才我們說(shuō)了延時(shí)函數(shù)的作用,如果我把上面的代碼里黃色高亮的部分注視掉會(huì)有什么樣的效果,結(jié)果就是其他的3個(gè)任務(wù)都無(wú)法運(yùn)行了,系統(tǒng)將一直處理任務(wù)Task_Test1,再加入我們?nèi)绻腰S色高亮部分的延時(shí)參數(shù)調(diào)大一些,調(diào)整到1s,結(jié)果也不令人滿意,雖然我給了提起任務(wù)充足的運(yùn)行時(shí)間,但是由于每檢測(cè)一次我都會(huì)等待很長(zhǎng)時(shí)間,導(dǎo)致我的檢測(cè)精度大大降低,按鍵變的極為難用。這時(shí)候我們就應(yīng)該思考,在uC/OS_II這樣一個(gè)實(shí)時(shí)的嵌入式操作系統(tǒng)里面,最可怕的就是無(wú)目的的等待,所以我們盡量使用中斷這樣方式去處理接口信息,中斷和實(shí)時(shí)系統(tǒng)是相得益彰的。




          評(píng)論


          技術(shù)專(zhuān)區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();