FreeRTOS事件组之事件组置位(xEventGroupSetBits)

(1)第一种情况描述如下(最简单的情况)

           事件组的xTasksWaitingForBits下面没有挂载任何东西,而且uxEventBits=0;相当于调用xEventGroupCreate之后马上执行xEventGroupSetBits。

       

#define BIT_0 (1 << 0 )

#define BIT_4 (1 << 4 )

xEventGroup =xEventGroupCreate()

uxBits =xEventGroupSetBits (xEventGroup, /* The event group being tested. */

                                                              BIT_0 | BIT_4),/* The bits within the eventgroup to wait for. */


执行之前的内存状态为:

        


xEventGroupSetBits中所做的工作有:

uxEventBits的第bit0bit4置位。之后退出函数并返回uxEventBits的值。

(2)第二种情况描述如下

      事件组的xTasksWaitingForBits下面挂载一个节点,而且uxEventBits=0,这个节点以及具体内存情况见我的博客xEventGroupWaitBits的情况(1)。等效程序执行代码如下

下面两句代码是在在任务TCB_First中对应的代码中执行的:

xEventGroup =xEventGroupCreate();

uxBits = xEventGroupWaitBits(

xEventGroup, /*The event group being tested. */

BIT_0 | BIT_4, /* The bits within the eventgroup to wait for. */

pdTRUE,     /* BIT_0 & BIT_4 should be cleared before returning.

xClearOnExit在返回之前需要将第0位和第4位清楚*/

pdFALSE,     /* Don't wait for both bits, either bit will do.不是等待所有都要置                               xWaitForAllBits 位,只要有一个满足条件就好*/

xTicksToWait); /* Waita maximum of 100ms for either bit to be set. */

      执行之后的的内存情况如下:


之后由于发生任务调度,任务TCB_Second得到执行执行:

uxBits =xEventGroupSetBits (xEventGroup, /* The event group being tested. */

BIT_0 | BIT_4)/* The bits within the eventgroup to wait for. */

        由于此时在xTasksWaitingForBits中挂载了节点,和本文的情况(1)出现了不同情形。在这种情况下xEventGroupSetBits 内部所进行的操作有:

  • 首先将uxEventBits设置成BIT_0 | BIT_4(执行的过程是uxEventBits |= BIT_0 | BIT_4
  • 由于xTasksWaitingForBits链表中有节点存在,得到xTasksWaitingForBits链表中每一个节点xEventListItemxItemValue值(TCB_First),分别提取xItemValue中的控制位(第24~31位)和等待事件位(xItemValue中的第0到第23位)。
  •  将等待事件位(xItemValue中的第0到第23位)和xEventGroupuxEventBits进行比较,由于TCB_First并不是等待BIT_0 BIT_4同时置位,所以当前uxEventBits的值满足TCB_First的要求(在本例中,只要uxEventBits中有一个位和xItemValue0到第23位中的BIT_0 BIT_4位一样就满足了TCB_First的要求)(可以这样理解,xEventListItemxItemValue提出要求,而uxEventBits是用来满足这种要求的),如果满足要求就标记xMatchFound为pdTrue(在本例中是满足要求的因此标记为pdTrue)。
  • 如果xMatchFound为pdTrue,将TCB_First的xEventListItemxItemValue的值修改uxEventBits|eventUNBLOCKED_DUE_TO_BIT_SETeventUNBLOCKED_DUE_TO_BIT_SET用来标志记录解挂原因)更新完的xItemValue中记录的是解挂原因以及到底是什么样的uxEventBits使TCB_First解挂的。
  • xEventListItemxStateListItem分别从xTasksWaitingForBits链表pxDelayedTaskList链表中删除,并且将任务控制块TCB_First放到相应的就绪链表中,如果TCB_First任务控制块的优先级大于当前任务控制块的优先级,则标记需要进行任务调度,标记记录在xYieldPending(是个全局变量)中。(需要注意的是如果xTasksWaitingForBits链表中不只有一个xEventListItem节点时,需要遍历xTasksWaitingForBits链表,如果节点都满足要求则会将所有节点TCB都解挂,如果没有一个节点xMatchFound,也不清零,直接返回uxEventBits的值,然后退出函数)。
  •  如果在TCB_First的xEventGroupWaitBits中输入参数xClearOnExit设置为pdTrue,要将uxEventBits相应位清零(需要清除哪些位是TCB_FirstxEventListItemxItemValue第0~23位中置位的那些位)这点一定要注意xClearOnExit是在xEventGroupSetBits中完成的,而且清零操作是在遍历完xTasksWaitingForBits链表中所有xEventListItem节点之后,统一清零的
  • 然后根据xYieldPending是否为pdTrue,在xTaskResumeAll中发生任务调度。

  • 当调度回来再次执行本任务控制块的时候,则返回当前uxEventBits值(注意此时uxEventBits值的值不一定是0,因为其他函数可能也会调用xEventGroupSetBits












<think>好的,我需要回答用户关于FreeRTOS事件组与裸机事件驱动区别及用法的问题。首先,我需要理解两者的基本概念和工作原理。 首先,回忆一下FreeRTOS事件组。根据引用[2],FreeRTOS事件组可以通过动态或静态方式创建,用于任务间的事件通知和同步。事件组允许任务等待多个事件中的任意一个或全部发生,支持操作,每个事件对应一个。 接下来,裸机事件驱动通常是在没有操作系统的情况下,通过中断和全局变量来处理事件。例如,在轮询或中断服务程序中设标志,主循环中检查这些标志并执行相应操作。 用户想知道两者的区别和使用场景。我需要从机制、资源占用、同步能力、实时性等方面进行比较。比如,FreeRTOS事件组是多任务环境下的机制,支持复杂的同步,而裸机事件驱动更简单但功能有限。 还要考虑使用场景。根据引用[1],FreeRTOS适合实时性要求高的应用,而裸机可能适合资源受限的系统。引用[4]提到定时器驱动在裸机中的局限性,可能影响事件处理的效率。 需要确保回答结构清晰,分点说明区别和用法,并引用提供的资料。同时生成相关问题,如实现机制对比、如何选择等。 最后检查是否符合用户要求:使用正确的中文,LaTeX格式无误,引用标注正确,问题相关且合理。</think>### FreeRTOS事件组 vs 裸机事件驱动的区别与用法 #### 1. **核心机制对比** - **FreeRTOS事件组** 基于实时操作系统(RTOS),通过任务间同步机制实现事件管理。每个事件对应一个二进制(bit),支持多任务同时等待多个事件,并可通过逻辑运算(如“与”或“或”)触发响应[^2]。例如: ```c // 等待事件0和1同时 xEventGroupWaitBits(eventGroup, (1<<0 | 1<<1), pdTRUE, pdTRUE, portMAX_DELAY); ``` - **裸机事件驱动** 在单任务循环中通过全局变量或标志实现事件检测。通常依赖中断服务程序(ISR)设标志,主循环轮询标志并处理,例如: ```c volatile uint8_t event_flag = 0; // 中断中设标志 void ISR() { event_flag |= 0x01; } // 主循环中处理 while(1) { if(event_flag & 0x01) { /* 处理事件 */ } } ``` #### 2. **关键区别** | 特性 | FreeRTOS事件组 | 裸机事件驱动 | |---------------------|----------------------------------|--------------------------| | **多任务支持** | 原生支持多任务同步与优先级调度[^1] | 需手动管理任务切换与资源竞争 | | **事件组合逻辑** | 支持按操作与复杂逻辑条件 | 仅能通过简单条件判断 | | **资源占用** | 需要RTOS内存与调度开销[^3] | 无额外开销,适合资源受限场景 | | **实时性** | 高(依赖RTOS优先级抢占机制) | 依赖主循环轮询频率 | | **开发复杂度** | 需掌握RTOS API与任务设计 | 代码结构简单,调试直观 | #### 3. **典型使用场景** - **FreeRTOS事件组适用场景** - 多任务需协同完成复杂事件(如同时等待传感器数据和网络响应)。 - 实时性要求高的系统(如工业控制中紧急停机信号触发多任务响应)[^1][^4]。 - 需要动态创建/销毁事件组的场景(如物联网设备连接状态管理)。 - **裸机事件驱动适用场景** - 资源有限的微控制器(如8MCU)。 - 简单事件处理(如按键检测、定时器触发单次操作)。 - 无多任务需求或逻辑复杂度低的系统。 #### 4. **代码实现对比** - **FreeRTOS事件组示例** ```c // 创建事件组 EventGroupHandle_t xEventGroup = xEventGroupCreate(); // 任务A设事件0 xEventGroupSetBits(xEventGroup, (1 << 0)); // 任务B等待事件0和1 EventBits_t uxBits = xEventGroupWaitBits(xEventGroup, 0x03, pdTRUE, pdTRUE, 100/portTICK_PERIOD_MS); ``` - **裸机事件驱动示例** ```c // 全局标志 volatile uint8_t flags = 0; // 中断设标志 void Timer_ISR() { flags |= 0x01; } // 主循环处理 while(1) { if (flags & 0x01) { handle_event(); flags &= ~0x01; } } ``` #### 5. **选择建议** - 若需**多任务协作、复杂事件逻辑、高实时性**,优先选择FreeRTOS事件组。 - 若**硬件资源紧张、功能简单、无实时性强制要求**,裸机事件驱动更合适。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值