一、FreeRTOS事件组之事件组的创建(xEventGroupCreate())
1.使用事件组的前提:
(1)与互斥量、队列集等其他内核资源不同,想要使用事件组(xEventGroup)重点不在宏定义上是否配置为1,重点在组织程序以及程序编译的时候是否包括event_groups.c源代码以及event_groups.h头文件。
(2)另外需要将宏configSUPPORT_DYNAMIC_ALLOCATION设置为1,否则不能应用事件组创建函数(xEventGroupCreate());
2.函数说明(xEventGroupCreate()):
函数原型:EventGroupHandle_t xEventGroupCreate( void );
函数参数:void
返回值 :如果成功建立事件组,则会返回事件组的句柄(指针),如果内存堆没有足够的内存则会返回NULL(创建失败)。
3.执行过程分析:
事件组的结构体不是用队列实现的(互斥量,信号量,队列的结构体都是用队列来实现的),其有自己的结构体叫EventGroup_t。以代码为例来分析xEventGroupCreate()函数内部对内存数据的改变。
EventGroupHandle_t xCreatedEventGroup;
xCreatedEventedGroup=xEventGroupCreate();
执行完
xCreatedEventedGroup=xEventGroupCreate();
之后内存的状况为如下:(另外需要说明的是,事件组的建立对任务控制块的成员组成没有影响(与之对比,互斥量的使用就需要改变任务控制块的成员组成))。
二、FreeRTOS事件组之事件组等待位(xEventGroupWaitBits)
1.函数说明(xEventGroupWaitBits)
函数原型:
EventBits_t xEventGroupWaitBits(
const EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait );
函数参数:
(1)xEventGroup:
(2)uxBitsToWaitFor:
(3)xClearOnExit:
(4)xWaitForAllBits:
(5)xTicksToWai:
2.执行过程分析
(1)情况1(不满足事件发生条件):
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
xEventGroup =xEventGroupCreate();
uxBits = xEventGroupWaitBits(
xEventGroup, /* The event group being tested. */
BIT_0 | BIT_4, /* The bits within the event group to wait for. */
pdTRUE, /* BIT_0 & BIT_4 should be cleared before returning. 在返回之前需要将第0位和第4位清楚*/
pdFALSE, /* Don't wait for both bits, either bit will do. 不是等待所有都要置位, 只要有一个满足条件就好*/
xTicksToWait ); /* Wait a maximum of 100ms for either bit to be set. */
执行xEventGroupWaitBits之前内存状态如下:
首先要提取xEventGroup中的uxEventBits(其值和传入xEventGroupWaitBits的函数参数uxBitsToWaitFor进行比较来确定是否满足事件发生条件)的值,由于刚刚建立,所以uxEventBits=0。之后要检查是否事件发生条件,本例中设置的是判断部分位是否满足(xWaitForAllBits是pdFALSE),即uxEventBits中只要BIT_0 或BIT_4有一个位为1就可以。因为uxEventBits=0,因此不满足事件组发生条件。
之后要将函数传参xClearOnExit和xWaitForAllBits记录到xEventGroupWaitBits中的局部变量uxControlBits中(uxControlBits的bit24记录xClearOnExit,bit26用来记录xWaitForAllBits)。
此时将当前任务控制块TCB的xEventListItem节点的xItemValue(32位int类型)的0-23位设置成事件标志位(本例中为BIT_0 | BIT_4),xItemValue中的第24-31位设置成相应的控制位{xItemValue的32位数据分成两部分,其中第24-31位设置成相应的控制位,0~23是事件标志位,控制位来源于上一段的uxControlBits和第31位(用来标记当前任务控制块的xItemValue是否正在使用)}(在本例中,由于xClearOnExit是pdTRUE,因此将xItemValue的第24位置1,同时标记xItemValue第31位为1,表明本任务控制块的xEventListItem的xItemValue正在使用)。
之后利用vListInsertEnd函数将当前任务控制块的xEventListItem节点插入到xEventGroup的xTasksWaitingForBits链表中,并且将当前控制块TCB的xStateListItem节点从就绪任务链表中删除,并且将xStateListItem插入到pxDelayedTaskList链表中,并将下一个即将唤醒的pxDelayedTaskList中的节点的绝对时间记录到xNextTaskUnblockTime全局变量中。
之后执行xTaskResumeAll以发生任务调度(即使xTaskResumeAll内部没有发生任务调度,执行完xTaskResumeAll也会发生调度)。执行完上面的内容之后,内存中的数据结构情况如下:
上面内存变化情况总结是:
任务控制块TCB_First在等待一个事件(xEventGroup结构体中的uxEventBits的BIT_0 或BIT_4有一个位为1,而调用xEventGroupWaitBits就是判