FreeRTOS任務控制API函數(shù)的功能分析
1.相對延時
1.1函數(shù)描述
void vTaskDelay( portTickTypexTicksToDelay )
調(diào)用vTaskDelay()函數(shù)后,任務會進入阻塞狀態(tài),持續(xù)時間由vTaskDelay()函數(shù)的參數(shù)xTicksToDelay指定,單位是系統(tǒng)節(jié)拍時鐘周期。常量portTICK_RATE_MS 用來輔助計算真實時間,此值是系統(tǒng)節(jié)拍時鐘中斷的周期,單位是毫秒。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelay 必須設置成1,此函數(shù)才能有效。
vTaskDelay()指定的延時時間是從調(diào)用vTaskDelay()后開始計算的相對時間。比如vTaskDelay(100),那么從調(diào)用vTaskDelay()后,任務進入阻塞狀態(tài),經(jīng)過100個系統(tǒng)時鐘節(jié)拍周期,任務解除阻塞。因此,vTaskDelay()并不適用與周期性執(zhí)行任務的場合。此外,其它任務和中斷活動,會影響到vTaskDelay()的調(diào)用(比如調(diào)用前高優(yōu)先級任務搶占了當前任務),因此會影響任務下一次執(zhí)行的時間。API函數(shù)vTaskDelayUntil()可用于固定頻率的延時,它用來延時一個絕對時間。
1.2參數(shù)描述
xTicksToDelay:延時時間總數(shù),單位是系統(tǒng)時鐘節(jié)拍周期。
1.3用法舉例
voidvTaskFunction( void * pvParameters )
{
/* 阻塞500ms. */
constportTickType xDelay = 500 / portTICK_RATE_MS;
for( ;; )
{
/* 每隔500ms觸發(fā)一次LED, 觸發(fā)后進入阻塞狀態(tài) */
vToggleLED();
vTaskDelay( xDelay );
}
}2.絕對延時
2.1函數(shù)描述
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime,const TickType_txTimeIncrement );
任務延時一個指定的時間。周期性任務可以使用此函數(shù),以確保一個恒定的頻率執(zhí)行。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelayUntil 必須設置成1,此函數(shù)才有效。
這個函數(shù)不同于vTaskDelay()函數(shù)的一個重要之處在于:vTaskDelay()指定的延時時間是從調(diào)用vTaskDelay()之后(執(zhí)行完該函數(shù))開始算起的,但是vTaskDelayUntil()指定的延時時間是一個絕對時間。
調(diào)用vTaskDelay()函數(shù)后,任務會進入阻塞狀態(tài),持續(xù)時間由vTaskDelay()函數(shù)的參數(shù)指定,單位是系統(tǒng)節(jié)拍時鐘周期。因此vTaskDelay()并不適用于周期性執(zhí)行任務的場合。因為調(diào)用vTaskDelay()到任務解除阻塞的時間不總是固定的并且該任務下一次調(diào)用vTaskDelay()函數(shù)的時間也不總是固定的(兩次執(zhí)行同一任務的時間間隔本身就不固定,中斷或高優(yōu)先級任務搶占也可能會改變每一次執(zhí)行時間)。
vTaskDelay()指定一個從調(diào)用vTaskDelay()函數(shù)后開始計時,到任務解除阻塞為止的相對時間,而vTaskDelayUntil()指定一個絕對時間,每當時間到達,則解除任務阻塞。
應當指出的是,如果指定的喚醒時間已經(jīng)達到,vTaskDelayUntil()立刻返回(不會有阻塞)。因此,使用vTaskDelayUntil()周期性執(zhí)行的任務,無論任何原因(比如,任務臨時進入掛起狀態(tài))停止了周期性執(zhí)行,使得任務少運行了一個或多個執(zhí)行周期,那么需要重新計算所需要的喚醒時間。這可以通過傳遞給函數(shù)的指針參數(shù)pxPreviousWake指向的值與當前系統(tǒng)時鐘計數(shù)值比較來檢測,在大多數(shù)情況下,這并不是必須的。
常量portTICK_RATE_MS 用來輔助計算真實時間,此值是系統(tǒng)節(jié)拍時鐘中斷的周期,單位是毫秒。
當調(diào)用vTaskSuspendAll()函數(shù)掛起RTOS調(diào)度器時,不可以使用此函數(shù)。
2.2參數(shù)描述
pxPreviousWakeTime:指針,指向一個變量,該變量保存任務最后一次解除阻塞的時間。第一次使用前,該變量必須初始化為當前時間。之后這個變量會在vTaskDelayUntil()函數(shù)內(nèi)自動更新。
xTimeIncrement:周期循環(huán)時間。當時間等于(*pxPreviousWakeTime + xTimeIncrement)時,任務解除阻塞。如果不改變參數(shù)xTimeIncrement的值,調(diào)用該函數(shù)的任務會按照固定頻率執(zhí)行。
2.3用法舉例
//每10次系統(tǒng)節(jié)拍執(zhí)行一次
void vTaskFunction( void * pvParameters )
{
static portTickType xLastWakeTime;
const portTickType xFrequency = 10;
// 使用當前時間初始化變量xLastWakeTime
xLastWakeTime = xTaskGetTickCount();
for( ;; )
{
//等待下一個周期
vTaskDelayUntil( &xLastWakeTime,xFrequency );
// 需要周期性執(zhí)行代碼放在這里
}
}3.獲取任務優(yōu)先級
3.1函數(shù)描述
UBaseType_t uxTaskPriorityGet(TaskHandle_t xTask );
獲取指定任務的優(yōu)先級。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskPriorityGet必須設置成1,此函數(shù)才有效。
3.2參數(shù)描述
xTask:任務句柄。NULL表示獲取當前任務的優(yōu)先級。
3.3返回值
返回指定任務的優(yōu)先級。
3.4用法舉例
voidvAFunction( void )
{
xTaskHandlexHandle;
// 創(chuàng)建任務,保存任務句柄
xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ...
// 使用句柄獲取創(chuàng)建的任務的優(yōu)先級
if( uxTaskPriorityGet( xHandle ) !=tskIDLE_PRIORITY )
{
// 任務可以改變自己的優(yōu)先級
}
// ...
// 當前任務優(yōu)先級比創(chuàng)建的任務優(yōu)先級高?
if( uxTaskPriorityGet( xHandle ) <uxTaskPriorityGet( NULL ) )
{
// 當前優(yōu)先級較高
}
}4.設置任務優(yōu)先級
4.1函數(shù)描述
void vTaskPrioritySet( TaskHandle_txTask,UBaseType_tuxNewPriority );
設置指定任務的優(yōu)先級。如果設置的優(yōu)先級高于當前運行的任務,在函數(shù)返回前會進行一次上下文切換。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskPrioritySet 必須設置成1,此函數(shù)才有效。
4.2參數(shù)描述
xTask:要設置優(yōu)先級任務的句柄,為NULL表示設置當前運行的任務。uxNewPriority:要設置的新優(yōu)先級。
4.3用法舉例
voidvAFunction( void )
{
xTaskHandlexHandle;
// 創(chuàng)建任務,保存任務句柄。
xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ...
// 使用句柄來提高創(chuàng)建任務的優(yōu)先級
vTaskPrioritySet( xHandle,tskIDLE_PRIORITY + 1 );
// ...
// 使用NULL參數(shù)來提高當前任務的優(yōu)先級,設置成和創(chuàng)建的任務相同。
vTaskPrioritySet( NULL, tskIDLE_PRIORITY +1 );
}5.任務掛起
5.1函數(shù)描述
void vTaskSuspend( TaskHandle_txTaskToSuspend );
掛起指定任務。被掛起的任務絕不會得到處理器時間,不管該任務具有什么優(yōu)先級。
調(diào)用vTaskSuspend函數(shù)是不會累計的:即使多次調(diào)用vTaskSuspend ()函數(shù)將一個任務掛起,也只需調(diào)用一次vTaskResume ()函數(shù)就能使掛起的任務解除掛起狀態(tài)。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend必須設置成1,此函數(shù)才有效。
5.2參數(shù)描述
xTaskToSuspend:要掛起的任務句柄。為NULL表示掛起當前任務。
5.3用法舉例
voidvAFunction( void )
{
xTaskHandlexHandle;
// 創(chuàng)建任務,保存任務句柄.
xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ...
// 使用句柄掛起創(chuàng)建的任務.
vTaskSuspend( xHandle );
// ...
// 任務不再運行,除非其它任務調(diào)用了vTaskResume(xHandle )
//...
// 掛起本任務.
vTaskSuspend( NULL );
// 除非另一個任務使用handle調(diào)用了vTaskResume,否則永遠不會執(zhí)行到這里
}6.恢復掛起的任務
6.1函數(shù)描述
void vTaskResume( TaskHandle_txTaskToResume );
恢復掛起的任務。
通過調(diào)用一次或多次vTaskSuspend()掛起的任務,可以調(diào)用一次vTaskResume ()函數(shù)來再次恢復運行。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend必須置1,此函數(shù)才有效。
6.2參數(shù)描述
xTaskToResume:要恢復運行的任務句柄。
6.3用法舉例
voidvAFunction( void )
{
xTaskHandle xHandle;
// 創(chuàng)建任務,保存任務句柄
xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ...
// 使用句柄掛起創(chuàng)建的任務
vTaskSuspend( xHandle );
// ...
//任務不再運行,除非其它任務調(diào)用了vTaskResume(xHandle )
//...
// 恢復掛起的任務.
vTaskResume( xHandle );
// 任務再一次得到處理器時間
// 任務優(yōu)先級與之前相同
}7.恢復掛起的任務(在中斷服務函數(shù)中使用)
7.1函數(shù)描述
BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume );
用于恢復一個掛起的任務,用在ISR中。
通過調(diào)用一次或多次vTaskSuspend()函數(shù)而掛起的任務,只需調(diào)用一次xTaskResumeFromISR()函數(shù)即可恢復運行。
xTaskResumeFromISR()不可用于任務和中斷間的同步,如果中斷恰巧在任務被掛起之前到達,這就會導致一次中斷丟失(任務還沒有掛起,調(diào)用xTaskResumeFromISR()函數(shù)是沒有意義的,只能等下一次中斷)。這種情況下,可以使用信號量作為同步機制。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 必須設置成1,此函數(shù)才有效。
7.2參數(shù)描述
xTaskToResume:要恢復運行的任務句柄。
7.3返回值
如果恢復任務后需要上下文切換返回pdTRUE,否則返回pdFALSE。由ISR確定是否需要上下文切換。
7.4用法舉例
xTaskHandlexHandle; //注意這是一個全局變量
void vAFunction( void )
// 創(chuàng)建任務并保存任務句柄
xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
// ... 剩余代碼.
}
void vTaskCode( void *pvParameters )
{
for( ;; )
{
// ... 在這里執(zhí)行一些其它功能
// 掛起自己
vTaskSuspend( NULL );
//直到ISR恢復它之前,任務會一直掛起
}
}
void vAnExampleISR( void )
{
portBASE_TYPExYieldRequired;
// 恢復被掛起的任務
xYieldRequired = xTaskResumeFromISR(xHandle );
if( xYieldRequired == pdTRUE )
{
// 我們應該進行一次上下文切換
// 注: 如何做取決于你具體使用,可查看說明文檔和例程
portYIELD_FROM_ISR();
}
}以上就是FreeRTOS任務控制API函數(shù)的功能分析的詳細內(nèi)容,更多關(guān)于FreeRTOS任務控制API函數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
FreeRTOS進階系統(tǒng)節(jié)拍時鐘示例的完全解析
這篇文章主要為大家介紹了FreeRTOS進階系統(tǒng)節(jié)拍時鐘示例的完全解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04
FreeRTOS實時操作系統(tǒng)的內(nèi)核控制示例解析
這篇文章主要為大家介紹了FreeRTOS實時操作系統(tǒng)的內(nèi)核控制示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04

