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

FreeRTOS信號(hào)量的使用與實(shí)例
使用STM32CubeMX生成的FreeRTOS系統(tǒng)中,似乎沒(méi)有新封裝的事件標(biāo)志組,怎么解決?
使用FreeRTOS系統(tǒng)事件標(biāo)志組有些收不到是怎么回事?
轉(zhuǎn):freeRTOS事件組學(xué)習(xí)
轉(zhuǎn):第18章 FreeRTOS事件標(biāo)志組
轉(zhuǎn):第26章 FreeRTOS任務(wù)事件標(biāo)志組
第13章 事件標(biāo)志組
【NUCLEO-F412ZG試用體驗(yàn)】FreeRTOS_事件標(biāo)志組實(shí)現(xiàn)任務(wù)和中斷的同步
怎么才能讓任務(wù)等待到事件標(biāo)志組后一直執(zhí)行并且還要把事件標(biāo)志組清零?
怎樣去設(shè)置FreeRTOS事件標(biāo)志組的事件位呢
FreeRTOS中如何在多任務(wù)中訪問(wèn)外設(shè)?
FreeRTOS的事件標(biāo)志組
FreeRTOS的消息隊(duì)列

FreeRTOS創(chuàng)建事件標(biāo)志組

評(píng)論