FreeRTOS任务可以使用信号量来完成同步,但是使用信号量来同步的话任务只能与单个的事件或任务进行同步。有时候某个任务可能会需要与多个事件或任务进行同步,此时信号量就无能为力了。 FreeRTOS 为此提供了一个可选的解决方法,那就是事件标志组。
事件位用来表明某个事件是否发生, 事件位通常用作事件标志。个事件组就是一组的事件位, 事件组中的事件位通过位编号来访问。事件标志组的数据类型为 EventGroupHandle_t, 当 configUSE_16_BIT_TICKS 为 1 的时候事件标志组可以存储 8 个事件位,当 configUSE_16_BIT_TICKS 为 0 的时候事件标志组存储 24个事件位。.
函数xEventGroupCreate()用于创建一个事件标志组,所需要的内存通过动态内存管理方法分配。 由于内部处理 的 原 因 , 事 件 标 志 组 可 用 的 bit 数 取 决 于 configUSE_16_BIT_TICKS , 当configUSE_16_BIT_TICKS1 为 1 的 时 候 事 件 标 志 组 有 8 个 可 用 的 位 (bit0~bit7) , 当configUSE_16_BIT_TICKS 为 0 的时候事件标志组有 24 个可用的位(bit0~bit23)。 EventBits_t 类型的变量用来存储事件标志组中的各个事件位,函数原型如下:
EventGroupHandle_t xEventGroupCreate( void )
返回值:NULL: 事件标志组创建失败。其他值: 创建成功的事件标志组句柄。
设置事件标志组中事件位(标志)包括清零和置 1 两种操作
函数 xEventGroupClearBits()将事件标志组中的指定事件位清零,此函数只能用在任务中,不能用在中断服务函数中。函数原型如下:
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear );
xEventGroup: 要操作的事件标志组的句柄。
uxBitsToClear: 要清零的事件位, 比如要清除 bit3 的话就设置为 0X08。可以同时清除多个bit,如设置为 0X09 的话就是同时清除 bit3 和 bit0。
返回值:: 将指定事件位清零之前的事件组值。
函数 xEventGroupSetBits()设置指定的事件位为 1,此函数只能用在任务中,不能用于中断服务函数,此函数原型如下:
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet );
xEventGroup: 要操作的事件标志组的句柄。
uxBitsToClear: 指定要置 1 的事件位,比如要将 bit3 值 1 的话就设置为 0X08。可以同时将多个 bit 置 1,如设置为 0X09 的话就是同时将 bit3 和 bit0 置 1。
返回值: 在将指定事件位置 1 后的事件组值。
函数 xEventGroupGetBits()用于获取当前事件标志组的值,也就是各个事件位的值。此函数用在任务中,不能用在中断服务函数中。此函数原型如下:
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup )
xEventGroup: 要获取的事件标志组的句柄。
返回值:当前事件标志组的值。
某个任务可能需要与多个事件进行同步,那么这个任务就需要等待并判断多个事件位(标志),使用函数 xEventGroupWaitBits()可以完成这个功能。调用函数以后如果任务要等待的事件位还没有准备好(置 1 或清零)的话任务就会进入阻塞态,直到阻塞时间到达或者所等待的事件位准备好。函数原型如下:
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
const TickType_t xTicksToWait );
xEventGroup: 指定要等待的事件标志组。
uxBitsToWaitFord: 指定要等待的事件位,比如要等待bit0和(或)bit2的时候此参数就是0X05,如果要等待 bit0 和(或)bit1 和(或)bit2 的时候此参数就是 0X07,以此类推。
xClearOnExit: 此参数要是为pdTRUE的话,那么在退出此函数之前由参数uxBitsToWaitFor所设置的这些事件位就会清零。如果设置位 pdFALSE 的话这些事件位就不会改变。
xWaitForAllBits: 此参数如果设置为 pdTRUE 的话, 当 uxBitsToWaitFor 所设置的这些事件位都置 1, 或者指定的阻塞时间到的时候函数 xEventGroupWaitBits()才会返回。 当此函数为 pdFALSE 的话,只要 uxBitsToWaitFor 所设置的这些事件 位 其 中 的 任 意 一 个 置 1 , 或 者 指 定 的 阻 塞 时 间 到 的 话 函 数xEventGroupWaitBits()就会返回。
xTicksToWait: 设置阻塞时间,单位为节拍数。
返回值:返回当所等待的事件位置 1 以后的事件标志组的值,或者阻塞时间到。根据这个值我们就知道哪些事件位置 1 了。如果函数因为阻塞时间到而返回的话那么这个返回值就不代表任何的含义。
#define MCU_UPDATE_START BIT0 //事件位
EventGroupHandle_t spi_event_group;//事件标志组句柄
void My_TaskTest(void *pvParameters)
{
spi_event_group = xEventGroupCreate();//创建事件标志组
xTaskCreate(My_TaskTest1, "My_TaskTest1", 2048, NULL, 1, NULL);
while(true)
{
if(KEY==1)xEventGroupSetBits(spi_event_group, MCU_UPDATE_START);
vTaskDelay(20 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
void My_TaskTest1(void *pvParameters)
{
//等待事件组中的相应事件位
xEventGroupWaitBits(spi_event_group, MCU_UPDATE_START, false, true,portMAX_DELAY);
while(true)
{
printf("\r\nDo job!");
vTaskDelay(200 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}