freeRTOS中還有一種可以用于任務之間同步的手段 — 事件標志組。
假如在項目中,有些任務或者動作需要等到某種條件成立的時候才能被執(zhí)行,不成立的時候不執(zhí)行,這種情況就可以考慮使用事件標志組。設定一個事件標志,在項目運行過程中監(jiān)控某種條件是否成立,如果條件成立了就設置這個事件標志位,另外一個地方如果發(fā)現(xiàn)這個標志位有效了,就執(zhí)行這個任務或者動作,完成這個同步的過程。
0、事件標志組的配置 & 原理
FreeRTOS 中事件標志的實現(xiàn),是在 FreeRTOSConfig.h 文件中配置的,如下:
1)選擇 8 個可用的事件標志組
配置宏定義 configUSE_16_BIT_TICKS 為 1 時,每創(chuàng)建一個事件標志組,用戶可以使用的事件標志是 8 個。
2)選擇 24 個可用的事件標志組
配置宏定義 configUSE_16_BIT_TICKS 為 0 時,每創(chuàng)建一個事件標志組,用戶可以使用的事件標志是 24 個。
上面說的 8 個和 24 個事件標志是怎么回事呢?
首選看看宏 configUSE_16_BIT_TICKS ** 定義了之后做了些什么吧?在文件portmacro.h** 有這么一段代碼:
typedef uint16_t TickType_t;typedef uint32_t TickType_t;/* 32-bit tick type on a 32-bit architecture, so reads of the tick count donot need to be guarded with a critical section. */
注意這個 TickType_t 這個類型重聲明!??!
以及下面這個類型重定義:
typedef TickType_t EventBits_t;
再看時間標志組的結構體:
typedef struct xEventGroupDefinition{EventBits_t uxEventBits; // 看這個、看這個、看這個?。?!嘿嘿!??!List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */UBaseType_t uxEventGroupNumber;} EventGroup_t;
注意看 EventBits_t uxEventBits;
最后看時間標志組的創(chuàng)建過程,代碼如下:
EventGroupHandle_t xEventGroupCreate( void ){EventGroup_t *pxEventBits;pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );if( pxEventBits != NULL ){pxEventBits->uxEventBits = 0; // 記得看我、記得看我、記得看我?。?!嘻嘻?。?/span>vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );traceEVENT_GROUP_CREATE( pxEventBits );}else{traceEVENT_GROUP_CREATE_FAILED();}return ( EventGroupHandle_t ) pxEventBits;}
看上面代碼的 pxEventBits->uxEventBits = 0; 應該就明白了吧?。。?/strong>
其實freeRTOS的事件標志組的實現(xiàn)原理就是定義了一個變量,如果是 16 位變量,就僅使用了低 8bit ;如果定義了一個 32 位變量,就僅使用了低 24bit。
每一個 bit 用 0 和 1 兩種狀態(tài)來代表事件標志。
2、事件標志組的API管理函數(shù)
2.1、事件標志組的創(chuàng)建
函數(shù)原型:
EventGroupHandle_t xEventGroupCreate( void );
函數(shù)描述:
函數(shù) xEventGroupCreate 用于創(chuàng)建事件標志組。
返回值,如果創(chuàng)建成功,此函數(shù)返回事件標志組的句柄,失敗會返回 NULL。
2.2、事件標志組的位設置
(1)在任務中設置
函數(shù)原型:
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, /* 事件標志組句柄 */const EventBits_t uxBitsToSet ); /* 事件標志位設置 */
函數(shù)描述:
函數(shù) xEventGroupSetBits 用于設置指定的事件標志位為 1。
第 1 個參數(shù)是事件標志組句柄。
第 2 個參數(shù)表示 24 個可設置的事件標志位,EventBits_t 是定義的 32 位變量,低 24 位用于事件標志設置。變量 uxBitsToSet 的低 24 位的某個位設置為 1,那么被設置的 事件標志組的相應位就設置為 1。變量 uxBitsToSet 設置為 0 的位對事件標志相應位沒有影響。比 如設置變量 uxBitsToSet = 0x0003 就表示將事件標志的位 0 和位 1 設置為1,其余位沒有變化。
返回當前的事件標志組數(shù)值。
(2)在中斷中設置
函數(shù)原型:
BaseType_t xEventGroupSetBitsFromISR(EventGroupHandle_t xEventGroup, /* 事件標志組句柄 */const EventBits_t uxBitsToSet, /* 事件標志位設置 */BaseType_t *pxHigherPriorityTaskWoken ); /* 高優(yōu)先級任務是否被喚醒的狀態(tài)保存 */
函數(shù)描述:
函數(shù) xEventGroupSetBits 用于設置指定的事件標志位為 1。
第 1 個參數(shù)是事件標志組句柄。
第 2 個參數(shù)表示 24 個可設置的事件標志位,EventBits_t 是定義的 32 位變量,低 24 位用于事件標志設置。變量 uxBitsToSet 的低 24 位的某個位設置為 1,那么被設置的 事件標志組的相應位就設置為 1。變量 uxBitsToSet 設置為 0 的位對事件標志相應位沒有影響。比 如設置變量 uxBitsToSet = 0x0003 就表示將事件標志的位 0 和位 1 設置為 1,其余位沒有變化。
第3個參數(shù)用于保存是否有高優(yōu)先級任務準備就緒。如果函數(shù)執(zhí)行完畢后,此參數(shù)的數(shù)值是pdTRUE, 說明有高優(yōu)先級任務要執(zhí)行,否則沒有。
返回值,如果消息成功發(fā)送給 daemon 任務(就是 FreeRTOS 的定時器任務)返回 pdPASS,否則 返回 pdFAIL,另外 daemon 任務中的消息隊列滿了也會返回 pdFAIL。
使用前一定要保證事件標志已經(jīng)通過函數(shù) xEventGroupCreate 創(chuàng)建了。同時要在 FreeRTOSConfig.h 文件中使能如下三個宏定義:
3、事件標志組的位清除
(1)在任務中設置
EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToClear );
函數(shù)描述:
xEventGroup:需要操作的事件標志組;
uxBitsToClear:要清零的事件位,比如要清楚bit2就設置為0x04。
返回值:將指定事件位清零之前的事件組值。
(2)在中斷中設置
BaseType_t xEventGroupClearBitsFromISR(EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToClear );
xEventGroup:需要操作的事件標志組;
uxBitsToClear:要清零的事件位,比如要清楚bit2就設置為0x04。
返回值:將指定事件位清零之前的事件組值。
4、等待時間標志組中的指定位被設置
(1)在任務中等待
函數(shù)原型:
EventBits_t xEventGroupWaitBits(const EventGroupHandle_t xEventGroup, /* 事件標志組句柄 */const EventBits_t uxBitsToWaitFor, /* 等待被設置的事件標志位 */const BaseType_t xClearOnExit, /* 選擇是否清零被置位的事件標志位 */const BaseType_t xWaitForAllBits, /* 選擇是否等待所有標志位都被設置 */TickType_t xTicksToWait ); /* 設置等待時間 */
函數(shù)描述:
函數(shù) xEventGroupWaitBits 等待事件標志被設置。
第 1 個參數(shù)是事件標志組句柄。
第 2 個參數(shù)表示等待 24 個事件標志位中的指定標志,EventBits_t 是定義的 32 位變量,低 24 位用于事件標志設置。比如設置變量 uxBitsToWaitFor = 0x0003 就表示等待事 件標志的位 0 和位 1 設置為 1。 此參數(shù)切不可設置為 0 。
第 3 個參數(shù)選擇是否清除已經(jīng)被置位的事件標志,如果這個參數(shù)設置為 pdTRUE,且函數(shù) xEventGroupWaitBits 在參數(shù) xTicksToWait 設置的溢出時間內(nèi)返回,那么相應被設置的事件標志 位會被清零。如果這個參數(shù)設置為 pdFALSE,對已經(jīng)被設置的事件標志位沒有影響。
第 4 個參數(shù)選擇是否等待所有的標志位都被設置,如果這個參數(shù)設置為 pdTRUE,要等待第 2 個參 數(shù) uxBitsToWaitFor 所指定的標志位全部被置 1,函數(shù)才可以返回。當然,超出了在參數(shù) xTicksToWait 設置的溢出時間也是會返回的。如果這個參數(shù)設置為 pdFALSE,第 2 個參數(shù) uxBitsToWaitFor 所指定的任何標志位被置 1,函數(shù)都會返回,超出溢出時間也會返回。
第 5 個參數(shù)設置等待時間,單位時鐘節(jié)拍周期。如果設置為 portMAX_DELAY,表示永久等待。
返回值:由于設置的時間超時或者指定的事件標志位被置 1,導致函數(shù)退出時返回的事件標志組數(shù)值。
5、刪除事件標志組
void vEventGroupDelete( EventGroupHandle_t xEventGroup );
xEventGroup:要刪除的時間標志組
6、事件標志組的示例demo
代碼中創(chuàng)建了兩個任務和一個24bit可用的時間標志組,一個任務通過按鍵掃描設置事件標志組的值,通過按鍵按三下設置事件標志組的值為0x00000008,然后另外一個任務阻塞等待,直到檢測到事件標志組被設置為0x00000008之后翻轉(zhuǎn)LED的閃爍。
EventGroupHandle_t FlagEventGroup; //事件標志組FlagEventGroup = xEventGroupCreate(); //創(chuàng)建事件標志組 24bit可用//task1任務函數(shù)void task1_task(void *pvParameters) //prio = 2{u8 keyVal = 0;EventBits_t FlagVal;u32 setVal = 0x0001;while(1){keyVal = KEY_Scan(0);if(keyVal == KEY0_PRES){FlagVal = xEventGroupSetBits(FlagEventGroup, setVal);printf("事件標志組設置值為:%d\\r\\n",FlagVal);xEventGroupClearBits(FlagEventGroup, setVal); //清除標志位setVal <<= 1;}LED1 ^= 1;vTaskDelay(200); //延時n個時鐘節(jié)拍}}//task2任務函數(shù)void task2_task(void *pvParameters) //prio = 3{u32 i,j;u32 TxStr[3] = {0};while(1){xEventGroupWaitBits(FlagEventGroup, //事件標志組句柄0x0008, //等待 24 個事件標志位中的指定標志pdFALSE, //是否清除已經(jīng)被置位的事件標志,pdTRUE - 清除,pdFALSE - 不清除pdFALSE, //是否等待所有的標志位都被設置,pdTRUE - 是,pdFALSE - 不是portMAX_DELAY //等待時間,單位時鐘節(jié)拍周期);LED0 ^= 1;vTaskDelay(500); //延時n個時鐘節(jié)拍}}
-
同步
+關注
關注
0文章
103瀏覽量
19887 -
FreeRTOS
+關注
關注
14文章
496瀏覽量
65996 -
事件標志組
+關注
關注
0文章
3瀏覽量
1427
發(fā)布評論請先 登錄

freeRTOS用于任務之間同步的手段事件標志組
評論