freeRtos学习笔记 (5)事件组

freeRtos学习笔记

freeRtos事件组

为什么要用事件组?

多任务环境下, 任务、中断之间往往需要同步操作,一个事件发生会告知等待中的任
务,即形成一个任务与任务、中断与任务间的同步。事件可以提供一对多、多对多的同步
操作。一对多同步模型:一个任务等待多个事件的触发,这种情况是比较常见的;多对多
同步模型:多个任务等待多个事件的触发。

为什么不直接使用全局变量?

在裸机编程时,使用全局变量的确比较方便,但是在加上 RTOS 后
就是另一种情况了。 使用全局变量相比事件标志组主要有如下三个问题:

  • 使用事件标志组可以让 RTOS 内核有效地管理任务, 而全局变量是无法做到的,任务的超时等机制需
    要用户自己去实现。
  • 使用了全局变量就要防止多任务的访问冲突,而使用事件标志组则处理好了这个问题,用户无需担心。
  • 使用事件标志组可以有效地解决中断服务程序和任务之间的同步问题

事件组创建

EventGroupHandle_t xEventGroupCreate(void);

函数 xEventGroupCreate 用于创建事件标志组。

  • 返回值,如果创建成功,此函数返回事件标志组的句柄,如果 FreeRTOSConfig.h 文件中定义的 heap
    空间不足会返回 NULL

设置事件组

EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup,  /* 事件组句柄 */
                               const EventBits_t  uxBitsToSet); /* 要设置的事件标志位 */

EventBits_t xEventGroupSetBitsFromISR(EventGroupHandle_t xEventGroup,   /* 事件组句柄 */
                               const EventBits_t  uxBitsToSet,          /* 要设置的事件标志位 */
                               BaseType_t *pxHigherPriorityTaskWoken ); /* 高优先级任务是否被唤醒的状态保存 */

函数 xEventGroupSetBits 用于设置指定的事件标志位为 1。

  • 第 1 个参数是事件标志组句柄。
  • 第 2 个参数表示可设置的事件标志位, 当单片机为16位时 EventBits_t 是定义的 16 位变量,低8位用于事件标志位设置;当单片机位32位时 EventBits_t 是定义的 32 位变量,低24位用于事件标志位设置;变量 uxBitsToSet 的低 24 位的某个位设置为 1,那么被设置的事件标志组的相应位就设置为 1。 变量 uxBitsToSet 设置为 0 的位对事件标志相应位没有影响。比如设置变量 uxBitsToSet = 0x0003 就表示将事件标志的位 0 和位 1 设置为 1, 其余位没有变化。
  • 第 3 个参数用于保存是否有高优先级任务准备就绪。 如果函数执行完毕后,此参数的数值是 pdTRUE,
    说明有高优先级任务要执行, 否则没有。可以利用此参数判断是否需要立刻进行任务切换 taskYIELD()。
  • 返回值: 返回当前的事件标志组数值。
  • 注意事项:
    1. 中断服务程序中使用的是 xEventGroupSetBitsFromISR();

函数 xEventGroupSetBitsFromISR 对事件标志组的操作是不确定性操作,因为不知道当前有多少个
任务在等待此事件标志(消息队列有对应的列表,信号量底层也是根据消息队列实现的,因此信号量和消息队列不需要这样)。而 FreeRTOS 不允许在中断服务程序和临界段中执行不确定性操作。 为了不在中断服务程序中执行,就通过此函数给 FreeRTOS 的 daemon 任务(就是 FreeRTOS 的定时器任务)发送消息,在 daemon 任务中执行事件标志的置位操作。 同时也为了不在临界段中执行此不确定操作,将临界段改成由调度锁来完成。这样不确定性操作在中断服务程序和临界段中执行的问题就都得到解决了。由于函数 xEventGroupSetBitsFromISR 对事件标志的置位操作是在 daemon 任务里面执行的, 所以如果使用xEventGroupSetBitsFromISR函数需要使能软件定时器,如果想让置位操作立即生效,即让等此事件标志的任务能够得到及时执行,需要设置 daemon 任务的优先级高于使用此事件标志组的所有其它任务。

  1. 由于函数 xEventGroupSetBitsFromISR 对事件标志的置位操作是在 daemon 任务里面执行的, 如果
    想让置位操作立即生效,即让等此事件标志的任务能够得到及时执行,需要设置 daemon 任务的优先
    级高于使用此事件标志组的所有其它任务。
    2. 用户通过参数 uxBitsToSet 设置的标志位并不一定会保留到此函数的返回值中, 下面举两种情况:

a. 调用此函数的过程中,其它高优先级的任务就绪了,并且也修改了事件标志,此函数返回的事件标志位会发生变化。
b. 调用此函数的任务是一个低优先级任务, 通过此函数设置了事件标志后,让一个等待此事件标志的高优先级任务就绪了,会立即切换到高优先级任务去执行, 相应的事件标志位会被函数xEventGroupWaitBits 清除掉,等从高优先级任务返回到低优先级任务后, 函数xEventGroupSetBits 的返回值已经被修改。

等待事件标志位

EventBits_t xEventGroupWaitBits(EventGroupHandle_t xEventGroup,    /* 事件组句柄 */
                                const EventBits_t uxBitsToWaitFor, /* 等待被设置的事件标志位 */
                                const BaseType_t xClearOnExit,     /* 选择是否清除被置位的事件标志位 */
                                const BaseType_t xWaitForAllBits,  /* 是否等待所有标志位被置位 */
                                TickType_t xTicksToWait);          /* 超时事件 */

函数 xEventGroupWaitBits 等待事件标志被设置。

  • 第 1 个参数是事件标志组句柄。
  • 第 2 个参数表示等待事件标志位中的指定标志, EventBits_t 是定义的 32 位变量时低 24 位用于事件标志设置。 此参数切不可设置为 0。
  • 第 3 个参数选择是否清除已经被置位的事件标志, 如果这个参数设置为 pdTRUE, 且函数
    xEventGroupWaitBits 在参数 xTicksToWait 设置的溢出时间内返回,那么相应被设置的事件标志
    位在xEventGroupWaitBits()函数退出前会被清零。 如果这个参数设置为 pdFALSE,对已经被设置的事件标志位没有影响。
  • 第 4 个参数选择是否等待所有的标志位都被设置, 如果这个参数设置为 pdTRUE,要等待第 2 个参
    数 uxBitsToWaitFor 所指定的标志位全部被置 1, 函数才可以返回。当然,超出了在参数
    xTicksToWait 设置的溢出时间也是会返回的。如果这个参数设置为 pdFALSE, 第 2 个参数
    uxBitsToWaitFor 所指定的任何标志位被置 1, 函数都会返回, 超出溢出时间也会返回。
  • 第 5 个参数设置等待时间,单位时钟节拍周期。 如果设置为 portMAX_DELAY, 表示永久等待。
  • 返回值,由于设置的时间超时或者指定的事件标志位被置 1,导致函数退出时返回的事件标志组数值。第三个参数不会影响返回值。
  • 注意事项: 不要在中断中调用该函数

清除事件组标志位

EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup,
                                 const EventBits_t uxBitsToClear);

EventBits_t xEventGroupClearBitsFromISR(EventGroupHandle_t xEventGroup,
                                        const EventBits_t uxBitsToClear);

函数 xEventGroupClearBits 清除事件标志位。

  • 第 1 个参数是事件标志组句柄。
  • 第 2 个参数表示等待清除的指定标志, EventBits_t 是定义的 32 位变量时低 24 位用于事件标志设置。 此参数切不可设置为 0。
  • 返回值:清除前的事件组值。

本文参考 freertos官方文档 https://freertos.org/a00110.html
《野火-FreeRTOS 内核实现与应用开发实战指南》
《安富莱 STM32-V6 开发板 FreeRTOS 教程》

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值