FreeRTOS實(shí)時(shí)操作系統(tǒng)的內(nèi)核控制示例解析
前言
內(nèi)核控制的一些功能需要移植層提供,為了方便移植,這些API函數(shù)用宏來(lái)實(shí)現(xiàn),比如上下文切換、進(jìn)入和退出臨界區(qū)、禁止和使能可屏蔽中斷。內(nèi)核控制函數(shù)還包括啟動(dòng)和停止調(diào)度器、掛起和恢復(fù)調(diào)度器以及用于低功耗模式的調(diào)整系統(tǒng)節(jié)拍函數(shù)。
1.強(qiáng)制上下文切換宏
taskYIELD:用于強(qiáng)制上下文切換的宏。在中斷服務(wù)程序中的等價(jià)版本為portYIELD_FROM_ISR,這也是個(gè)宏,其實(shí)現(xiàn)取決于移植層。
用于上下文切換的實(shí)際代碼由移植層提供。對(duì)于Cortex-M3硬件,這個(gè)宏會(huì)引起PendSV中斷。
2.進(jìn)入臨界區(qū)宏
taskENTER_CRITICAL:用于進(jìn)入臨界區(qū)的宏。在臨界區(qū)中不會(huì)發(fā)生上下文切換。
進(jìn)入臨界區(qū)的實(shí)際代碼由移植層提供,對(duì)于Cortex-M3硬件,先禁止所有RTOS可屏蔽中斷,這可以通過向basepri 寄存器寫入configMAX_SYSCALL_INTERRUPT_PRIORITY來(lái)實(shí)現(xiàn)。
basepri寄存器被設(shè)置成某個(gè)值后,所有優(yōu)先級(jí)號(hào)大于等于此值的中斷都被禁止,但若被設(shè)置為0,則不關(guān)閉任何中斷,0為默認(rèn)值。然后臨界區(qū)嵌套計(jì)數(shù)器增1。
3.退出臨界區(qū)宏
taskEXIT_CRITICAL:用于退出臨界區(qū)的宏。
退出臨界區(qū)的實(shí)際代碼有移植層提供,對(duì)于Cortex-M3硬件,先將臨界區(qū)嵌套計(jì)數(shù)器減1,如果臨界區(qū)計(jì)數(shù)器為零,則使能所有RTOS可屏蔽中斷,這可以通過向basepri 寄存器寫入0來(lái)實(shí)現(xiàn)。
4.禁止可屏蔽中斷宏
taskDISABLE_INTERRUPTS:禁止所有RTOS可屏蔽中斷。
在調(diào)用宏taskENTER_CRITICAL進(jìn)入臨界區(qū)時(shí),也會(huì)間接調(diào)用該宏禁止所有RTOS可屏蔽中斷。
5.使能可屏蔽中斷宏
taskENABLE_INTERRUPTS:使能所有RTOS可屏蔽中斷。
在調(diào)用宏taskEXIT_CRITICAL退出臨界區(qū)時(shí),也會(huì)間接調(diào)用該宏使能所有RTOS可屏蔽中斷。
6.啟動(dòng)調(diào)度器
6.1函數(shù)描述
void vTaskStartScheduler( void );
啟動(dòng)RTOS調(diào)度器,之后RTOS內(nèi)核控制哪個(gè)任務(wù)執(zhí)行以及何時(shí)執(zhí)行。
當(dāng)調(diào)用vTaskStartScheduler()后,空閑任務(wù)被自動(dòng)創(chuàng)建。
如果configUSE_TIMERS被設(shè)置為1,定時(shí)器后臺(tái)任務(wù)也會(huì)被創(chuàng)建。
如果vTaskStartScheduler()成功執(zhí)行,則該函數(shù)不會(huì)返回,直到有任務(wù)調(diào)用了vTaskEndScheduler()。
如果因?yàn)镽AM不足而無(wú)法創(chuàng)建空閑任務(wù),該函數(shù)也可能執(zhí)行失敗,并會(huì)立刻返回調(diào)用處。
7.停止調(diào)度器
7.1函數(shù)描述
void vTaskEndScheduler( void );
僅用于x86硬件架構(gòu)中。
停止RTOS內(nèi)核系統(tǒng)節(jié)拍時(shí)鐘。所有創(chuàng)建的任務(wù)自動(dòng)刪除并停止多任務(wù)調(diào)度。
8.掛起調(diào)度器
8.1函數(shù)描述
void vTaskSuspendAll( void );
掛起調(diào)度器,但不禁止中斷。當(dāng)調(diào)度器掛起時(shí),不會(huì)進(jìn)行上下文切換。調(diào)度器掛起后,正在執(zhí)行的任務(wù)會(huì)一直繼續(xù)執(zhí)行,內(nèi)核不再調(diào)度(意味著當(dāng)前任務(wù)不會(huì)被切換出去),直到該任務(wù)調(diào)用了xTaskResumeAll ()函數(shù)。
內(nèi)核調(diào)度器掛起期間,那些可以引起上下文切換的API函數(shù)(如vTaskDelayUntil()、xQueueSend()等)決不可使用。
9.恢復(fù)被掛起的調(diào)度器
9.1函數(shù)描述
BaseType_t xTaskResumeAll( void );
恢復(fù)因調(diào)用vTaskSuspendAll()函數(shù)而掛起的實(shí)時(shí)內(nèi)核調(diào)度器。
xTaskResumeAll()僅恢復(fù)調(diào)度器,它不會(huì)恢復(fù)那些被vTaskSuspend()函數(shù)掛起的任務(wù)。
9.2返回值
返回pdTRUE 表示恢復(fù)調(diào)度器引起了一次上下文切換,否則,返回pdFALSE。
9.3用法舉例
voidvTask1( void * pvParameters ) { for( ;; ) { /* 任務(wù)代碼寫在這里 */ /* ... */ /* 有些時(shí)候,某個(gè)任務(wù)希望可以連續(xù)長(zhǎng)時(shí)間的運(yùn)行,但這時(shí)不能使用taskENTER_CRITICAL ()/taskEXIT_CRITICAL ()的方法,這樣會(huì)屏蔽掉中斷,引起中斷丟失,包括系統(tǒng)節(jié)拍時(shí)鐘??梢允褂胿TaskSuspendAll ()停止RTOS內(nèi)核調(diào)度:*/ xTaskSuspendAll (); /* 執(zhí)行操作代碼放在這里。這樣不用進(jìn)入臨界區(qū)就可以連續(xù)長(zhǎng)時(shí)間執(zhí)行了。在這期間,中斷仍然會(huì)得到響應(yīng),RTOS內(nèi)核系統(tǒng)節(jié)拍時(shí)鐘也會(huì)繼續(xù)保持運(yùn)作 */ /* ... */ /* 操作結(jié)束,重新啟動(dòng)RTOS內(nèi)核 。我們想強(qiáng)制進(jìn)行一次上下文切換,但是如果恢復(fù)調(diào)度器的時(shí)候已經(jīng)執(zhí)行了上下文切換,再執(zhí)行一次是沒有意義的,因此會(huì)進(jìn)行一次判斷。*/ if( !xTaskResumeAll () ) { taskYIELD (); } } }
10.調(diào)整系統(tǒng)節(jié)拍
10.1函數(shù)描述
void vTaskStepTick( TickType_txTicksToJump );
如果RTOS使能tickless空閑功能,每當(dāng)只有空閑任務(wù)被執(zhí)行時(shí),系統(tǒng)節(jié)拍時(shí)鐘中斷將會(huì)停止,微控制器進(jìn)入低功耗模式。
當(dāng)微控制器退出低功耗后,系統(tǒng)節(jié)拍計(jì)數(shù)器必須被調(diào)整,將進(jìn)入低功耗的時(shí)間彌補(bǔ)上。
如果FreeRTOS移植文件中定義了宏portSUPPRESS_TICKS_AND_SLEEP()實(shí)體,則函數(shù)vTaskStepTick用于在這個(gè)宏portSUPPRESS_TICKS_AND_SLEEP()實(shí)體內(nèi)部調(diào)整系統(tǒng)節(jié)拍計(jì)數(shù)器。
函數(shù)vTaskStepTick是一個(gè)全局函數(shù),所以也可以在宏portSUPPRESS_TICKS_AND_SLEEP()實(shí)體中重寫該函數(shù)。
在文件FreeRTOSConfig.h中,宏configUSE_TICKLESS_IDLE必須設(shè)置為1,此函數(shù)才有效。
10.2參數(shù)描述
xTickToJump:時(shí)間值,單位是系統(tǒng)節(jié)拍周期,表示微處理器進(jìn)入低功耗的時(shí)間,函數(shù)根據(jù)這個(gè)值來(lái)調(diào)整系統(tǒng)節(jié)拍計(jì)數(shù)器的值。
10.3用法舉例
/* 首先定義宏portSUPPRESS_TICKS_AND_SLEEP()。宏參數(shù)指定要進(jìn)入低功耗(睡眠)的時(shí)間,單位是系統(tǒng)節(jié)拍周期。*/#defineportSUPPRESS_TICKS_AND_SLEEP( xIdleTime ) vApplicationSleep( xIdleTime ) /* 定義被宏portSUPPRESS_TICKS_AND_SLEEP()調(diào)用的函數(shù) */void vApplicationSleep(TickType_t xExpectedIdleTime ){ unsigned long ulLowPowerTimeBeforeSleep,ulLowPowerTimeAfterSleep; /* 從時(shí)鐘源獲取當(dāng)前時(shí)間,當(dāng)微控制器進(jìn)入低功耗的時(shí)候,這個(gè)時(shí)鐘源必須在運(yùn)行 */ ulLowPowerTimeBeforeSleep =ulGetExternalTime(); /*停止系統(tǒng)節(jié)拍時(shí)鐘中斷。*/ prvStopTickInterruptTimer(); /* 配置一個(gè)中斷,當(dāng)指定的睡眠時(shí)間達(dá)到后,將處理器從低功耗中喚醒。這個(gè)中斷源必須在微控制器進(jìn)入低功耗時(shí)也可以工作。*/ vSetWakeTimeInterrupt( xExpectedIdleTime ); /*進(jìn)入低功耗 */ prvSleep(); /* 確定微控制器進(jìn)入低功耗模式持續(xù)的真正時(shí)間。因?yàn)槠渌袛嘁部赡苁沟梦⑻幚砥魍顺龅凸哪J健W⒁猓涸谡{(diào)用宏portSUPPRESS_TICKS_AND_SLEEP()之前,調(diào)度器應(yīng)該被掛起,portSUPPRESS_TICKS_AND_SLEEP()返回后,再將調(diào)度器恢復(fù)。因此,這個(gè)函數(shù)未完成前,不會(huì)執(zhí)行其它任務(wù)。*/ ulLowPowerTimeAfterSleep =ulGetExternalTime(); /*調(diào)整內(nèi)核系統(tǒng)節(jié)拍計(jì)數(shù)器。*/ vTaskStepTick( ulLowPowerTimeAfterSleep –ulLowPowerTimeBeforeSleep ); /*重新啟動(dòng)系統(tǒng)節(jié)拍時(shí)鐘中斷。*/ prvStartTickInterruptTimer();}/* 首先定義宏portSUPPRESS_TICKS_AND_SLEEP()。宏參數(shù)指定要進(jìn)入低功耗(睡眠)的時(shí)間,單位是系統(tǒng)節(jié)拍周期。*/ #defineportSUPPRESS_TICKS_AND_SLEEP( xIdleTime ) vApplicationSleep( xIdleTime ) /* 定義被宏portSUPPRESS_TICKS_AND_SLEEP()調(diào)用的函數(shù) */ void vApplicationSleep(TickType_t xExpectedIdleTime ) { unsigned long ulLowPowerTimeBeforeSleep,ulLowPowerTimeAfterSleep; /* 從時(shí)鐘源獲取當(dāng)前時(shí)間,當(dāng)微控制器進(jìn)入低功耗的時(shí)候,這個(gè)時(shí)鐘源必須在運(yùn)行 */ ulLowPowerTimeBeforeSleep =ulGetExternalTime(); /*停止系統(tǒng)節(jié)拍時(shí)鐘中斷。*/ prvStopTickInterruptTimer(); /* 配置一個(gè)中斷,當(dāng)指定的睡眠時(shí)間達(dá)到后,將處理器從低功耗中喚醒。這個(gè)中斷源必須在微控制器進(jìn)入低功耗時(shí)也可以工作。*/ vSetWakeTimeInterrupt( xExpectedIdleTime ); /*進(jìn)入低功耗 */ prvSleep(); /* 確定微控制器進(jìn)入低功耗模式持續(xù)的真正時(shí)間。因?yàn)槠渌袛嘁部赡苁沟梦⑻幚砥魍顺龅凸哪J?。注意:在調(diào)用宏portSUPPRESS_TICKS_AND_SLEEP()之前,調(diào)度器應(yīng)該被掛起,portSUPPRESS_TICKS_AND_SLEEP()返回后,再將調(diào)度器恢復(fù)。因此,這個(gè)函數(shù)未完成前,不會(huì)執(zhí)行其它任務(wù)。*/ ulLowPowerTimeAfterSleep =ulGetExternalTime(); /*調(diào)整內(nèi)核系統(tǒng)節(jié)拍計(jì)數(shù)器。*/ vTaskStepTick( ulLowPowerTimeAfterSleep –ulLowPowerTimeBeforeSleep ); /*重新啟動(dòng)系統(tǒng)節(jié)拍時(shí)鐘中斷。*/ prvStartTickInterruptTimer(); }
以上就是FreeRTOS實(shí)時(shí)操作系統(tǒng)的內(nèi)核控制示例解析的詳細(xì)內(nèi)容,更多關(guān)于FreeRTOS實(shí)時(shí)操作系統(tǒng)內(nèi)核控制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
FreeRTOS進(jìn)階之任務(wù)通知示例完全解析
這篇文章主要為大家介紹了FreeRTOS進(jìn)階系列之任務(wù)通知的示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04FreeRTOS實(shí)時(shí)操作系統(tǒng)多任務(wù)管理基礎(chǔ)知識(shí)
這篇文章主要為大家介紹了FreeRTOS實(shí)時(shí)操作系統(tǒng)多任務(wù)管理的基礎(chǔ)知識(shí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04FreeRTOS進(jìn)階之任務(wù)創(chuàng)建完全解析
這篇文章主要為大家介紹了FreeRTOS進(jìn)階之任務(wù)創(chuàng)建完全解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04FreeRTOS進(jìn)階列表和列表項(xiàng)示例分析
這篇文章主要為大家介紹了FreeRTOS進(jìn)階系列之列表和列表項(xiàng)示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04FreeRTOS編碼標(biāo)準(zhǔn)及風(fēng)格指南
這篇文章主要為大家介紹了FreeRTOS編碼標(biāo)準(zhǔn)及風(fēng)格指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04FreeRTOS信號(hào)量API函數(shù)基礎(chǔ)教程
這篇文章主要為大家介紹了FreeRTOS信號(hào)量API函數(shù)的基礎(chǔ)教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04FreeRTOS實(shí)時(shí)操作系統(tǒng)的任務(wù)創(chuàng)建與任務(wù)切換
這篇文章主要為大家介紹了FreeRTOS實(shí)時(shí)操作系統(tǒng)的任務(wù)創(chuàng)建與任務(wù)切換,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04FreeRTOS實(shí)時(shí)操作系統(tǒng)的任務(wù)通知方法
這篇文章主要為大家介紹了FreeRTOS實(shí)時(shí)操作系統(tǒng)的任務(wù)通知方法示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04FreeRTOS任務(wù)控制API函數(shù)的功能分析
這篇文章主要為大家介紹了FreeRTOS任務(wù)控制API函數(shù)的功能分析,F(xiàn)reeRTOS任務(wù)控制API函數(shù)主要實(shí)現(xiàn)任務(wù)延時(shí)、任務(wù)掛起、解除任務(wù)掛起、任務(wù)優(yōu)先級(jí)獲取和設(shè)置等功能2022-04-04