[FreeRTOS學(xué)習(xí)] 內(nèi)核控制

上下文切換

taskYIELD 在中斷服務(wù)程序中的等價版本為portYIELD_FROM_ISR,用于強(qiáng)制上下文切換的宏。對于Cortex-M3硬件,這個宏會引起PendSV中斷。

進(jìn)入臨界區(qū)

taskENTER_CRITICAL:用于進(jìn)入臨界區(qū)的宏。在臨界區(qū)中不會發(fā)生上下文切換。

對于Cortex-M3硬件,先禁止所有RTOS可屏蔽中斷,這可以通過向basepri 寄存器寫入configMAX_SYSCALL_INTERRUPT_PRIORITY來實現(xiàn)。basepri寄存器被設(shè)置成某個值后,所有優(yōu)先級號大于等于此值的中斷都被禁止,但若被設(shè)置為0,則不關(guān)閉任何中斷,0為默認(rèn)值。然后臨界區(qū)嵌套計數(shù)器增1。

退出臨界區(qū)

taskEXIT_CRITICAL:用于退出臨界區(qū)的宏。

對于Cortex-M3硬件,先將臨界區(qū)嵌套計數(shù)器減1,如果臨界區(qū)計數(shù)器為零,則使能所有RTOS可屏蔽中斷,這可以通過向basepri 寄存器寫入0來實現(xiàn)。

禁止可屏蔽中斷

taskDISABLE_INTERRUPTS:禁止所有RTOS可屏蔽中斷。在調(diào)用宏taskENTER_CRITICAL進(jìn)入臨界區(qū)時,也會間接調(diào)用該宏禁止所有RTOS可屏蔽中斷。

使能可屏蔽中斷宏

taskENABLE_INTERRUPTS:使能所有RTOS可屏蔽中斷。在調(diào)用宏taskEXIT_CRITICAL退出臨界區(qū)時,也會間接調(diào)用該宏使能所有RTOS可屏蔽中斷。

啟動調(diào)度器

void vTaskStartScheduler( void );

當(dāng)調(diào)用vTaskStartScheduler()后,空閑任務(wù)被自動創(chuàng)建。如果configUSE_TIMERS被設(shè)置為1,定時器后臺任務(wù)也會被創(chuàng)建。

如果vTaskStartScheduler()成功執(zhí)行,則該函數(shù)不會返回,直到有任務(wù)調(diào)用了vTaskEndScheduler()。如果因為RAM不足而無法創(chuàng)建空閑任務(wù),該函數(shù)也可能執(zhí)行失敗,并會立刻返回調(diào)用處。

停止調(diào)度器

void vTaskEndScheduler( void );

僅用于x86硬件架構(gòu)中。停止RTOS內(nèi)核系統(tǒng)節(jié)拍時鐘。所有創(chuàng)建的任務(wù)自動刪除并停止多任務(wù)調(diào)度。

掛起任務(wù)調(diào)度器

 void vTaskSuspendAll( void );

掛起調(diào)度器,但不禁止中斷。當(dāng)調(diào)度器掛起時,不會進(jìn)行上下文切換。調(diào)度器掛起后,正在執(zhí)行的任務(wù)會一直繼續(xù)執(zhí)行,內(nèi)核不再調(diào)度(意味著當(dāng)前任務(wù)不會被切換出去),直到該任務(wù)調(diào)用了xTaskResumeAll ()函數(shù)。

內(nèi)核調(diào)度器掛起期間,那些可以引起上下文切換的API函數(shù)(如vTaskDelayUntil()、xQueueSend()等)決不可使用。

恢復(fù)被掛起的調(diào)度器

BaseType_t xTaskResumeAll( void );

恢復(fù)因調(diào)用vTaskSuspendAll()函數(shù)而掛起的實時內(nèi)核調(diào)度器。xTaskResumeAll()僅恢復(fù)調(diào)度器,它不會恢復(fù)那些被vTaskSuspend()函數(shù)掛起的任務(wù)。

voidvTask1( voidvoid * pvParameters )  
{  
    for( ;; )  
    {  
        /* 任務(wù)代碼寫在這里 */  
  
        /* ... */  
  
        /* 有些時候,某個任務(wù)希望可以連續(xù)長時間的運(yùn)行,但這時不能使用taskENTER_CRITICAL ()/taskEXIT_CRITICAL ()的方法,這樣會屏蔽掉中斷,引起中斷丟失,包括系統(tǒng)節(jié)拍時鐘??梢允褂胿TaskSuspendAll ()停止RTOS內(nèi)核調(diào)度:*/  
        xTaskSuspendAll ();  
  
        /* 執(zhí)行操作代碼放在這里。這樣不用進(jìn)入臨界區(qū)就可以連續(xù)長時間執(zhí)行了。在這期間,中斷仍然會得到響應(yīng),RTOS內(nèi)核系統(tǒng)節(jié)拍時鐘也會繼續(xù)保持運(yùn)作 */  
  
        /* ... */  
  
        /* 操作結(jié)束,重新啟動RTOS內(nèi)核 。我們想強(qiáng)制進(jìn)行一次上下文切換,但是如果恢復(fù)調(diào)度器的時候已經(jīng)執(zhí)行了上下文切換,再執(zhí)行一次是沒有意義的,因此會進(jìn)行一次判斷。*/  
        if( !xTaskResumeAll () )  
        {  
             taskYIELD ();  
        }  
    }  
}  

調(diào)整系統(tǒng)節(jié)拍

 void vTaskStepTick( TickType_txTicksToJump );

如果RTOS使能tickless空閑功能,每當(dāng)只有空閑任務(wù)被執(zhí)行時,系統(tǒng)節(jié)拍時鐘中斷將會停止,微控制器進(jìn)入低功耗模式。當(dāng)微控制器退出低功耗后,系統(tǒng)節(jié)拍計數(shù)器必須被調(diào)整,將進(jìn)入低功耗的時間彌補(bǔ)上。

如果FreeRTOS移植文件中定義了宏portSUPPRESS_TICKS_AND_SLEEP()實體,則函數(shù)vTaskStepTick用于在這個宏portSUPPRESS_TICKS_AND_SLEEP()實體內(nèi)部調(diào)整系統(tǒng)節(jié)拍計數(shù)器。函數(shù)vTaskStepTick是一個全局函數(shù),所以也可以在宏portSUPPRESS_TICKS_AND_SLEEP()實體中重寫該函數(shù)。

宏configUSE_TICKLESS_IDLE必須設(shè)置為1,此函數(shù)才有效。

/* 首先定義宏portSUPPRESS_TICKS_AND_SLEEP()。宏參數(shù)指定要進(jìn)入低功耗(睡眠)的時間,單位是系統(tǒng)節(jié)拍周期。*/  
#define portSUPPRESS_TICKS_AND_SLEEP( xIdleTime ) vApplicationSleep( xIdleTime )  
   
/* 定義被宏portSUPPRESS_TICKS_AND_SLEEP()調(diào)用的函數(shù) */  
void vApplicationSleep(TickType_t xExpectedIdleTime )  
{  
    unsigned long ulLowPowerTimeBeforeSleep,ulLowPowerTimeAfterSleep;  
   
    /* 從時鐘源獲取當(dāng)前時間,當(dāng)微控制器進(jìn)入低功耗的時候,這個時鐘源必須在運(yùn)行 */  
    ulLowPowerTimeBeforeSleep =ulGetExternalTime();  
   
    /*停止系統(tǒng)節(jié)拍時鐘中斷。*/  
    prvStopTickInterruptTimer();  
   
    /* 配置一個中斷,當(dāng)指定的睡眠時間達(dá)到后,將處理器從低功耗中喚醒。這個中斷源必須在微控制器進(jìn)入低功耗時也可以工作。*/  
    vSetWakeTimeInterrupt( xExpectedIdleTime );  
   
    /*進(jìn)入低功耗 */  
    prvSleep();  
   
    /* 確定微控制器進(jìn)入低功耗模式持續(xù)的真正時間。因為其它中斷也可能使得微處理器退出低功耗模式。注意:在調(diào)用宏portSUPPRESS_TICKS_AND_SLEEP()之前,調(diào)度器應(yīng)該被掛起,portSUPPRESS_TICKS_AND_SLEEP()返回后,再將調(diào)度器恢復(fù)。因此,這個函數(shù)未完成前,不會執(zhí)行其它任務(wù)。*/  
    ulLowPowerTimeAfterSleep =ulGetExternalTime();  
          
    /*調(diào)整內(nèi)核系統(tǒng)節(jié)拍計數(shù)器。*/  
    vTaskStepTick( ulLowPowerTimeAfterSleep –ulLowPowerTimeBeforeSleep );  
   
    /*重新啟動系統(tǒng)節(jié)拍時鐘中斷。*/  
    prvStartTickInterruptTimer();  
}  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容