ucosii 移植STM32筆記之入門篇一

10.31

今天接觸了ucosii在STM32上面的移植,就碰到的幾個問題進行總結:

1、工程輸出文件出現錯誤,原因是沒有添加相應設備芯片的啓動文件;

2、出現undefined symbol ...  refered from ...,原因是OS_CPU_A.ASM這個彙編文件沒有添加;

3、啓動函數(如下),主要用於系統啓動之後進行調用的,也叫啓動任務:

 1  static void startup_task(void *p_arg) 
 2  { 
 3          systick_init(); /* Initialize the SysTick. */
 4  /*創建新任務,系統啓動時執行的任務,其餘的用戶可以其他地方自定義創建*/
 5          OSTaskCreate(led1_task,0,&led1_task_stk[LED1_TASK_STK_SIZE - 1], LED1_TASK_PRIO); 
 6 
 7     while(1)
 8      {
 9             OSTimeDlyHMSM(0,0,0,50); //500ms延時,釋放CPU控制權
10      } 
11  } 

 

當用戶想要創建新的任務,在主函數中進行如下編輯:

 1 int main(void) 
 2 { 
 3   BSP_Init();
 4   OSInit(); 
 5   // g_TxMbox=OSMboxCreate((void*)0); //創建全局信號-消息郵箱
6   OSTaskCreate(startup_task, (void *)0, 7           &startup_task_stk[STARTUP_TASK_STK_SIZE - 1], 8           STARTUP_TASK_PRIO);//啓動任務 9   OSTaskCreate(led2_task, (void *)0, 10           &led2_task_stk[STARTUP_TASK_STK_SIZE - 1], 11           6);//自定義任務1 12   OSTaskCreate(led3_task, (void *)0, 13           &led3_task_stk[STARTUP_TASK_STK_SIZE - 1], 14           7); //自定義任務2 15   OSStart(); 16   return 0; 17 }

4、開發一定要注意的是細節,複製需要重複利用的代碼之後,需要修改的地方一定要記得修改,比如這次在創建新任務時,用複製的方式,忘記改了led1、2、3,把程序燒進去了發現只有一個燈作用,然後去找程序的任務創建問題,結果不是,只是忘記修改io口而已。

 

 

11.07

今天主要學習ucosii信號量的使用,遇到問題整理如下:

1、在機房寫完程序,回來用自己的筆記本打開的時候,老是出現“uvision IDE 已停止工作”,上網找了許久,有說重裝系統有說重裝軟件的,但是我本身其他的工程可以打開,我覺得應該不關重裝的事,會不會是版本問題?抱着試試的心態,用高一點的版本覆蓋安裝了一下,再重新打開,可以了,真是版本的問題,orz;

2、mkd註釋亂碼問題

  由於編碼使用不統一導致別的開發環境下的文件在MDK(keil)下打開中文顯示亂碼,從mdk拷貝出來的漢字也會亂碼,解決這一問題需要進行碼制轉換,可以在打開文件前將MDK的編碼設置爲chinese2312(Edit>Configuration>Editor>Encoding),這樣就能夠正確顯示中文了,不過中文編碼下的英文是在難看,只好又換回去了。。

3、今天的任務是完成以下要求:

  在uC/OS-II至少建立任務三個任務,第一、二、三個任務優先級從高到低,分別負責控制3LED以不同的頻率閃爍。其中第三個LED燈在任務啓動後就能以1Hz的頻率閃爍,其它兩個LED是需在第三個任務的執行了510次後下才開始閃爍(要求用信號量、消息郵箱或消息隊列的方法實現),最後下載到開發板上驗證。

具體實現如下:

(1)定義信號量事件以及開闢任務堆棧:

1 OS_EVENT *LED1_SEM;
2 OS_EVENT *LED2_SEM;
3 OS_EVENT *LED3_SEM;
4 
5 static  OS_STK  startup_task_stk[STARTUP_TASK_STK_SIZE];   //開闢任務堆棧
6 static  OS_STK  led1_task_stk[LED1_TASK_STK_SIZE ];   //開闢任務堆棧
7 static  OS_STK  led2_task_stk[LED1_TASK_STK_SIZE ];   //開闢任務堆棧
8 static  OS_STK  led3_task_stk[LED1_TASK_STK_SIZE ];   //開闢任務堆棧

(2)在開始任務中建立信號量以及其他任務

 1 static void startup_task(void *p_arg) 
 2 { 
 3     systick_init();     /* Initialize the SysTick. */
 4     LED1_SEM = OSSemCreate(0);//建立信號量
 5     LED2_SEM = OSSemCreate(0);
 6 
 7   /*建立三個任務,建立一次即可,不必放在while(1)中*/
 8     OSTaskCreate(led1_task, ( void *)0, 
 9               &led1_task_stk[STARTUP_TASK_STK_SIZE - 1], 
10               5);
11     OSTaskCreate(led2_task, (void *)0, 
12               &led2_task_stk[STARTUP_TASK_STK_SIZE - 1], 
13               6);
14     OSTaskCreate(led3_task, 0, 
15               &led3_task_stk[LED1_TASK_STK_SIZE - 1], 
16               7); 
17     while(1)
18      {
19          OSTimeDlyHMSM(0,0,0,50);   //50ms釋放CPU
20      }   
21 }

(3)三個任務具體如下

 1 static void led1_task(void *p_arg)
 2 {   
 3      INT8U err;
 4      p_arg=p_arg;     
 5      while(1)
 6       {     
 7            OSSemPend(LED1_SEM,0,&err);
 8            led_on(LED1);
 9            OSTimeDlyHMSM(0,0,0,250); 
10            led_off(LED1);
11            OSTimeDlyHMSM(0,0,0,250); 
12       }
13 }
14 
15 static void led2_task(void *p_arg)
16 {   
17         INT8U err;
18         p_arg=p_arg;     
19         while(1)
20         {     
21              OSSemPend(LED2_SEM,0,&err);
22              led_on(LED2);
23              OSTimeDlyHMSM(0,0,0,125); 
24              led_off(LED2);
25              OSTimeDlyHMSM(0,0,0,125);
26         }
27 }
28 
29 static void led3_task(void *p_arg)
30 {
31         p_arg=p_arg;     
32         while(1)
33         {
34              tasktimes++;
35              led_on(LED3);
36              OSTimeDlyHMSM(0,0,0,500);  
37              led_off(LED3);
38              OSTimeDlyHMSM(0,0,0,500);     
39             
40              if(tasktimes>=5)
41                 OSSemPost(LED1_SEM);
42              if(tasktimes>=10)
43                 OSSemPost(LED2_SEM);     
44         }
45 }            

具體執行順序:雖然任務優先級1>2>3,但是因爲受 OSSemPend(LED2/1_SEM,0,&err); 限制,導致即使任務1和任務2有創建,沒有收到信號量,仍舊不能執行下面的閃爍程序。

任務三在進行判斷tasktimes之後發送信號量,任務1任務2等到任務三發送完之後執行閃爍程序。

所以實際的效果是,任務3先執行之後任務1之後任務2,但是實際上三個任務執行順序依舊是任務1-->任務2-->任務3。

 4、OSTaskCreate()與OSTaskCreateExt()創建任務的區別

  1 OSTaskCreate()函數
  2 
  3 #if OS_TASK_CREATE_EN > 0    //允許生成OSTaskCreate()函數
  4 INT8U  OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)
  5 {
  6 #if OS_CRITICAL_METHOD == 3                  //中斷函數被設定爲模式3
  7     OS_CPU_SR  cpu_sr;
  8 #endif
  9     OS_STK    *psp;                            //初始化任務堆棧指針變量,返回新的棧頂指針
 10     INT8U      err;                            //定義(獲得並定義初始化任務控制塊)是否成功
 11 
 12 
 13 #if OS_ARG_CHK_EN > 0                        //所有參數必須在指定的參數內
 14     if (prio > OS_LOWEST_PRIO) {            //檢查任務優先級是否合法
 15         return (OS_PRIO_INVALID);            //參數指定的優先級大於OS_LOWEST_PRIO
 16     }
 17 #endif
 18     OS_ENTER_CRITICAL();            //關閉中斷
 19     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { //確認優先級未被使用,即就緒態爲0
 20         OSTCBPrioTbl[prio] = (OS_TCB *)1;    //保留這個優先級,將就緒態設爲1
 21                                             
 22         OS_EXIT_CRITICAL();                //打開中斷
 23         psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0);    //初始化任務堆棧
 24         err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);        //獲得並初始化任務控制塊
 25         if (err == OS_NO_ERR) {        //任務控制初始化成功
 26             OS_ENTER_CRITICAL();    //關閉中斷
 27             OSTaskCtr++;            //任務計數器加1
 28             OS_EXIT_CRITICAL();        //打開中斷
 29             if (OSRunning == TRUE) {         //檢查是否有(某個)任務在運行
 30                 OS_Sched();                     //任務調度,最高任務優先級運行
 31             }
 32         } else {        //否則,任務初始化失敗
 33             OS_ENTER_CRITICAL();        //關閉中斷
 34             OSTCBPrioTbl[prio] = (OS_TCB *)0;        //放棄任務,設此任務就緒態爲0
 35             OS_EXIT_CRITICAL();                        //打開中斷
 36         }
 37         return (err);            //返回(獲得並定義初始化任務控制塊是否成功)
 38     }
 39     OS_EXIT_CRITICAL();            //打開中斷
 40     return (OS_PRIO_EXIST);        //返回(具有該優先級的任務已經存在)
 41 }
 42 #endif
 43 
 44 
 45 //OSTaskCreateExt()函數
 46 //與OSTaskCreate()不同的是,OSTaskCreateExt()允許用戶設置更多的細節
 47 //內容。任務的建立可以在多任務環境啓動之前,也可以在正在運行的任務中建立,但中斷處理
 48 //程序中不能建立新任務。一個任務必須爲無限循環結構,且不能有返回點。
 49 #if OS_TASK_CREATE_EXT_EN > 0                //允許生成OSTaskCreateExt()函數
 50 INT8U  OSTaskCreateExt (void   (*task)(void *pd),    //建立擴展任務(任務代碼指針)
 51                         void    *pdata,                //傳遞參數指針
 52                         OS_STK  *ptos,                //分配任務堆棧棧頂指針
 53                         INT8U    prio,                //分配任務優先級
 54                         INT16U   id,                //(未來的)優先級標識(與優先級相同)
 55                         OS_STK  *pbos,                //分配任務堆棧棧底指針
 56                         INT32U   stk_size,            //指定堆棧的容量(檢驗用)
 57                         void    *pext,                //指向用戶附加的數據域的指針
 58                         INT16U   opt)                //建立任務設定選項
 59 {
 60 #if OS_CRITICAL_METHOD == 3                  //中斷函數被設定爲模式3
 61     OS_CPU_SR  cpu_sr;
 62 #endif
 63     OS_STK    *psp;                            //初始化任務堆棧指針變量,返回新的棧頂指針
 64     INT8U      err;                            //定義(獲得定義初始化任務控制塊)是否成功
 65 
 66 
 67 #if OS_ARG_CHK_EN > 0        //所有參數必須在指定的參數內
 68     if (prio > OS_LOWEST_PRIO) {             //檢查任務優先級是否合法
 69         return (OS_PRIO_INVALID);             //參數指定的優先級大於OS_LOWEST_PRIO
 70     }
 71 #endif
 72     OS_ENTER_CRITICAL();        //關閉中斷
 73     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { //確認優先級未被使用,即就緒態爲0
 74         OSTCBPrioTbl[prio] = (OS_TCB *)1;    //保留這個優先級,將就緒態設爲0
 75                                              
 76         OS_EXIT_CRITICAL();        //打開中斷
 77 
 78         //以下兩爲1堆棧才能清0
 79         if (((opt & OS_TASK_OPT_STK_CHK) != 0x0000) ||   //檢驗任務堆棧,CHK=1
 80             ((opt & OS_TASK_OPT_STK_CLR) != 0x0000)) {   //任務建立時是否清0,CLR=1
 81             #if OS_STK_GROWTH == 1            //堆棧生長方向
 82             (void)memset(pbos, 0, stk_size * sizeof(OS_STK));        //從下向上遞增
 83             #else
 84             (void)memset(ptos, 0, stk_size * sizeof(OS_STK));        //從下向下遞減
 85             #endif
 86         }
 87 
 88         psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, opt);        //初始化任務堆棧
 89         err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt);        //獲得並初始化任務控制塊
 90         if (err == OS_NO_ERR) {    //任務控制初始化成功
 91             OS_ENTER_CRITICAL();        //關閉中斷
 92             OSTaskCtr++;                //任務計數器加1
 93             OS_EXIT_CRITICAL();            //打開中斷
 94             if (OSRunning == TRUE) {              //檢查是否有(某個)任務在運行
 95                 OS_Sched();                          //任務調度,最高任務優先級運行
 96             }
 97         } else {        //否則,任務初始化失敗
 98             OS_ENTER_CRITICAL();        //關閉中斷
 99             OSTCBPrioTbl[prio] = (OS_TCB *)0;                 //放棄任務,設此任務就緒態爲0
100             OS_EXIT_CRITICAL();            //打開中斷
101         }
102         return (err);        //返回(獲得並定義初始化任務控制塊是否成功)
103     }
104     OS_EXIT_CRITICAL();        //打開中斷
105     return (OS_PRIO_EXIST);        //具有該優先級的任務已經存在
106 }
107 #endif

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章