FreeRTOS事件组(event group)及内部机制

简介

 

事件组概念与操作

事件组的概念

事件组可以简单地认为就是一个整数:
        --每一位表示一个事件。
        --每一位事件的含义由程序员决定,比如:Bit0 表示用来串口是否就绪,Bit1 表示按键是否被按,这些位,值为 1 表示事件发生了,值为 0 表示事件没发生。
        --一个或多个任务、ISR 都可以去写这些位;一个或多个任务、 ISR 都可以去读这些位。
        --可以等待某一位、某些位中的任意一个,也可以等待多位。
        事件组用一个整数来表示, 其中的高8位留给内核使用 ,只能用其他的位来表示事件。那么这个整数是多少位的?

 

事件组的操作

事件组和队列、信号量等不太一样,主要集中在 2 个地方:
唤醒谁?

        1、队列、信号量:事件发生时,只会唤醒一个任务。

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

是否清除事件? 

        1、队列、信号量:是消耗型的资源,队列的数据被读走就没了;信号量被获取之后就减少了。

        2、事件组:被唤醒的任务有两个选择,可以让事件保留不动,也可以清除事件。

以上图为列,事件组的常规操作如下:
1、先创建事件组
2、任务 CD 等待事件
      等待什么事件?可以等待某一位、某些位中的任意一个,也可以等待多位。
      简单地说就是" " " " 的关系。 得到事件时,要不要清除?可选择清除、不清除。
3、任务 AB 产生事件:设置事件组里的某一位、某些位。

事件组函数

创建

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

删除 

         vEventGroupDelete 可以用来删除事件组,函数原型如下:

 设置事件 

        函数原型如下: 

        值得注意的是,ISR 中的函数,比如队列函数 xQueueSendToBackFromISR 、信号量函数 xSemaphoreGiveFromISR ,它们会唤醒某个任务,最多只会唤醒 1 个任务。
         但是设置事件组时,有可能导致多个任务被唤醒, 这会带来很大的不确定性。所以 xEventGroupSetBitsFromISR 函数不是直接去设置事件组,而 是给一个 FreeRTOS 后台任务(daemon task)发送队列数据,由这个任务来设置事件组。
        如果后台任务的优先级比当前被中断的任务优先级 xEventGroupSetBitsFromISR 会设置 *pxHigherPriorityTaskWoken pdTRUE 。如果daemon task 成功地把队列数据发送给了后台任务,那么 xEventGroupSetBitsFromISR 的返回值就是 pdPASS

 等待事件

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

 函数原型如下:

 

 函数参数说明列表如下:

举例一下:

 

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

同步点

有一个事情需要多个任务协同,比如:
xEventGroupSync 函数原型如下:

 事件组的内部机制

前面讲的是事件组的基本使用,我们这里研究一下他的内部机制。

核心是:关调度器、位操作、链表

我们先看一下事件组的结构体:

 

 

一个位操作来表示事件组的每个事件、一个等待事件的任务链表用于阻塞到不满足事件的任务。 

 怎么互斥访问数据(关调度器)

        

这里还是老套路了,访问这种信息量的时候,直接暴力点,关闭调度器,还是按之前那套,如果成功访问,就获得所谓的信息量,如果访问失败,那就进入阻塞状态,把任务丢进去阻塞链表里面。

位操作

设置位
等待位

 

等到位就好说,直接一套流程走完,成功获取事件组,如果说期待的位还没有设置,那就按之前说的,去到阻塞链表里面,等待事件组被设置成功之后,在被唤醒。

链表

唤醒所有符合条件的任务

等待位的时候,条件不满足则会休眠

 

总结

其实事件组和前面讲的信息量啊,互斥量啊,队列那些几乎都很像了,FreeRTOS的核心就是“调度”,只要你看懂”调度“,那么内部实现的原理你也就能迎刃而解了,当然,提醒一下,无需每条代码都要看懂,大概知道这些代码干什么的就行,毕竟,我们RTOS相比裸机开发已经很高级,越高级越不需要弄底层,大概知道就行了。 

 

相关推荐

  1. 11.FreeRTOS_事件

    2024-07-15 01:06:03       19 阅读
  2. FreeRTOS学习笔记-基于stm32(10)事件标志

    2024-07-15 01:06:03       31 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-15 01:06:03       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-15 01:06:03       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-15 01:06:03       58 阅读
  4. Python语言-面向对象

    2024-07-15 01:06:03       69 阅读

热门阅读

  1. 【FPGA】Verilog 中 typedef enum 用法教程

    2024-07-15 01:06:03       18 阅读
  2. React@16.x(58)Redux@4.x(7)- 实现 combineReducers

    2024-07-15 01:06:03       21 阅读
  3. springsecurity01

    2024-07-15 01:06:03       15 阅读
  4. this指向解析

    2024-07-15 01:06:03       22 阅读
  5. AI究竟是在帮助开发者还是取代他们?

    2024-07-15 01:06:03       20 阅读
  6. C语言 判断素数

    2024-07-15 01:06:03       19 阅读
  7. ios CCRectangleBlock.m

    2024-07-15 01:06:03       17 阅读
  8. Spring之常见注解

    2024-07-15 01:06:03       19 阅读
  9. Golang 后端面经

    2024-07-15 01:06:03       21 阅读
  10. 印度标普基金关门,继续套利美元债LOF

    2024-07-15 01:06:03       20 阅读
  11. 基于深度学习的点云平滑

    2024-07-15 01:06:03       19 阅读
  12. 【网络编程】poll函数

    2024-07-15 01:06:03       18 阅读