1. 程式人生 > >FreeRTOS系列第13篇---FreeRTOS內核控制

FreeRTOS系列第13篇---FreeRTOS內核控制

使用方法 exp ole dfa pow cati 返回 有意 ng-

內核控制的一些功能須要移植層提供,為了方便移植。這些API函數用宏來實現,比方上下文切換、進入和退出臨界區、禁止和使能可屏蔽中斷。內核控制函數還包含啟動和停止調度器、掛起和恢復調度器以及用於低功耗模式的調整系統節拍函數。

1.強制上下文切換宏

taskYIELD:用於強制上下文切換的宏。

在中斷服務程序中的等價版本號為portYIELD_FROM_ISR。這也是個宏,事實上現取決於移植層。

用於上下文切換的實際代碼由移植層提供。對於Cortex-M3硬件。這個宏會引起PendSV中斷。

2.進入臨界區宏

taskENTER_CRITICAL:用於進入臨界區的宏。在臨界區中不會發生上下文切換。

進入臨界區的實際代碼由移植層提供,對於Cortex-M3硬件,先禁止全部RTOS可屏蔽中斷,這能夠通過向basepri 寄存器寫入configMAX_SYSCALL_INTERRUPT_PRIORITY來實現。basepri寄存器被設置成某個值後,全部優先級號大於等於此值的中斷都被禁止。但若被設置為0。則不關閉不論什麽中斷。0為默認值。然後臨界區嵌套計數器增1。

3.退出臨界區宏

taskEXIT_CRITICAL:用於退出臨界區的宏。

退出臨界區的實際代碼有移植層提供。對於Cortex-M3硬件。先將臨界區嵌套計數器減1。假設臨界區計數器為零,則使能全部RTOS可屏蔽中斷。這能夠通過向

basepri 寄存器寫入0來實現。

4.禁止可屏蔽中斷宏

taskDISABLE_INTERRUPTS:禁止全部RTOS可屏蔽中斷。

在調用宏taskENTER_CRITICAL進入臨界區時,也會間接調用該宏禁止全部RTOS可屏蔽中斷。

5.使能可屏蔽中斷宏

taskENABLE_INTERRUPTS:使能全部RTOS可屏蔽中斷。在調用宏taskEXIT_CRITICAL退出臨界區時,也會間接調用該宏使能全部RTOS可屏蔽中斷。

6.啟動調度器

6.1函數描寫敘述

void vTaskStartScheduler( void );

啟動RTOS調度器。之後RTOS內核控制哪個任務運行以及何時運行。

當調用vTaskStartScheduler()後,空暇任務被自己主動創建。假設configUSE_TIMERS被設置為1,定時器後臺任務也會被創建。

假設vTaskStartScheduler()成功運行,則該函數不會返回,直到有任務調用了vTaskEndScheduler()。假設由於RAM不足而無法創建空暇任務,該函數也可能運行失敗。並會立馬返回調用處。

7.停止調度器

7.1函數描寫敘述

void vTaskEndScheduler( void );

僅用於x86硬件架構中。

停止RTOS內核系統節拍時鐘。全部創建的任務自己主動刪除並停止多任務調度。

8.掛起調度器

8.1函數描寫敘述

void vTaskSuspendAll( void );

掛起調度器。但不禁止中斷。當調度器掛起時,不會進行上下文切換。

調度器掛起後。正在運行的任務會一直繼續運行,內核不再調度(意味著當前任務不會被切換出去),直到該任務調用了xTaskResumeAll ()函數。

內核調度器掛起期間,那些能夠引起上下文切換的API函數(如vTaskDelayUntil()、xQueueSend()等)決不可使用。

9.恢復被掛起的調度器

9.1函數描寫敘述

BaseType_t xTaskResumeAll( void );

恢復因調用vTaskSuspendAll()函數而掛起的實時內核調度器。xTaskResumeAll()僅恢復調度器,它不會恢復那些被vTaskSuspend()函數掛起的任務。

9.2返回值

返回pdTRUE 表示恢復調度器引起了一次上下文切換,否則,返回pdFALSE。

9.3使用方法舉例

 voidvTask1( void * pvParameters )
 {
     for( ;; )
     {
         /* 任務代碼寫在這裏 */
 
         /* ... */
 
         /* 有些時候。某個任務希望能夠連續長時間的運行,但這時不能使用taskENTER_CRITICAL ()/taskEXIT_CRITICAL ()的方法,這樣會屏蔽掉中斷,引起中斷丟失。包含系統節拍時鐘。

能夠使用vTaskSuspendAll ()停止RTOS內核調度:*/ xTaskSuspendAll (); /* 運行操作代碼放在這裏。

這樣不用進入臨界區就能夠連續長時間運行了。在這期間。中斷仍然會得到響應,RTOS內核系統節拍時鐘也會繼續保持運作 */ /* ... */ /* 操作結束。又一次啟動RTOS內核 。我們想強制進行一次上下文切換。可是假設恢復調度器的時候已經運行了上下文切換。再運行一次是沒有意義的。因此會進行一次推斷。

*/ if( !xTaskResumeAll () ) { taskYIELD (); } } }

10.調整系統節拍

10.1函數描寫敘述

void vTaskStepTick( TickType_txTicksToJump );

假設RTOS使能tickless空暇功能,每當僅僅有空暇任務被運行時,系統節拍時鐘中斷將會停止,微控制器進入低功耗模式。

當微控制器退出低功耗後。系統節拍計數器必須被調整,將進入低功耗的時間彌補上。

假設FreeRTOS移植文件裏定義了宏portSUPPRESS_TICKS_AND_SLEEP()實體,則函數vTaskStepTick用於在這個宏portSUPPRESS_TICKS_AND_SLEEP()實體內部調整系統節拍計數器。函數vTaskStepTick是一個全局函數,所以也能夠在宏portSUPPRESS_TICKS_AND_SLEEP()實體中重寫該函數。

在文件FreeRTOSConfig.h中,宏configUSE_TICKLESS_IDLE必須設置為1。此函數才有效。

10.2參數描寫敘述

  • xTickToJump:時間值,單位是系統節拍周期,表示微處理器進入低功耗的時間,函數依據這個值來調整系統節拍計數器的值。

10.3使用方法舉例

/* 首先定義宏portSUPPRESS_TICKS_AND_SLEEP()。宏參數指定要進入低功耗(睡眠)的時間,單位是系統節拍周期。*/
#defineportSUPPRESS_TICKS_AND_SLEEP( xIdleTime ) vApplicationSleep( xIdleTime )
 
/* 定義被宏portSUPPRESS_TICKS_AND_SLEEP()調用的函數 */
void vApplicationSleep(TickType_t xExpectedIdleTime )
{
    unsigned long ulLowPowerTimeBeforeSleep,ulLowPowerTimeAfterSleep;
 
    /* 從時鐘源獲取當前時間,當微控制器進入低功耗的時候,這個時鐘源必須在運行 */
    ulLowPowerTimeBeforeSleep =ulGetExternalTime();
 
    /*停止系統節拍時鐘中斷。*/
    prvStopTickInterruptTimer();
 
    /* 配置一個中斷,當指定的睡眠時間達到後,將處理器從低功耗中喚醒。這個中斷源必須在微控制器進入低功耗時也能夠工作。*/
    vSetWakeTimeInterrupt( xExpectedIdleTime );
 
    /*進入低功耗 */
    prvSleep();
 
    /* 確定微控制器進入低功耗模式持續的真正時間。由於其他中斷也可能使得微處理器退出低功耗模式。

註意:在調用宏portSUPPRESS_TICKS_AND_SLEEP()之前。調度器應該被掛起,portSUPPRESS_TICKS_AND_SLEEP()返回後,再將調度器恢復。因此。這個函數未完畢前。不會運行其他任務。

*/ ulLowPowerTimeAfterSleep =ulGetExternalTime(); /*調整內核系統節拍計數器。*/ vTaskStepTick( ulLowPowerTimeAfterSleep –ulLowPowerTimeBeforeSleep ); /*又一次啟動系統節拍時鐘中斷。*/ prvStartTickInterruptTimer(); }



FreeRTOS系列第13篇---FreeRTOS內核控制