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