uCOS-II函數解析

時間管理服務函數是以系統節拍爲處理單位的,實際的時間與希望的時間是有誤差的,最壞的情況下誤差接近一個系統節拍。因此時間管理服務函數只能用在對時間精度要求不高的場合,或者時間間隔較長的場合。


1. void  OSSchedLock(void);

void  OSSchedLock (void)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0;
#endif
    if (OSRunning == OS_TRUE) {                  /* Make sure multitasking is running                  */
        OS_ENTER_CRITICAL();
        if (OSIntNesting == 0) {                 /* Can't call from an ISR                             */
            if (OSLockNesting < 255u) {          /* Prevent OSLockNesting from wrapping back to 0      */
                OSLockNesting++;                 /* Increment lock nesting level                       */
            }
        }
        OS_EXIT_CRITICAL();
    }
}

這個函數又叫上鎖函數,如果在一個任務裏面調用了上鎖函數,那麼OSSched()這個任務切換函數就不會執行也就是說不會進任務調度。

調用OSSchedLock()以後,用戶的應用程序不得使用任何能將現行任務掛起的系統調用。也就是說,用戶程序不得調用OSMboxPend()、OSQPend()、OSSemPend()、OSTaskSuspend(OS_PR1O_SELF)、OSTimeDly()或OSTimeDlyHMSM(),直到OSLockNesting回零爲止因爲調度器上了鎖,用戶就鎖住了系統,任何其它任務都不能運行。

但是上鎖了任務是可以中斷,若任務遇到中斷,則中斷函數的執行會爲OSIntNesting變量加1,當中斷返回時又要判斷OSLockNesting是否爲0,如果不爲0說明系統仍被鎖,直接退出中斷。如果OSLockNesting爲0說明系統未被鎖,CPU進入任務就緒表查找優先級最高的任務。所以上鎖函數執行後,CPU一直處於當前任務與中斷服務函數之間的運行,直到解鎖函數將OSLockNesting和OSIntNesting的值減到0時,方可解除系統鎖定。

OSSchedUnlock() 取消函數上鎖。



2.void  OSTimeDly (INT16U ticks);

void  OSTimeDly (INT16U ticks)
{
    INT8U      y;
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0;
#endif
    if (OSIntNesting > 0) {                      /* See if trying to call from an ISR                  */
        return;
    }
    if (ticks > 0) {                             /* 0 means no delay!                                  */
        OS_ENTER_CRITICAL();
        y            =  OSTCBCur->OSTCBY;        /* Delay current task                                 */
        OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;
        if (OSRdyTbl[y] == 0) {
            OSRdyGrp &= ~OSTCBCur->OSTCBBitY;         /*取消當前任務的就緒狀態
        }
        OSTCBCur->OSTCBDly = ticks;              /* 延時節拍數存入任務控制塊TCB                               */
        OS_EXIT_CRITICAL();
        OS_Sched();                              /* 調度函數                           */
    }
}

      將一個任務延時若干個時鐘節拍。如果延時時間大於0,系統將立即進行任務調度。延時時間的長度可從0到65535個時鐘節拍。延時時間0表示不進行延時,函數將立即返回調用者。延時的具體時間依賴於系統每秒鐘有多少時鐘節拍(由文件OS_CFG.H中的常量OS_TICKS_PER_SEC設定): 

#define OS_TICKS_PER_SEC       1000  

   調用該函數會使uCOS-II進行一次任務調度,並且執行下一個優先級最高的就緒態任務。任務調用OSTimeDly()後,一旦規定的時間期滿或者有其它的任務通過調用OSTimeDlyResume()取消了延時,它就會馬上進入就緒狀態。注意,只有當該任務在所有就緒任務中具有最高的優先級時,它纔會立即運行。





3.INT8U  OSTimeDlyHMSM (INT8U hours, INT8U minutes, INT8U seconds, INT16U ms);

這個函數是以小時(H)、分(M)、秒(S)和毫秒(m)四個參數來定義延時時間的,函數在內部把這些參數轉換爲時鐘節拍,再通過單次或多次調用OSTimeDly()進行延時和任務調度,所以延時原理和調用延時函數OSTimeDly()是一樣的。



4.INT8U  OS_TCBInit(INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt);

任務控制塊初始化  

描述:這個函數是uCOS-II內部函數,在建立任務時調用的初始化任務控制塊OS_TCB函數,含7個參數,查看OSTaskCreate()和OSTaskCreateExt()  

初始化任務控制塊TCB(優先級指針,堆棧指針,棧底指針,任務標誌符,堆棧容量,擴展指針,選擇項)  

   INT8U  OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)  

    {  

     #if OS_CRITICAL_METHOD == 3                                //中斷函數被設定爲模式3 

      OS_CPU_SR  cpu_sr;  

  1. #endif      
  2.     OS_TCB    *ptcb;                                      //定義一個PCB變量  
  3.   
  4.   
  5.     OS_ENTER_CRITICAL();                                  //關閉中斷  
  6.     ptcb = OSTCBFreeList;                                 //分配一個空任務控制塊給ptcb  
  7.     if (ptcb != (OS_TCB *)0) {                            //如果緩衝池有空餘TCB,這個TCB被初始化  
  8.         OSTCBFreeList        = ptcb->OSTCBNext;           //指向TCB的雙向鏈接的後鏈接  
  9.         OS_EXIT_CRITICAL();                               //打開中斷  
  10.         ptcb->OSTCBStkPtr    = ptos;                       //指向當前TCB的棧頂指針(輸入的數據)  
  11.         ptcb->OSTCBPrio      = (INT8U)prio;                //保存當前TCB的優先級別(輸入的數據)  
  12.         ptcb->OSTCBStat      = OS_STAT_RDY;                //設定當前TCB的狀態字(內容爲(準備完畢))  
  13.         ptcb->OSTCBDly       = 0;                          //允許任務等待的最大字節節拍爲0  
  14.   
  15. #if OS_TASK_CREATE_EXT_EN > 0                               //允許生成OSTaskCreateExt()函數  
  16.         ptcb->OSTCBExtPtr    = pext;                       //指向用戶定義的任務控制塊(擴展指針)  
  17.         ptcb->OSTCBStkSize   = stk_size;                   //設定堆棧的容量  
  18.         ptcb->OSTCBStkBottom = pbos;                       //指向堆棧棧底的指針  
  19.         ptcb->OSTCBOpt       = opt;                        //保存OS_TCB的選擇項  
  20.         ptcb->OSTCBId        = id;                         //保存任務標誌符  
  21. #else   //否則使用舊的參數  
  22.         pext                 = pext;                       //擴展指針  
  23.         stk_size             = stk_size;                   //堆棧的容量  
  24.         pbos                 = pbos;                       //棧底的指針  
  25.         opt                  = opt;                        //選擇項  
  26.         id                   = id;                         //任務標誌符  
  27. #endif  
  28.   
  29. #if OS_TASK_DEL_EN > 0           //允許生成OSTaskDel()函數代碼函數  
  30.         ptcb->OSTCBDelReq    = OS_NO_ERR;                    //如果可以刪除任務本身,可以從每個OS_TCB中節省出一個布爾量  
  31. #endif  
  32.   
  33.         ptcb->OSTCBY         = prio >> 3;                  //對一些參數提前運算,爲了節省CPU的操作事件  
  34.         ptcb->OSTCBBitY      = OSMapTbl[ptcb->OSTCBY];  
  35.         ptcb->OSTCBX         = prio & 0x07;  
  36.         ptcb->OSTCBBitX      = OSMapTbl[ptcb->OSTCBX];  
  37.   
  38. #if OS_EVENT_EN > 0                  //如果不打算在應用程序中使用各類事件  
  39.         ptcb->OSTCBEventPtr  = (OS_EVENT *)0;              //OS_TCB中OSTCBEventPtr就不會出現  
  40. #endif  
  41.   
  42. //針對的事件爲信號量,互斥型信號量,消息郵箱,消息隊列,當滿足版本大於2.51且事件標誌允許且有最大事件標誌及允許刪除任務  
  43. #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)  
  44.         ptcb->OSTCBFlagNode  = (OS_FLAG_NODE *)0;          //則向事件標誌節點的指針被初始化爲空指針  
  45. #endif  
  46.   
  47. #if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))  
  48.         ptcb->OSTCBMsg       = (void *)0;                  //滿足以上條件,指向傳遞給任務的消息指針爲0空指針  
  49. #endif  
  50.   
  51. #if OS_VERSION >= 204            //如果版本大於2.04  
  52.         OSTCBInitHook(ptcb);                              //允許使用OSTCBInitHook(ptcb)函數,可對其加代碼  
  53. #endif              //主要增加OS_TCB擴展,浮點運算,MMU寄存器,與任務相關內容,調用此程序時中斷開着的  
  54.   
  55.         OSTaskCreateHook(ptcb);                            //調用戶建立任務鉤子程序  
  56.           
  57.         OS_ENTER_CRITICAL();  
  58.         OSTCBPrioTbl[prio] = ptcb;  
  59.         ptcb->OSTCBNext    = OSTCBList;                    //鏈接到任務控制塊鏈接串  
  60.         ptcb->OSTCBPrev    = (OS_TCB *)0;  
  61.         if (OSTCBList != (OS_TCB *)0) {  
  62.             OSTCBList->OSTCBPrev = ptcb;  
  63.         }  
  64.         OSTCBList               = ptcb;                   //讓該任務進入就緒表  
  65.         OSRdyGrp               |= ptcb->OSTCBBitY;         /* Make task ready to run                   */  
  66.         OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;  
  67.         OS_EXIT_CRITICAL();             //打開中斷  
  68.         return (OS_NO_ERR);             //調用成功,最後讓此函數返回到調用函數[OSTaskCreate()或OSTaskCreateExt()函數],  
  69.                                         //返回值表示分配到任務控塊,並初始化了  
  70.     }  
  71.     OS_EXIT_CRITICAL();                 //打開中斷  
  72.     return (OS_NO_MORE_TCB);            //沒有更多的任務控制塊被分配,將無法創建新的任務  


5.INT8U  OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio);


  1. //建立一個新任務  
  2. #if OS_TASK_CREATE_EN > 0                //允許生成OSTaskCreate()函數  
  3. INT8U  OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)  
  4. {  
  5. #if OS_CRITICAL_METHOD == 3                  //中斷函數被設定爲模式3  
  6.     OS_CPU_SR  cpu_sr;  
  7. #endif  
  8.     OS_STK    *psp;                         //初始化任務堆棧指針變量,返回新的棧頂指針  
  9.     INT8U      err;                         //定義(獲得並定義初始化任務控制塊)是否成功  
  10.   
  11.   
  12. #if OS_ARG_CHK_EN > 0                        //所有參數必須在指定的參數內  
  13.     if (prio > OS_LOWEST_PRIO) {            //檢查任務優先級是否合法  
  14.         return (OS_PRIO_INVALID);           //參數指定的優先級大於OS_LOWEST_PRIO  
  15.     }  
  16. #endif  
  17.     OS_ENTER_CRITICAL();            //關閉中斷  
  18.     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { //確認優先級未被使用,即就緒態爲0  
  19.         OSTCBPrioTbl[prio] = (OS_TCB *)1;    //保留這個優先級,將就緒態設爲1  
  20.                                               
  21.         OS_EXIT_CRITICAL();             //打開中斷  
  22.         psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0);    //初始化任務堆棧  
  23.         err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);       //獲得並初始化任務控制塊  
  24.         if (err == OS_NO_ERR) {     //任務控制初始化成功  
  25.             OS_ENTER_CRITICAL();    //關閉中斷  
  26.             OSTaskCtr++;            //任務計數器加1  
  27.             OS_EXIT_CRITICAL();     //打開中斷  
  28.             if (OSRunning == TRUE) {         //檢查是否有(某個)任務在運行  
  29.                 OS_Sched();                  //任務調度,最高任務優先級運行  
  30.             }  
  31.         } else {        //否則,任務初始化失敗  
  32.             OS_ENTER_CRITICAL();        //關閉中斷  
  33.             OSTCBPrioTbl[prio] = (OS_TCB *)0;       //放棄任務,設此任務就緒態爲0  
  34.             OS_EXIT_CRITICAL();                     //打開中斷  
  35.         }  
  36.         return (err);           //返回(獲得並定義初始化任務控制塊是否成功)  
  37.     }  
  38.     OS_EXIT_CRITICAL();         //打開中斷  
  39.     return (OS_PRIO_EXIST);     //返回(具有該優先級的任務已經存在)  
  40. }  
  41. #endif  

6.static  void  OS_InitTaskStat (void) ;

  1. //創建統計任務  
  2. #if OS_TASK_STAT_EN > 0  
  3. static  void  OS_InitTaskStat (void)   
  4. {  
  5. #if OS_TASK_CREATE_EXT_EN > 0        //允許生成OSTaskCreateExt()函數  
  6.     #if OS_STK_GROWTH == 1          //堆棧生長方向向下  
  7.     (void)OSTaskCreateExt(OS_TaskStat,                                 //建立擴展任務;產生一個統計任務  
  8.       (void *)0,                                   //沒有(傳遞參數指針)  
  9.       &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],   //分配任務堆棧棧頂指針  
  10.       OS_STAT_PRIO,                                //分配任務優先級  
  11.       OS_TASK_STAT_ID,                             //(未來的)優先級標識(與優先級相同)  
  12.       &OSTaskStatStk[0],                           //分配任務堆棧棧底指針  
  13.        OS_TASK_STAT_STK_SIZE,                       //指定堆棧的容量(檢驗用)  
  14.       (void *)0,                                   //沒有(指向用戶附加的數據域的指針)  
  15.      OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */  
  16.     #else                                                             //建立擴展任務;堆棧生長方向向上  
  17.     (void)OSTaskCreateExt(OS_TaskStat,                                //產生一個統計任務  
  18.        (void *)0,                                  //沒有(傳遞參數指針)  
  19.        &OSTaskStatStk[0],                          //分配任務堆棧棧底指針  
  20.        OS_STAT_PRIO,                               //分配任務優先級  
  21.        OS_TASK_STAT_ID,                            //(未來的)優先級標識(與優先級相同)  
  22.        &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],  //分配任務堆棧棧頂指針  
  23.        OS_TASK_STAT_STK_SIZE,                      //指定堆棧的容量(檢驗用)  
  24.        (void *)0,                                  //沒有(指向用戶附加的數據域的指針)  
  25.         OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */  
  26.     #endif  
  27. #else                   //否則只能生成OSTaskCreate()函數  
  28.     #if OS_STK_GROWTH == 1          //堆棧生長方向向下  
  29.     (void)OSTaskCreate(OS_TaskStat,     //產生一個統計任務  
  30.                        (void *)0,                                      //沒有(傳遞參數指針)  
  31.                        &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],      //分配任務堆棧棧頂指針  
  32.                        OS_STAT_PRIO);                                  //分配任務優先級  
  33.     #else               //否則堆棧生長方向向上  
  34.     (void)OSTaskCreate(OS_TaskStat,     //產生一個統計任務  
  35.                        (void *)0,                                      //沒有(傳遞參數指針)  
  36.                        &OSTaskStatStk[0],                              //分配任務堆棧棧底指針  
  37.                        OS_STAT_PRIO);                                  //分配任務優先級  
  38.     #endif  
  39. #endif  
  40. }  
  41. #endif  

7.static  void  OS_InitTCBList (void);


  1. //初始化空閒TCB鏈表  
  2. static  void  OS_InitTCBList (void)  
  3. {  
  4.     INT8U    i;  
  5.     OS_TCB  *ptcb1;  
  6.     OS_TCB  *ptcb2;  
  7.   
  8.   
  9.     OSTCBList     = (OS_TCB *)0;                                 //任務控制塊鏈接表的指針清0  
  10.     for (i = 0; i < (OS_LOWEST_PRIO + 1); i++) {                   
  11.         OSTCBPrioTbl[i] = (OS_TCB *)0;        //清除所有的優先級控制塊優先級列表  
  12.     }  
  13.     ptcb1 = &OSTCBTbl[0];    //查找任務控制塊列表(0)的對應地址  
  14.     ptcb2 = &OSTCBTbl[1];    //查找任務控制塊列表(1)的對應地址  
  15.     for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) {    
  16.         ptcb1->OSTCBNext = ptcb2;//釋放所有的任務控制塊列表  
  17.         ptcb1++;  
  18.         ptcb2++;  
  19.     }  
  20.     ptcb1->OSTCBNext = (OS_TCB *)0;             //將最後的任務塊雙向鏈接表的後鏈接爲0  
  21.     OSTCBFreeList    = &OSTCBTbl[0];   //空任務控制塊地址爲當前任務控制塊列表的首地址  



























































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