1. 程式人生 > >ucosIII 中斷、臨界區與時間管理

ucosIII 中斷、臨界區與時間管理

本文內容簡介
講述了進入和退出中斷的方法
臨界區的介紹以及延時函式,取消延時函式和獲取系統時間
ucosIII中斷

中斷:應內部或外部非同步事件的請求中止當前任務,而去處理非同步事件所要求的任務的過程叫做中斷。

void USART1_IRQHandler(void)
{
       OSIntEnter();
      //中斷服務程式
      OSIntExit();
}  
進入中斷
void  OSIntEnter (void)
{
      if (OSRunning != OS_STATE_OS_RUNNING) {//用於確定系統是否正常執行
return } if (OSIntNestingCtr >= (OS_NESTING_CTR)250u) { return; } OSIntNestingCtr++;//中斷巢狀的層數 }

OSIntNestingCtr來記錄中斷巢狀次數,UCOSIII最多支援250級的中斷巢狀。退出中斷服務函式時要呼叫函式OSIntExit()。

退出中斷

退出函式內部步驟如下:
1.系統是否執行。不符合則退出
2.關閉全域性中斷
3.中斷巢狀次數和任務切換次數記錄
4.進行中斷級任務切換

void  OSIntExit (void)
{
    CPU_SR_ALLOC();//巨集定義的CPU_SR
    if (OSRunning != OS_STATE_OS_RUNNING) {                 /* Has the OS started?                                    */
        return;                                             /* No                                                     */
    }
    /*關閉全域性中斷,包括關閉滴答定時器中斷*/
CPU_INT_DIS(); if (OSIntNestingCtr == (OS_NESTING_CTR)0) { /* Prevent OSIntNestingCtr from wrapping */ CPU_INT_EN(); return; } OSIntNestingCtr--;//中斷巢狀次數 if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* ISRs still nested? */ CPU_INT_EN(); /* Yes */ return; } /*OSSchedLockNestingCtr 排程器是否加鎖的標誌*/ if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Scheduler still locked? */ CPU_INT_EN(); /* Yes */ return; } /*獲得最高優先順序的任務*/ OSPrioHighRdy = OS_PrioGetHighest(); /* Find highest priority */ OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr; /* Get highest priority task ready-to-run */ if (OSTCBHighRdyPtr == OSTCBCurPtr) { /* Current task still the highest priority? */ CPU_INT_EN(); /* Yes */ return; } #if OS_CFG_TASK_PROFILE_EN > 0u OSTCBHighRdyPtr->CtxSwCtr++; /* Inc. # of context switches for this new task */ #endif OSTaskCtxSwCtr++; //任務切換的次數 /* Keep track of the total number of ctx switches */ #if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u) OS_TLS_TaskSw(); #endif /*中斷級任務排程*/ OSIntCtxSw(); /* Perform interrupt level ctx switch */ CPU_INT_EN(); }
臨界區
  1. 臨界段程式碼也叫做臨界區,是指那些必須完整連續執行,不可被打斷的程式碼段。當訪問這些臨界段程式碼的時候需要對這些臨界段程式碼進行保護

  2. 巨集OS_CFG_ISR_POST_DEFERRED_EN
    0:UCOSIII使用關中斷的方式來保護臨界段程式碼
    1:採用給排程器上鎖的方式來保護臨界段程式碼。

  3. UCOSIII定義了一個進入臨界段程式碼的巨集OS_CRITICAL_ENTER(),定義了兩個退出臨界段程式碼的巨集OS_CRITICAL_EXITOS_CRITICAL_EXIT_NO_SCHED()

時間管理
任務延時
  • UCOSIII中的任務是一個無限迴圈並且還是一個搶佔式核心,為了使高優先順序的任務不至於獨佔CPU,可以給其他優先順序較低任務獲取CPU使用權的機會,UCOSIII中除空閒任務外的所有任務必須在合適的位置呼叫系統提供的延時函式或者任務排程函式,讓當前的任務暫停執行一段時間並進行一個任務切換。

  • 延時函式有兩種,OSTimeDly()—指定節拍數
    和OSTimeDlyHMSM()—引數直觀。

  • OSTimeDly()函式有三種工作模式:相對模式、週期模式和絕對模式。
    OSTimeDlyHMSM()函式僅在相對模式下工作。
取消任務延時

延時任務任務可通過在其他任務中呼叫函式OSTimeDlyResume()取消延時而進入就緒狀態,此函式最後會引發一次任務排程。

獲取和設定系統時間
  • UCOSIII定義了一個CPU_INT32U型別的全域性變數OSTickCtr來記錄系統時鐘節拍數,在呼叫OSInit()時被初始化為0,以後每發生1個時鐘節拍,OSTickCtr加1。
  • OSTimeSet()允許使用者改變當前時鐘節拍計數器的值,慎用!!!!!
  • OSTimeGet()用來獲取動遷時鐘節拍計數器的值。