溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

FreeRTOS任務(wù)控制API函數(shù)的功能是什么

發(fā)布時(shí)間:2022-04-07 09:56:59 來源:億速云 閱讀:123 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“FreeRTOS任務(wù)控制API函數(shù)的功能是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“FreeRTOS任務(wù)控制API函數(shù)的功能是什么”吧!

1.相對延時(shí)

1.1函數(shù)描述

void vTaskDelay( portTickTypexTicksToDelay )

      調(diào)用vTaskDelay()函數(shù)后,任務(wù)會進(jìn)入阻塞狀態(tài),持續(xù)時(shí)間由vTaskDelay()函數(shù)的參數(shù)xTicksToDelay指定,單位是系統(tǒng)節(jié)拍時(shí)鐘周期。常量portTICK_RATE_MS 用來輔助計(jì)算真實(shí)時(shí)間,此值是系統(tǒng)節(jié)拍時(shí)鐘中斷的周期,單位是毫秒。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelay 必須設(shè)置成1,此函數(shù)才能有效。

      vTaskDelay()指定的延時(shí)時(shí)間是從調(diào)用vTaskDelay()后開始計(jì)算的相對時(shí)間。比如vTaskDelay(100),那么從調(diào)用vTaskDelay()后,任務(wù)進(jìn)入阻塞狀態(tài),經(jīng)過100個(gè)系統(tǒng)時(shí)鐘節(jié)拍周期,任務(wù)解除阻塞。因此,vTaskDelay()并不適用與周期性執(zhí)行任務(wù)的場合。此外,其它任務(wù)和中斷活動(dòng),會影響到vTaskDelay()的調(diào)用(比如調(diào)用前高優(yōu)先級任務(wù)搶占了當(dāng)前任務(wù)),因此會影響任務(wù)下一次執(zhí)行的時(shí)間。API函數(shù)vTaskDelayUntil()可用于固定頻率的延時(shí),它用來延時(shí)一個(gè)絕對時(shí)間。

1.2參數(shù)描述

xTicksToDelay:延時(shí)時(shí)間總數(shù),單位是系統(tǒng)時(shí)鐘節(jié)拍周期。

1.3用法舉例

voidvTaskFunction( void * pvParameters )
 {
     /* 阻塞500ms. */
     constportTickType xDelay = 500 / portTICK_RATE_MS;
 
     for( ;; )
     {
         /* 每隔500ms觸發(fā)一次LED, 觸發(fā)后進(jìn)入阻塞狀態(tài) */
         vToggleLED();
         vTaskDelay( xDelay );
     }
}

2.絕對延時(shí)

2.1函數(shù)描述

void vTaskDelayUntil( TickType_t *pxPreviousWakeTime,const TickType_txTimeIncrement );

      任務(wù)延時(shí)一個(gè)指定的時(shí)間。周期性任務(wù)可以使用此函數(shù),以確保一個(gè)恒定的頻率執(zhí)行。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelayUntil 必須設(shè)置成1,此函數(shù)才有效。

      這個(gè)函數(shù)不同于vTaskDelay()函數(shù)的一個(gè)重要之處在于:vTaskDelay()指定的延時(shí)時(shí)間是從調(diào)用vTaskDelay()之后(執(zhí)行完該函數(shù))開始算起的,但是vTaskDelayUntil()指定的延時(shí)時(shí)間是一個(gè)絕對時(shí)間。

      調(diào)用vTaskDelay()函數(shù)后,任務(wù)會進(jìn)入阻塞狀態(tài),持續(xù)時(shí)間由vTaskDelay()函數(shù)的參數(shù)指定,單位是系統(tǒng)節(jié)拍時(shí)鐘周期。因此vTaskDelay()并不適用于周期性執(zhí)行任務(wù)的場合。因?yàn)檎{(diào)用vTaskDelay()到任務(wù)解除阻塞的時(shí)間不總是固定的并且該任務(wù)下一次調(diào)用vTaskDelay()函數(shù)的時(shí)間也不總是固定的(兩次執(zhí)行同一任務(wù)的時(shí)間間隔本身就不固定,中斷或高優(yōu)先級任務(wù)搶占也可能會改變每一次執(zhí)行時(shí)間)。

      vTaskDelay()指定一個(gè)從調(diào)用vTaskDelay()函數(shù)后開始計(jì)時(shí),到任務(wù)解除阻塞為止的相對時(shí)間,而vTaskDelayUntil()指定一個(gè)絕對時(shí)間,每當(dāng)時(shí)間到達(dá),則解除任務(wù)阻塞。

      應(yīng)當(dāng)指出的是,如果指定的喚醒時(shí)間已經(jīng)達(dá)到,vTaskDelayUntil()立刻返回(不會有阻塞)。因此,使用vTaskDelayUntil()周期性執(zhí)行的任務(wù),無論任何原因(比如,任務(wù)臨時(shí)進(jìn)入掛起狀態(tài))停止了周期性執(zhí)行,使得任務(wù)少運(yùn)行了一個(gè)或多個(gè)執(zhí)行周期,那么需要重新計(jì)算所需要的喚醒時(shí)間。這可以通過傳遞給函數(shù)的指針參數(shù)pxPreviousWake指向的值與當(dāng)前系統(tǒng)時(shí)鐘計(jì)數(shù)值比較來檢測,在大多數(shù)情況下,這并不是必須的。

      常量portTICK_RATE_MS 用來輔助計(jì)算真實(shí)時(shí)間,此值是系統(tǒng)節(jié)拍時(shí)鐘中斷的周期,單位是毫秒。

      當(dāng)調(diào)用vTaskSuspendAll()函數(shù)掛起RTOS調(diào)度器時(shí),不可以使用此函數(shù)。

2.2參數(shù)描述

pxPreviousWakeTime:指針,指向一個(gè)變量,該變量保存任務(wù)最后一次解除阻塞的時(shí)間。第一次使用前,該變量必須初始化為當(dāng)前時(shí)間。之后這個(gè)變量會在vTaskDelayUntil()函數(shù)內(nèi)自動(dòng)更新。

xTimeIncrement:周期循環(huán)時(shí)間。當(dāng)時(shí)間等于(*pxPreviousWakeTime + xTimeIncrement)時(shí),任務(wù)解除阻塞。如果不改變參數(shù)xTimeIncrement的值,調(diào)用該函數(shù)的任務(wù)會按照固定頻率執(zhí)行。

2.3用法舉例

//每10次系統(tǒng)節(jié)拍執(zhí)行一次
 void vTaskFunction( void * pvParameters )
 {
     static portTickType xLastWakeTime;
     const portTickType xFrequency = 10;
     // 使用當(dāng)前時(shí)間初始化變量xLastWakeTime
     xLastWakeTime = xTaskGetTickCount();
     for( ;; )
     {
         //等待下一個(gè)周期
         vTaskDelayUntil( &xLastWakeTime,xFrequency );
         // 需要周期性執(zhí)行代碼放在這里
     }
 }

3.獲取任務(wù)優(yōu)先級

3.1函數(shù)描述

UBaseType_t uxTaskPriorityGet(TaskHandle_t xTask );

      獲取指定任務(wù)的優(yōu)先級。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskPriorityGet必須設(shè)置成1,此函數(shù)才有效。

3.2參數(shù)描述

xTask:任務(wù)句柄。NULL表示獲取當(dāng)前任務(wù)的優(yōu)先級。

3.3返回值

      返回指定任務(wù)的優(yōu)先級。

3.4用法舉例

voidvAFunction( void )
 {
     xTaskHandlexHandle;
     // 創(chuàng)建任務(wù),保存任務(wù)句柄
     xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
     // ...
     // 使用句柄獲取創(chuàng)建的任務(wù)的優(yōu)先級
     if( uxTaskPriorityGet( xHandle ) !=tskIDLE_PRIORITY )
     {
         // 任務(wù)可以改變自己的優(yōu)先級
     }
     // ...
     // 當(dāng)前任務(wù)優(yōu)先級比創(chuàng)建的任務(wù)優(yōu)先級高?
     if( uxTaskPriorityGet( xHandle ) <uxTaskPriorityGet( NULL ) )
     {
         // 當(dāng)前優(yōu)先級較高
     }
 }

4.設(shè)置任務(wù)優(yōu)先級

4.1函數(shù)描述

void vTaskPrioritySet( TaskHandle_txTask,UBaseType_tuxNewPriority );

      設(shè)置指定任務(wù)的優(yōu)先級。如果設(shè)置的優(yōu)先級高于當(dāng)前運(yùn)行的任務(wù),在函數(shù)返回前會進(jìn)行一次上下文切換。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskPrioritySet 必須設(shè)置成1,此函數(shù)才有效。

4.2參數(shù)描述

xTask:要設(shè)置優(yōu)先級任務(wù)的句柄,為NULL表示設(shè)置當(dāng)前運(yùn)行的任務(wù)。uxNewPriority:要設(shè)置的新優(yōu)先級。

4.3用法舉例

voidvAFunction( void )
 {
     xTaskHandlexHandle;
     // 創(chuàng)建任務(wù),保存任務(wù)句柄。
     xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
     // ...
     // 使用句柄來提高創(chuàng)建任務(wù)的優(yōu)先級
     vTaskPrioritySet( xHandle,tskIDLE_PRIORITY + 1 );
     // ...
     // 使用NULL參數(shù)來提高當(dāng)前任務(wù)的優(yōu)先級,設(shè)置成和創(chuàng)建的任務(wù)相同。
     vTaskPrioritySet( NULL, tskIDLE_PRIORITY +1 );
 }

5.任務(wù)掛起

5.1函數(shù)描述

void vTaskSuspend( TaskHandle_txTaskToSuspend );

      掛起指定任務(wù)。被掛起的任務(wù)絕不會得到處理器時(shí)間,不管該任務(wù)具有什么優(yōu)先級。

      調(diào)用vTaskSuspend函數(shù)是不會累計(jì)的:即使多次調(diào)用vTaskSuspend ()函數(shù)將一個(gè)任務(wù)掛起,也只需調(diào)用一次vTaskResume ()函數(shù)就能使掛起的任務(wù)解除掛起狀態(tài)。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend必須設(shè)置成1,此函數(shù)才有效。

5.2參數(shù)描述

xTaskToSuspend:要掛起的任務(wù)句柄。為NULL表示掛起當(dāng)前任務(wù)。

5.3用法舉例

voidvAFunction( void )
 {
     xTaskHandlexHandle;
     // 創(chuàng)建任務(wù),保存任務(wù)句柄.
     xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
     // ...
     // 使用句柄掛起創(chuàng)建的任務(wù).
     vTaskSuspend( xHandle );
     // ...
     // 任務(wù)不再運(yùn)行,除非其它任務(wù)調(diào)用了vTaskResume(xHandle )
     //...
     // 掛起本任務(wù).
     vTaskSuspend( NULL );
     // 除非另一個(gè)任務(wù)使用handle調(diào)用了vTaskResume,否則永遠(yuǎn)不會執(zhí)行到這里
 }

6.恢復(fù)掛起的任務(wù)

6.1函數(shù)描述

void vTaskResume( TaskHandle_txTaskToResume );

      恢復(fù)掛起的任務(wù)。

      通過調(diào)用一次或多次vTaskSuspend()掛起的任務(wù),可以調(diào)用一次vTaskResume ()函數(shù)來再次恢復(fù)運(yùn)行。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend必須置1,此函數(shù)才有效。

6.2參數(shù)描述

xTaskToResume:要恢復(fù)運(yùn)行的任務(wù)句柄。

6.3用法舉例

voidvAFunction( void )
 {
         xTaskHandle xHandle;
     // 創(chuàng)建任務(wù),保存任務(wù)句柄
     xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
     // ...
     // 使用句柄掛起創(chuàng)建的任務(wù)
     vTaskSuspend( xHandle );
     // ...
     //任務(wù)不再運(yùn)行,除非其它任務(wù)調(diào)用了vTaskResume(xHandle )    
          //...
     // 恢復(fù)掛起的任務(wù).
     vTaskResume( xHandle );
     // 任務(wù)再一次得到處理器時(shí)間
     // 任務(wù)優(yōu)先級與之前相同
 }

7.恢復(fù)掛起的任務(wù)(在中斷服務(wù)函數(shù)中使用)

7.1函數(shù)描述

BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume );

      用于恢復(fù)一個(gè)掛起的任務(wù),用在ISR中。

      通過調(diào)用一次或多次vTaskSuspend()函數(shù)而掛起的任務(wù),只需調(diào)用一次xTaskResumeFromISR()函數(shù)即可恢復(fù)運(yùn)行。

      xTaskResumeFromISR()不可用于任務(wù)和中斷間的同步,如果中斷恰巧在任務(wù)被掛起之前到達(dá),這就會導(dǎo)致一次中斷丟失(任務(wù)還沒有掛起,調(diào)用xTaskResumeFromISR()函數(shù)是沒有意義的,只能等下一次中斷)。這種情況下,可以使用信號量作為同步機(jī)制。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 必須設(shè)置成1,此函數(shù)才有效。

7.2參數(shù)描述

xTaskToResume:要恢復(fù)運(yùn)行的任務(wù)句柄。

7.3返回值

      如果恢復(fù)任務(wù)后需要上下文切換返回pdTRUE,否則返回pdFALSE。由ISR確定是否需要上下文切換。

7.4用法舉例

xTaskHandlexHandle;               //注意這是一個(gè)全局變量
 void vAFunction( void )
     // 創(chuàng)建任務(wù)并保存任務(wù)句柄
     xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
     // ... 剩余代碼.
 }
 void vTaskCode( void *pvParameters )
 {
     for( ;; )
     {
         // ... 在這里執(zhí)行一些其它功能
         // 掛起自己
         vTaskSuspend( NULL );
         //直到ISR恢復(fù)它之前,任務(wù)會一直掛起
     }
 }
 void vAnExampleISR( void )
 {
     portBASE_TYPExYieldRequired;
     // 恢復(fù)被掛起的任務(wù)
     xYieldRequired = xTaskResumeFromISR(xHandle );
     if( xYieldRequired == pdTRUE )
     {
         // 我們應(yīng)該進(jìn)行一次上下文切換
         // 注:  如何做取決于你具體使用,可查看說明文檔和例程
         portYIELD_FROM_ISR();
     }
 }

到此,相信大家對“FreeRTOS任務(wù)控制API函數(shù)的功能是什么”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI