天天看点

FreeRTOS事件组----任务同步

有时,应用程序的设计需要两个或多个任务才能彼此同步。例如,考虑一个设计,其中任务A接收一个事件,然后将事件所需的一些处理提供给其他三个任务:任务B,任务C和任务D。如果任务A在任务B,C和D已经全部完成了对上一个事件的处理,那么所有这四个任务将需要彼此同步。每个任务的同步点将在该任务完成其处理之后,并且无法继续进行,直到其他每个任务都完成了相同的任务。在所有四个任务都达到其同步点之后,任务A才能接收另一个事件。

事件组可用于创建同步点:

  1. 必须在同步组中为每个必须参与同步的任务分配一个唯一的事件位。
  2. 每个任务到达同步点时都会设置自己的事件位。
  3. 设置好自己的事件位后,事件组中的每个任务块都将等待代表所有其他同步任务的事件位也被置位。

但是,在这种情况下不能使用xEventGroupSetBits()和xEventGroupWaitBits()API函数。如果使用它们,则将位的设置(以指示任务已到达其同步点)和位的测试(以确定其他同步任务是否已到达其同步点)将作为两个单独的操作执行。若要查看为什么会出现问题,请考虑以下情形:任务A,任务B和任务C尝试使用事件组进行同步:

★任务A和任务B已经到达同步点,因此它们的事件位在事件组中已设置,并且它们处于“阻塞”状态,等待任务C的事件位也被置位。

★任务C到达同步点,并使用xEventGroupSetBits()设置其在事件组中的位。一旦设置了任务C的位,任务A和任务B就会退出“阻塞”状态,并清除所有三个事件位。

★然后,任务C调用xEventGroupWaitBits()等待所有三个事件位被置位,但是到那时,所有三个事件位已经被清除,任务A和任务B离开了各自的同步点,因此同步失败了。 。

若要成功使用事件组创建同步点,必须将事件位的设置以及事件位的后续测试作为单个不间断操作执行。为此提供了xEventGroupSync()API函数。

xEventGroupSync()API 函数

xEventGroupSync函数,允许两个或多个任务使用一个事件组相互同步。该函数允许任务在事件组中设置一个或多个事件位。然后等待事件位的组合在同一事件组中被设置为单个不可中断的操作。

xEventGroupSync()函数中的uxBitsToWaitFor参数是指定调用任务的解除阻塞条件。如果xEventGroupSync()因为已满足解除阻塞条件而返回,则在xEventGroupSync()返回之前,将uxBitsToWaitFor指定的事件位清零。

EventBits_t xEventGroupSync(EventGroupHandle_t xEventGroup,
                            const EventBits_t uxBitsToSet,
                            const EventBits_t uxBitsToWaitFor,
                            TickType_t xTicksToWait);
           
                                              xEventGroupSync()参数和返回值
参数名称                                                      描述
xEventGroup 事件组的句柄,用来在其中设置事件位,然后对其进行测试。事件组句柄是创建事件组的xEventGroupCreate()的调用的返回值。
uxBitsToSet

一个位掩码,用于指定要在事件组中设置为1的一个或多个事件位。通过将事件组的现有值与uxBitsToSet中传递的值进行按位或运算,可以更新事件组的值。

例如,将uxBitsToSet设置为0x04(二进制0100)将导致事件位3被置位(如果尚未设置),而事件组中的所有其他事件位均保持不变。

uxBitsToWaitFor

位掩码,指定要在事件组中测试的一个或多个事件位。

例如,如果调用任务想要等待事件位0、1和2在事件组中被设置,则将uxBitsToWaitFor设置为0x07(二进制111)。

xTicksToWait

任务应保持在“阻塞”状态以等待其解除阻塞条件所需的最长时间。

如果xTicksToWait为零,或者在调用xEventGroupSync()时满足解锁条件,则xEventGroupSync()将立即返回。

块时间以滴答周期指定,因此它表示的绝对时间取决于滴答频率。宏pdMS_TO_TICKS()可用于将以毫秒为单位的时间转换为以刻度为单位的时间。

如果在FreeRTOSConfig.h中将INCLUDE_vTaskSuspend设置为1,则将xTicksToWait设置为portMAX_DELAY将导致任务无限期等待(无超时)。

返回值

如果由于满足调用任务的取消阻塞条件而返回xEventGroupSync(),则返回值是满足调用任务的取消阻塞条件时事件组的值(在自动将所有位清零之前)。在这种情况下,返回的值也将满足调用任务的解锁条件。

如果由于xTicksToWait参数指定的阻塞时间到期而返回xEventGroupSync(),则返回的值是阻塞时间到期时事件组的值。在这种情况下,返回的值将不满足调用任务的取消阻塞条件。

继续阅读