freeRTOS中還有一種可以用于任務之間同步的手段 — 事件標志組。
假如在項目中,有些任務或者動作需要等到某種條件成立的時候才能被執行,不成立的時候不執行,這種情況就可以考慮使用事件標志組。設定一個事件標志,在項目運行過程中監控某種條件是否成立,如果條件成立了就設置這個事件標志位,另外一個地方如果發現這個標志位有效了,就執行這個任務或者動作,完成這個同步的過程。
0、事件標志組的配置 & 原理
FreeRTOS 中事件標志的實現,是在 FreeRTOSConfig.h 文件中配置的,如下:
1)選擇 8 個可用的事件標志組
配置宏定義 configUSE_16_BIT_TICKS 為 1 時,每創建一個事件標志組,用戶可以使用的事件標志是 8 個。
2)選擇 24 個可用的事件標志組
配置宏定義 configUSE_16_BIT_TICKS 為 0 時,每創建一個事件標志組,用戶可以使用的事件標志是 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 do
not 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;
最后看時間標志組的創建過程,代碼如下:
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; 應該就明白了吧!??!
其實freeRTOS的事件標志組的實現原理就是定義了一個變量,如果是 16 位變量,就僅使用了低 8bit ;如果定義了一個 32 位變量,就僅使用了低 24bit。
每一個 bit 用 0 和 1 兩種狀態來代表事件標志。
2、事件標志組的API管理函數
2.1、事件標志組的創建
函數原型:
EventGroupHandle_t xEventGroupCreate( void );
函數描述:
函數 xEventGroupCreate 用于創建事件標志組。
返回值,如果創建成功,此函數返回事件標志組的句柄,失敗會返回 NULL。
2.2、事件標志組的位設置
(1)在任務中設置
函數原型:
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, /* 事件標志組句柄 */
const EventBits_t uxBitsToSet ); /* 事件標志位設置 */
函數描述:
函數 xEventGroupSetBits 用于設置指定的事件標志位為 1。
第 1 個參數是事件標志組句柄。
第 2 個參數表示 24 個可設置的事件標志位,EventBits_t 是定義的 32 位變量,低 24 位用于事件標志設置。變量 uxBitsToSet 的低 24 位的某個位設置為 1,那么被設置的 事件標志組的相應位就設置為 1。變量 uxBitsToSet 設置為 0 的位對事件標志相應位沒有影響。比 如設置變量 uxBitsToSet = 0x0003 就表示將事件標志的位 0 和位 1 設置為1,其余位沒有變化。
返回當前的事件標志組數值。
(2)在中斷中設置
函數原型:
BaseType_t xEventGroupSetBitsFromISR(
EventGroupHandle_t xEventGroup, /* 事件標志組句柄 */
const EventBits_t uxBitsToSet, /* 事件標志位設置 */
BaseType_t *pxHigherPriorityTaskWoken ); /* 高優先級任務是否被喚醒的狀態保存 */
函數描述:
函數 xEventGroupSetBits 用于設置指定的事件標志位為 1。
第 1 個參數是事件標志組句柄。
第 2 個參數表示 24 個可設置的事件標志位,EventBits_t 是定義的 32 位變量,低 24 位用于事件標志設置。變量 uxBitsToSet 的低 24 位的某個位設置為 1,那么被設置的 事件標志組的相應位就設置為 1。變量 uxBitsToSet 設置為 0 的位對事件標志相應位沒有影響。比 如設置變量 uxBitsToSet = 0x0003 就表示將事件標志的位 0 和位 1 設置為 1,其余位沒有變化。
第3個參數用于保存是否有高優先級任務準備就緒。如果函數執行完畢后,此參數的數值是pdTRUE, 說明有高優先級任務要執行,否則沒有。
返回值,如果消息成功發送給 daemon 任務(就是 FreeRTOS 的定時器任務)返回 pdPASS,否則 返回 pdFAIL,另外 daemon 任務中的消息隊列滿了也會返回 pdFAIL。
使用前一定要保證事件標志已經通過函數 xEventGroupCreate 創建了。同時要在 FreeRTOSConfig.h 文件中使能如下三個宏定義:
3、事件標志組的位清除
(1)在任務中設置
EventBits_t xEventGroupClearBits(
EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear );
函數描述:
xEventGroup:需要操作的事件標志組;
uxBitsToClear:要清零的事件位,比如要清楚bit2就設置為0x04。
返回值:將指定事件位清零之前的事件組值。
(2)在中斷中設置
BaseType_t xEventGroupClearBitsFromISR(
EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear );
xEventGroup:需要操作的事件標志組;
uxBitsToClear:要清零的事件位,比如要清楚bit2就設置為0x04。
返回值:將指定事件位清零之前的事件組值。
4、等待時間標志組中的指定位被設置
(1)在任務中等待
函數原型:
EventBits_t xEventGroupWaitBits(
const EventGroupHandle_t xEventGroup, /* 事件標志組句柄 */
const EventBits_t uxBitsToWaitFor, /* 等待被設置的事件標志位 */
const BaseType_t xClearOnExit, /* 選擇是否清零被置位的事件標志位 */
const BaseType_t xWaitForAllBits, /* 選擇是否等待所有標志位都被設置 */
TickType_t xTicksToWait ); /* 設置等待時間 */
函數描述:
函數 xEventGroupWaitBits 等待事件標志被設置。
第 1 個參數是事件標志組句柄。
第 2 個參數表示等待 24 個事件標志位中的指定標志,EventBits_t 是定義的 32 位變量,低 24 位用于事件標志設置。比如設置變量 uxBitsToWaitFor = 0x0003 就表示等待事 件標志的位 0 和位 1 設置為 1。 此參數切不可設置為 0 。
第 3 個參數選擇是否清除已經被置位的事件標志,如果這個參數設置為 pdTRUE,且函數 xEventGroupWaitBits 在參數 xTicksToWait 設置的溢出時間內返回,那么相應被設置的事件標志 位會被清零。如果這個參數設置為 pdFALSE,對已經被設置的事件標志位沒有影響。
第 4 個參數選擇是否等待所有的標志位都被設置,如果這個參數設置為 pdTRUE,要等待第 2 個參 數 uxBitsToWaitFor 所指定的標志位全部被置 1,函數才可以返回。當然,超出了在參數 xTicksToWait 設置的溢出時間也是會返回的。如果這個參數設置為 pdFALSE,第 2 個參數 uxBitsToWaitFor 所指定的任何標志位被置 1,函數都會返回,超出溢出時間也會返回。
第 5 個參數設置等待時間,單位時鐘節拍周期。如果設置為 portMAX_DELAY,表示永久等待。
返回值:由于設置的時間超時或者指定的事件標志位被置 1,導致函數退出時返回的事件標志組數值。
5、刪除事件標志組
void vEventGroupDelete( EventGroupHandle_t xEventGroup );
xEventGroup:要刪除的時間標志組
6、事件標志組的示例demo
代碼中創建了兩個任務和一個24bit可用的時間標志組,一個任務通過按鍵掃描設置事件標志組的值,通過按鍵按三下設置事件標志組的值為0x00000008,然后另外一個任務阻塞等待,直到檢測到事件標志組被設置為0x00000008之后翻轉LED的閃爍。
EventGroupHandle_t FlagEventGroup; //事件標志組
FlagEventGroup = xEventGroupCreate(); //創建事件標志組 24bit可用
//task1任務函數
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個時鐘節拍
}
}
//task2任務函數
void task2_task(void *pvParameters) //prio = 3
{
u32 i,j;
u32 TxStr[3] = {0};
while(1)
{
xEventGroupWaitBits(FlagEventGroup, //事件標志組句柄
0x0008, //等待 24 個事件標志位中的指定標志
pdFALSE, //是否清除已經被置位的事件標志,pdTRUE - 清除,pdFALSE - 不清除
pdFALSE, //是否等待所有的標志位都被設置,pdTRUE - 是,pdFALSE - 不是
portMAX_DELAY //等待時間,單位時鐘節拍周期
);
LED0 ^= 1;
vTaskDelay(500); //延時n個時鐘節拍
}
}
-
同步
+關注
關注
0文章
89瀏覽量
19173 -
FreeRTOS
+關注
關注
12文章
484瀏覽量
62178 -
事件標志組
+關注
關注
0文章
3瀏覽量
1287
發布評論請先 登錄
相關推薦
評論