FreeRTOS笔记(七)事件event和事件组event grtoup

事件event

概念

事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,但事件通信只能是事件类型的通信,无数据传输。
与信号量不同的是,它可以实现一对多,多对多的同步
即一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。

也可以是多个任务同步多个事件。
每一个事件组只需要很少的 RAM 空间来保存事件组的状态。 事件组存储在一个 EventBits_t 类型的变量中,该变量在事件组结构体中定义。

事件可使用于多种场合,它能够在一定程度上替代信号量,用于任务与任务间,中断与任务间的同步。

  • 事件仅用于同步,不提供数据传输功能。
  • 事件无排队性,即多次向任务设置同一事件(如果任务还未来得及读走), 等效于只设置一次。
  • 允许多个任务对同一事件进行读写操作。
  • 支持事件等待超时机制。

在 FreeRTOS 事件中,每个事件获取的时候,用户可以选择感兴趣的事件,并且选择读取事件信息标记,它有三个属性,分别是逻辑与,逻辑或以及是否清除标记。

当任务等待事件同步时,可以通过任务感兴趣的事件位和事件信息标记来判断当前接收的事件是否满足要求。
如果满足则说明任务等待到对应的事件,系统将唤醒等待的任务;否则,任务会根据用户指定的阻塞超时时间继续等待下去。

事件组event grtoup

概念

FreeRTOS笔记(七)事件event和事件组event grtoup_第1张图片

事件组可以简单地认为就是一个整数:

  • 每一位表示一个事件
  • 每一位事件的含义由程序员决定,比如: Bit0 表示用来串口是否就绪,Bit1 表示按键是否被按下
  • 这些位,值为 1 表示事件发生了,值为 0 表示事件没发生
  • 一个或多个任务、 ISR 都可以去写这些位;一个或多个任务、 ISR 都可以去读这些位
  • 可以等待某一位、某些位中的任意一个,也可以等待多位

**事件组:事件发生时,会唤醒所有符号条件的任务,简单地说它有"广播"的作用 **

每一位代表一个事件, 任务通过“逻辑与”或“逻辑或”与一个或多个事件建立关联,形成一个事件组。
事件的“逻辑或”也被称作是独立型同步,指的是任务感兴趣的所有事件任一件发生即可被唤醒;
事件“逻辑与” 则被称为是关联型同步,指的是任务感兴趣的若干事件都发生时才被唤醒,并且事件发生的时间可以不同步。

事件组函数
创建函数

使用事件组之前,要先创建,得到一个句柄;使用事件组时,要使用句柄来表明使用哪个事件组。
有两种创建方法:动态分配内存、静态分配内存。

/* 创建一个事件组,返回它的句柄。
* 此函数内部会分配事件组结构体
* 返回值: 返回句柄,非 NULL 表示成功
*/
EventGroupHandle_t xEventGroupCreate( void );
/* 创建一个事件组,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个 StaticEventGroup_t 结构体,并传入它的指
针
* 返回值: 返回句柄,非 NULL 表示成功
*/
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer );
删除函数

对于动态创建的事件组,不再需要它们时,可以删除它们以回收内存。

/*
* xEventGroup: 事件组句柄,你要删除哪个事件组
*/
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
设置事件

可以设置事件组的某个位、某些位,使用的函数有 2 个:

  • 在任务中使用 xEventGroupSetBits()
  • 在 ISR 中使用 xEventGroupSetBitsFromISR()

有一个或多个任务在等待事件,如果这些事件符合这些任务的期望,那么任务还会被唤醒。

/* 设置事件组中的位
* xEventGroup: 哪个事件组
* uxBitsToSet: 设置哪些位?
* 如果 uxBitsToSet 的 bitX, bitY 为 1, 那么事件组中的 bitX, bitY 被设置为 1
* 可以用来设置多个位,比如 0x15 就表示设置 bit4, bit2, bit0
* 返回值: 返回原来的事件值(没什么意义, 因为很可能已经被其他任务修改了)
*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
						const EventBits_t uxBitsToSet );
/* 设置事件组中的位
* xEventGroup: 哪个事件组
* uxBitsToSet: 设置哪些位?
* 如果 uxBitsToSet 的 bitX, bitY 为 1, 那么事件组中的 bitX, bitY 被设置为 1
* 可以用来设置多个位,比如 0x15 就表示设置 bit4, bit2, bit0
* pxHigherPriorityTaskWoken: 有没有导致更高优先级的任务进入就绪态? pdTRUE-有, pdFA
LSE-没有
* 返回值: pdPASS-成功, pdFALSE-失败
*/
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
                                const EventBits_t uxBitsToSet,
                                BaseType_t * pxHi
                                gherPriorityTaskWoken );
等待事件

使用 xEventGroupWaitBits ()来等待事件,可以等待某一位、某些位中的任意一个,也可以等待多位;等到期望的事件后,还可以清除某些位。

EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
                            const EventBits_t uxBitsToWaitFor,
                            const BaseType_t xClearOnExit,
                            const BaseType_t xWaitForAllBits,
                            TickType_t xTicksToWait );

参数说明:

参数 说明
xEventGroup 等待哪个事件组?
uxBitsToWaitFor 等待哪些位?哪些位要被测试?
xWaitForAllBits 怎么测试?是"AND"还是"OR"? pdTRUE: 等待的位,全部为 1; pdFALSE: 等待的位,某一个为 1 即可
xClearOnExit 函数提出前是否要清除事件? pdTRUE: 清除 uxBitsToWaitFor 指定的位 pdFALSE: 不清除
xTicksToWait 如果期待的事件未发生,阻塞多久。 可以设置为 0:判断后即刻返回; 可设置为 portMAX_DELAY:一定等到成功才返回; 可以设置为期望的 Tick Count,一般用 pdMS_TO_TICKS()把 ms 转换为 Tick Count
返回值 返回的是事件值, 如果期待的事件发生了,返回的是"非阻塞条件成立"时的事件值; 如果是超时退出,返回的是超时时刻的事件值。

可 以 使 用 xEventGroupWaitBits() 等 待 期 望 的 事 件 , 它 发 生 之 后 再 使 用xEventGroupClearBits()来清除。但是这两个函数之间,有可能被其他任务或中断抢占,它们可能会修改事件组。
可 以 使 用 设 置 xClearOnExit 为 pdTRUE , 使 得 对 事 件 组 的 测 试 、 清 零 都 在xEventGroupWaitBits()函数内部完成,这是一个原子操作。

同步任务

使用 xEventGroupSync() 函数可以同步多个任务:

  • 可以设置某位、某些位,表示自己做了什么事
  • 可以等待某位、某些位,表示要等等其他任务
  • 期望的时间发生后, xEventGroupSync()才会成功返回。
  • xEventGroupSync 成功返回后,会清除事件
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
                    const EventBits_t uxBitsToSet,
                    const EventBits_t uxBitsToWaitFor,
                    TickType_t xTicksToWait );

参数列表:

参数 说明
xEventGroup 哪个事件组?
uxBitsToSet 要设置哪些事件?我完成了哪些事件? 比如 0x05(二进制为 0101)会导致事件组的 bit0,bit2 被设置为 1
uxBitsToWaitFor 等待那个位、哪些位? 比如 0x15(二级制 10101),表示要等待 bit0,bit2,bit4 都为 1
xTicksToWait 如果期待的事件未发生,阻塞多久。 可以设置为 0:判断后即刻返回; 可设置为 portMAX_DELAY:一定等到成功才返回; 可以设置为期望的 Tick Count,一般用 pdMS_TO_TICKS()把 ms 转换为 Tick Count
返回值 返回的是事件值, 如果期待的事件发生了,返回的是"非阻塞条件成立"时的事件值; 如果是超时退出,返回的是超时时刻的事件值。

要使用事件组,代码中要有如下操作:

/* 1. 工程中添加 event_groups.c */
/* 2. 源码中包含头文件 */
##include "event_groups.h"  

你可能感兴趣的:(FreeRTOS,c语言,物联网,开发语言)