ESP32 FreeRTOS-事件组(10)

提示:好记性不如烂笔头。本博客作为学习笔记,有错误的地方希望指正

前言:

  参考资料:FreeRTOS API参考
  事件组我们可以实现多个任务同时等待一个事件,或者多个事件中一个事件执发生之后的检测,实现事件的同步和事件等待。

一、xEventGroupCreate()

API原型:

EventGroupHandle_t xEventGroupCreate( void );

  创建一个新的 RTOS 事件组,并返回 可以引用新创建的事件组的句柄。

  要使此 RTOS API 函数可用:

  1. configSUPPORT_DYNAMIC_ALLOCATION 必须在 FreeRTOSConfig.h 中设置为 1,或保留未定义状态(此时 默认为 1)。
  2. RTOS 源文件 FreeRTOS/source/event_groups.c 必须 包含在构建中。
    每个事件组都需要非常少量 RAM 来保存 事件组的状态。 如果使用 xEventGroupCreate() 创建事件组, 则会从 RAM 堆FreeRTOS中自动分配所需的 。 如果使用 xEventGroupCreateStatic() 创建事件组 则 RAM 由应用程序编写者提供,这需要用到一个附加参数, 但允许在编译时静态分配 RAM 。 请参阅静态分配与 动态分配页面了解更多信息。

  事件组存储在 EventBits_t 类型的变量中。 如 果 configUSE_16_bit_TICKS 设置为 1,则事件组内实现的位(或标志)数为 8; 如果 configUSE_16_bit_TICKS 设置为 0,则为 24。 依赖于 configUSE_16_BIT_TICKS 的值 取决于 RTOS 任务内部实现中用于线程本地存储的数据类型。
返回值:
  如果创建了事件组, 则返回事件组的句柄。 如果没有足够的 FreeRTOS 堆可用于创建事件组, 则返回 NULL。
用法示例:

    /* 声明一个变量,以保存创建的事件组。*/
    EventGroupHandle_t xCreatedEventGroup。
    /* 尝试创建事件组。*/
    xCreatedEventGroup = xEventGroupCreate();

    /* 是否成功创建了该事件组?*/
    if( xCreatedEventGroup == NULL )
    {
    
    
        /* 该事件组没有被创建,因为没有足够的
        导致事件组没有被创建,因为没有足够的FreeRTOS堆可用。*/
    }
    else
    {
    
    
        /* 该事件组已创建。*/
    }

二、xEventGroupCreateStatic()

API原型:

EventGroupHandle_t xEventGroupCreateStatic(StaticEventGroup_t *pxEventGroupBuffer );

  创建一个新的 RTOS 事件组,并返回 可以引用新创建的事件组的句柄。 configSUPPORT_STATIC_ALLOCATION 必须在 FreeRTOSConfig.h 中设置为 1,并且 RTOS 源文件 FreeRTOS/source/event_groups.c 必须 包含在构建中,xEventGroupCreateStatic() 函数才可用。
  每个事件组都需要[非常]少量 RAM 来保存 事件组的状态。 如果使用 xEventGroupCreate() 创建事件组, 则会从 RAM 堆FreeRTOS中自动分配所需的 。 如果使用 xEventGroupCreateStatic() 创建事件组, 则 RAM 由应用程序编写者提供,这需要用到一个附加参数, 但允许在编译时静态分配 RAM 。 请参阅静态分配与 动态分配页面了解更多信息。
  事件组存储在 EventBits_t 类型的变量中。 如 果 configUSE_16_bit_TICKS 设置为 1,则事件组内实现的位(或标志)数为 8; 如果 configUSE_16_bit_TICKS 设置为 0,则为 24。 依赖于 configUSE_16_BIT_TICKS 的值 取决于 RTOS 任务内部实现中用于线程本地存储的数据类型。
参数
  pxEventGroupBuffer 必须指向 StaticEventGroup_t 类型的变量, 该变量用于存储事件组数据结构体。
返回值:
  如果成功创建了事件组, 则返回事件组的句柄。 如果 pxEventGroupBuffer 为 NULL,则返回 NULL。

用法示例:

/* 声明一个变量,以保持创建的事件组的句柄。*/
EventGroupHandle_t xEventGroupHandle;

/* 声明一个变量,用于保存与所创建的事件组相关的数据。
事件组相关的数据。*/
StaticEventGroup_t xCreatedEventGroup;

/* 尝试创建事件组。*/
xEventGroupHandle = xEventGroupCreateStatic( &xCreatedEventGroup );

/* pxEventGroupBuffer不是空的,所以希望事件组已经创建?
已经创建了?*/
configASSERT( xEventGroupHandle );

三、vEventGroupDelete()

API原型:

void vEventGroupDelete( EventGroupHandle_t xEventGroup );

   删除先前的事件组, 该事件组通过调用 xEventGroupCreate() 创建。
  在被删除的事件组上阻塞的任务将被取消阻塞,并且 报告事件组值为 0。
  要使 vEventGroupDelete() 函数可用,RTOS 源文件 FreeRTOS/source/event_groups.c 必须 包含在构建中。
  无法从中断调用此函数。
参数
  xEventGroup 要删除的事件组。

四、xEventGroupWaitBits()

API原型:

EventBits_t xEventGroupWaitBits(
                      const EventGroupHandle_t xEventGroup,
                      const EventBits_t uxBitsToWaitFor,
                      const BaseType_t xClearOnExit,
                      const BaseType_t xWaitForAllBits,
                      TickType_t xTicksToWait );

  读取 RTOS 事件组中的位,选择性地进入“已阻塞”状态(已设置 超时值)以等待设置单个位或一组位。无法从中断调用此函数。
  要使 xEventGroupWaitBits() 函数可用,RTOS 源文件 FreeRTOS/source/event_groups.c 必须 包含在构建中。
参数
  xEventGroup 正在测试位的事件组。 此前 必须已通过 xEventGroupCreate() 创建好事件组。
  uxBitsToWaitFor 指定事件组中要测试的一个或多个事件位 的按位值。 例如,要等待第 0 位和/或第 2 位, 请将 uxBitsToWaitFor 设置为 0x05。 要等待第 0 位和/或第 1 位和/或第 2 位, 请设置 uxBitsToWaitFor 为 0x07, 以此类推。
uxBitsToWaitFor 不得设置为 0。
  xClearOnExit 如果 xClearOnExit 设置为 pdTRUE, 那么在作为 uxBitsToWaitFor 参数传递的值中设置的任何位 会在 xEventGroupWaitBits() 返回某个值之前在事件组中清除掉, 前提是 xEventGroupWaitBits() 因超时以外的原因而返回值 。 超时值由 xTicksToWait 参数设置。
如果 xClearOnExit 设置为 pdFALSE, 那么当调用 xEventGroupWaitBits() 返回时,事件组中设置的位不会改变。
  xWaitForAllBits xWaitForAllBits 用于创建逻辑与测试 (必须设置所有位)或逻辑或测试(必须设置一个 或多个位),如下所示:
如果 xWaitForAllBits 设置为 pdTRUE, 那么当在作为 uxBitsToWaitFor 参数传递的值中设置的所有位 均已在事件组中设置好,或指定的阻塞时间已过期,则 xEventGroupWaitBits() 会返回相应值。
如果 xWaitForAllBits 设置为 pdFALSE,那么当在作为 uxBitsToWaitFor 参数传递的值中设置的任何位已在事件组中设置好, 或指定的阻塞时间已过期,则 xEventGroupWaitBits() 会返回相应值。
  xTicksToWait 等待 uxBitsToWaitFor 指定的一个/所有(取决于 xWaitForAllBits 的值)位完成设置的最大时间 (单位:tick)。
返回值:
  事件位等待完成设置或阻塞时间过期时 的事件组值。 如果 高优先级任务或中断在调用任务解除“已阻塞”状态和退出 xEventGroupWaitBits() 函数之间更改了事件位的值, 则事件组中事件位的当前值将与返回值不同 。
  测试返回值以确定 哪些位已完成设置。 如果 xEventGroupWaitBits() 因为超时值过期而返回, 则并非在等待的所有位都会进行设置。 如果 xEventGroupWaitBits() 因为它所等待的位均已完成设置而返回相应值, 则返回值是自动清除 (原因是 xClearOnExit 参数设置为 pdTRUE)任何位之前的事件组值。
用法示例:

#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )

void aFunction( EventGroupHandle_t xEventGroup )
{
    
    
	EventBits_t uxBits;
	const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;

	/* 在事件组中,最多等待100ms,等待第0位或第4位被设置。
	事件组中的第0位或第4位被设置。 在退出前清除这些位。*/
	uxBits = xEventGroupWaitBits(
	          xEventGroup, /*被测试的事件组。*/
	          BIT_0 | BIT_4, /*事件组中要等待的位。*/
	          pdTRUE, /* BIT_0 & BIT_4在返回前应被清除。*/
	          pdFALSE, /*不要等待这两个位,任何一个位都可以。*/
	          xTicksToWait );/*最多等待100ms,让任一比特被设置。*/

	if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
	{
    
    
	    /* xEventGroupWaitBits() 返回,因为两个位都被设置了。*/
	}
	else if( ( uxBits & BIT_0 ) != 0 )
	{
    
    
	    /* xEventGroupWaitBits() 返回,因为只有BIT_0被设置。*/
	}
	else if( ( uxBits & BIT_4 ) != 0 )
	{
    
    
	    /* xEventGroupWaitBits()返回,因为只有BIT_4被设置了。*/
	}
	else
	{
    
    
	    /* xEventGroupWaitBits()返回,因为xTicksToWait ticks通过了,但BIT_0或BIT_4没有被设置。
	    没有设置BIT_0或BIT_4。*/
	}
}

五、xEventGroupSetBits()

API原型:

EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToSet );

  在 RTOS 事件组中设置位(标志)。 无法从中断调用此函数。 xEventGroupSetBitsFromISR() 是可从中断调用的版本。
  在事件组中设置位将自动解除 所有等待位的任务的阻塞态。
  RTOS 源文件 FreeRTOS/source/event_groups.c 必须 包含在构建中,xEventGroupSetBits() 函数才可用。
参数
  xEventGroup 要设置位的事件组。 该 必须已通过 通过调用 xEventGroupCreate() 创建。
  uxBitsToSet 指定要在事件组中设置的一个或多个位的按位值。 例如,将 uxBitsToSet 设置为 0x08,可仅设置位 3。 将 uxBitsToSet 设置 为 0x09,可设置位 3 和位 0。
返回值:
  调用 xEventGroupSetBits() 返回时事件组的值。
  返回值可能会 清除 uxBitsToSet 参数指定的位,有如下两个原因:

  1. 如果设置某个位导致正在等待该位的任务 解除阻塞态, 则可能该位 已被自动清除(请参阅 xEventGroupWaitBits() 的 xClearBitOnExit 参数)。
  2. 将执行任何处于阻塞态(或就绪态)且优先级 高于调用 xEventGroupSetBits() 的任务, 并可能在调用 xEventGroupSetBits() 返回之前 更改事件组值。
    用法示例:
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )

void aFunction( EventGroupHandle_t xEventGroup )
{
    
    
	EventBits_t uxBits;

  /* 设置xEventGroup中的位0和位4。*/
  uxBits = xEventGroupSetBits(
                              xEventGroup, /* 被更新的事件组。*/
                              BIT_0 | BIT_4 );/*被设置的位。*/

  if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
  {
    
    
      /* 函数返回时,位0和位4都保持设置。*/
  }
  else if( ( uxBits & BIT_0 ) != 0 )
  {
    
    
      /* 当函数返回时,第0位仍然被设置,但第4位被清除。
      被清除了。 这可能是位4被自动清除了,因为一个等待位4的任务被从Block中删除了。
      可能是位4被自动清除了,因为等待位4的任务被从阻塞状态移除。
      状态。*/
  }
  else if( ( uxBits & BIT_4 ) != 0 )
  {
    
    
      /* 当函数返回时,第4位仍然被设置,但第0位被清除。
      位被清除了。 这可能是位0被自动清除了,因为一个等待位0的任务被从块中删除了。
      可能是位0被自动清除了,因为等待位0的任务被从阻塞状态中移除。
      状态。*/
  }
  else
  {
    
    
      /* 位0和位4都没有被设置。 这可能是一个任务
      可能是一个任务在等待这两个位被设置,而这两个位在任务离开阻塞状态时被清除了。
      当任务离开阻塞状态时,该位被清除。*/
  }
}

六、xEventGroupSetBitsFromISR()

API原型:

BaseType_t xEventGroupSetBitsFromISR(
                          EventGroupHandle_t xEventGroup,
                          const EventBits_t uxBitsToSet,
                          BaseType_t *pxHigherPriorityTaskWoken );

  在RTOS 事件组中设置位(标志)。 可以从中断服务程序 (ISR) 调用的 xEventGroupSetBits() 版本 。
  在事件组中设置位将自动解除 所有等待位的任务的阻塞状态。
  在事件组中设置位不是确定性操作,因为 可能有未知数量的任务正在等待设置一个 或多个位。 FreeRTOS 不允许在中断或临界区 中执行不确定的操作。 因此, xEventGroupSetBitFromISR() 会向 RTOS 守护进程任务发送一条消息, 从而在守护进程任务的上下文中执行设置操作,其中使用的是调度器锁 而非临界区。
  注意: 如上文所述,从中断服务程序中设置位 会将设置操作推迟到 RTOS 守护进程任务(也叫定时器服务任务) 。 RTOS守护进程任务 与其他RTOS任务一样, 都是根据优先级进行调度的。 因此,如果置位操作必须立即完成 (在应用程序创建的任务执行之前), 那么RTOS守护进程任务的优先级必须要高于 其他使用事件组的任务。 RTOS守护进程任务的优先级由 configTIMER_TASK_PRIORITY 在FreeRTOSConfig.h中定义。
  INCLUDE_xEventGroupSetBitFromISR, configUSE_TIMERS 和INCLUDE_xTimerPendFunctionCall 必须在FreeRTOSConfig.h中全部设置为1,才能使用xEventGroupSetBitsFromISR() 函数。
  RTOS源文件 FreeRTOS/source/event_groups.c 必须 包含在构建中,才能使用xEventGroupSetBitsFromISR()函数。
参数
  xEventGroup 要设置位的事件组。 该 必须已通过 通过调用 xEventGroupCreate() 创建。
  uxBitsToSet 指定要设置的一个或多个位的按位值。 例如,要设置位3,便将uxBitsToSet设置为0x08。 将 uxBitsToSet 设置 位3和位0,便将uxBitsToSet设置为0x09。
  pxHigherPriorityTaskWoken 如上所述,调用此函数 将意味着给RTOS守护进程任务发送一条消息。 如果 守护进程任务的优先级高于 当前正在运行的任务(中断中断的任务), 那么xEventGroupSetBitsFromISR()会将*pxHigherPriorityTaskWoken设置为pdTRUE, 指示应在中断退出之前 请求上下文切换。 因此 必须将 *pxHigherPriorityTaskWoken 初始化为 pdFALSE。 请参阅 下面的代码示例。
返回值:
  如果消息已发送到RTOS守护进程任务,则返回pdPASS, 否则将返回pdFAIL。 如果 计时器服务队列已满,则将返回pdFAIL 。
用法示例:

#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )

/* 一个事件组,它被认为已经通过调用
xEventGroupCreate()创建的事件组。*/
EventGroupHandle_t xEventGroup;

void anInterruptHandler( void )
{
    
    
	BaseType_t xHigherPriorityTaskWoken, xResult;

	/* xHigherPriorityTaskWoken必须被初始化为pdFALSE。*/
	xHigherPriorityTaskWoken = pdFALSE;
	
	/* 设置xEventGroup中的位0和位4。*/
	xResult = xEventGroupSetBitsFromISR(
	                           xEventGroup, /*被更新的事件组。*/
	                           BIT_0 | BIT_4, /*被设置的位。*/
	                           &xHigherPriorityTaskWoken )。
	
	/* 消息是否成功发布?*/
	if( xResult != pdFAIL )
	{
    
    
		/* 如果xHigherPriorityTaskWoken现在被设置为pdTRUE,那么应该请求进行上下文切换。
		则应请求进行上下文切换。 使用的宏是特定于端口的,将是
		是portYIELD_FROM_ISR()或portEND_SWITCHING_ISR()--请参考所使用的端口的文档。
		参考正在使用的端口的文档页面。*/
		portYIELD_FROM_ISR( xHigherPriorityTaskWoken )}
}

七、xEventGroupClearBits()

API原型:

EventBits_t xEventGroupClearBits(
                                EventGroupHandle_t xEventGroup,
                                const EventBits_t uxBitsToClear );

  清除 RTOS 事件组中的位(标志)。 无法从中断调用此函数 。 有关可从中断调用的版本,请参阅 xEventGroupClearBitsFromISR() 。
  RTOS 源文件 FreeRTOS/source/event_groups.c 必须 包含在 xEventGroupClearBits() 函数可用的构建中。
参数
  xEventGroup 要在其中清除位的事件组。 此事件组 必须已通过 调用 xEventGroupCreate() 事先创建。
  uxBitsToClear 表示要在事件组中清除一个或多个位的 按位值。 例如,将 uxBitsToClear 设置为 0x08 以仅清除位 3。 将 uxBitsToClear 设置为 0x09 以清除位 3 和位 0。
返回值:
  清除指定位之前的事件组的值。
用法示例:

#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )

void aFunction( EventGroupHandle_t xEventGroup )
{
    
    
  EventBits_t uxBits;

  /* 清除xEventGroup中的第0位和第4位。*/
  uxBits = xEventGroupClearBits(
                                xEventGroup, /* 被更新的事件组。*/
                                BIT_0 | BIT_4 );/* 被清除的位。*/

  if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
  {
    
    
      /* 在调用xEventGroupClearBits()之前,位0和位4都被设置。
      被调用之前,位0和位4都被设置了。 现在这两个都将被清除(不设置)。*/
  }
  else if( ( uxBits & BIT_0 ) != 0 )
  {
    
    
      /* 在调用xEventGroupClearBits()之前,位0被设置。 它将
      现在将被清除。*/
  }
  else if( ( uxBits & BIT_4 ) != 0 )
  {
    
    
      /* 在调用xEventGroupClearBits()之前,位4被设置了。 它将
      现在将被清除。*/
  }
  else
  {
    
    
      /* 第0位和第4位一开始都没有被设置。*/
  }
}

八、xEventGroupClearBitsFromISR()

API原型:

BaseType_t xEventGroupClearBitsFromISR(
                               EventGroupHandle_t xEventGroup,
                               const EventBits_t uxBitsToClear );

  可以从中断调用的 xEventGroupClearBits() 版本 。 清除操作被延迟为 RTOS 守护进程任务,也称为定时器服务任务。 守护进程任务的 优先级由 configTIMER_TASK_PRIORITY FreeRTOSConfig.h 中的设置来设定。
  要使 xEventGroupClearBitsFromISR() 函数可用,RTOS 源文件 FreeRTOS/source/event_groups.c 必须 包含在构建中。
参数
  xEventGroup 要在其中清除位的事件组。 此事件组 必须已通过 调用 xEventGroupCreate() 事先创建。
  uxBitsToClear 表示要在事件组中清除一个或多个位的 按位值。 例如,将 uxBitsToClear 设置为 0x08 以仅清除位 3。 将 uxBitsToClear 设置为 0x09 以清除位 3 和位 0。
返回值:
  如果操作已成功延迟为 RTOS 守护进程任务,则返回 pdPASS。 否则返回 pdFALSE。 只有当定时器命令队列已满时,才会返回 pdFALSE。
用法示例:

#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )

/* 这段代码假定由xEventGroup变量所引用的事件组已经通过调用
xEventGroup变量所引用的事件组已经被创建,并通过调用
xEventGroupCreate()创建的. */
void anInterruptHandler( void )
{
    
    
  BaseType_t xSuccess;

  /* 清除xEventGroup中的第0和第4位。*/
  xSuccess = xEventGroupClearBitsFromISR(
                                xEventGroup, /*被更新的事件组。*/
                                BIT_0 | BIT_4 );/*被清除的位。*/

  if( xSuccess == pdPASS )
  {
    
    
      /* 该命令被发送到守护任务中。*/
  }
  else
  {
    
    
      /* 该清除比特的命令没有被发送到守护任务中。*/
  }
}

九、xEventGroupGetBits()

API原型:

EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );

  返回RTOS 事件组中事件位(事件标志)的当前值。 不能从中断使用此函数。 可以在中断中使用的版本请参阅 xEventGroupGetBitsFromISR() 。
  RTOS源文件 FreeRTOS/source/event_groups.c 必须 包含在构建中,才能使用xEventGroupGetBits()函数。
参数
  xEventGroup 正在查询的事件组。 该 必须已通过 xEventGroupCreate()创建的。
返回值:
  调用xEventGroupGetBits()时,事件组中的 事件组中事件位的值。

十、xEventGroupGetBitsFromISR()

API原型:

EventBits_t xEventGroupGetBitsFromISR(EventGroupHandle_t xEventGroup );

  可从中断调用的 xEventGroupGetBits() 的 版本。
  RTOS 源文件 FreeRTOS/source/event_groups.c 必须 包含在构建中,xEventGroupGetBitsFrom() 函数才可使用。
参数
  xEventGroup 正在查询的事件组。 该 必须已通过 通过调用 xEventGroupCreate() 创建。
返回值:
  调用 XEventGroupGetBitsFromISR() 时, 事件组中事件位的值。

十一、xEventGroupSync()

API原型:

EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
                             const EventBits_t uxBitsToSet,
                             const EventBits_t uxBitsToWaitFor,
                             TickType_t xTicksToWait );

  以原子方式设置RTOS 事件组中的位(标志),然后等待 在同一事件组中设置位的组合。 此功能通常 用于同步多个任务(通常称为任务集合),其中每个 任务必须等待其他任务到达同步点 才能继续。
  不能从中断使用此函数。
  如果设置了 uxBitsToWait 参数指定的位, 或者在该时间内设置了这些位,则该函数将在其阻塞时间到期之前返回。 在 这种情况下,uxBitsToWait 指定的所有位将在 函数返回之前自动清除。
  RTOS源文件 FreeRTOS/source/event_groups.c 必须 包含在构建中,确保 xEventGroupSync()函数可用。
参数
  xEventGroup 设置和测试位的事件组。 必须 必须已通过 通过调用 xEventGroupCreate() 创建。
  uxBitsToSet 在确定(且可能等待)uxBitsToWait参数指定的所有位 设置完成之前, 要设置事件组中的一个或多个位。 例如,将uxBitsToSet设置为0x04 即可设置事件组中的位2。
  uxBitsToWaitFor 指定事件组中要测试的一个或多个事件位 的按位值。 例如,如果要等待 位0和位2被设置,则将uxBitsToWaitFor设置为0x05。 如果要等待 位0、位1和位2被设置,则将uxBitsToWaitFor设置为0x07 等等。
  xTicksToWait 等待uxBitsToWaitFor参数值指定的 所有位设置完成的最长时间 (以“ticks”表示)。
返回值:
  等待置位时或阻塞到期时 事件组的值。 测试返回值 以便了解设置了哪些位。
  如果xEventGroupSync()由于超时而返回, 则不会设置所有等待位。
  如果 xEventGroupSync()因其所等待的所有位都被设置而返回, 那么返回值是自动清除任何位之前的 事件组值。
用法示例:

/* 三个任务所使用的比特。*/
#define TASK_0_BIT ( 1 << 0 )
#define TASK_1_BIT ( 1 << 1 )
#define TASK_2_BIT ( 1 << 2 )

#define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )

/* 使用一个事件组来同步三个任务。 假设这个事件组
已经在其他地方被创建。*/
EventGroupHandle_t xEventBits;

void vTask0( void *pvParameters )
{
    
    
	EventBits_t uxReturn;
	TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;

    for( ; ; )
    {
    
    
        /* 在此执行任务功能。*/
        . . .

        /* 设置事件组中的第0位,以指出该任务已达到
        同步点。 其他两个任务将设置由ALL_SYNC_BITS定义的另外两个位。
        由ALL_SYNC_BITS定义。 所有三个任务都达到了同步点
        当所有的ALL_SYNC_BITS被设置时,所有三个任务都达到了同步点。 等待最多100ms
        来实现这一目标。*/
        uxReturn = xEventGroupSync( xEventBits,
                                    TASK_0_BIT,
                                    ALL_SYNC_BITS,
                                    xTicksToWait );

        if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
        {
    
    
            /* 所有三个任务都在调用xEventGroupSync( )之前达到同步点。
            xEventGroupSync()的调用超时之前,三个任务都达到了同步点。*/
        }
    }
}

void vTask1( void *pvParameters )
{
    
    
    for( ;;)
    {
    
    
        /* 在此执行任务功能。*/
        . . .

        /* 设置事件组中的第1位,以指出该任务已达到
        同步点。 其他两个任务将设置其他两个
        由ALL_SYNC_BITS定义的位。 所有三个任务都达到了
        当所有的ALL_SYNC_BITS被设置时,所有三个任务都达到了同步点。 无限期地等待
        无限期地等待这一情况的发生。*/
        xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );

        /* xEventGroupSync()被调用时有一个不确定的阻塞时间,所以
        这个任务只有在所有三个任务都进行了同步化的情况下才会到达这里。
        所以没有必要测试返回值。*/
    }
}

void vTask2( void *pvParameters )
{
    
    
    for( ;;)
    {
    
    
        /* 在此执行任务功能。*/
        . . .

        /* 设置事件组中的第2位,注意该任务已经达到了
        同步点。 其他两个任务将设置其他两个
        由ALL_SYNC_BITS定义的位。 所有三个任务都达到了
        当所有的ALL_SYNC_BITS被设置时,所有三个任务都达到了同步点。 无限期地等待
        无限期地等待这一情况的发生。*/
        xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );

        /* xEventGroupSync()被调用时有一个不确定的阻塞时间,所以
        这个任务只有在所有三个任务都进行了同步化的情况下才会到达这里。
        所以没有必要测试返回值。*/
    }
}

十二、事件组示例

事件组等待

/**
 * @file 16_EventGroupWait.c
 * @author WSP
 * @brief 事件组等待
 * @version 0.1
 * @date 2022-10-20
 *
 * @copyright Copyright (c) 2022
 *
 */
#include "FreeRTOS_Include.h"

const static char *TAG = "APP_EventGroupWait";

#define BIT_0 ( 1 << 0 )
#define BIT_1 ( 1 << 1 )
#define BIT_2 ( 1 << 2 )
#define BIT_3 ( 1 << 3 )
#define BIT_4 ( 1 << 4 )
#define BIT_5 ( 1 << 5 )
#define BIT_6 ( 1 << 6 )
#define BIT_7 ( 1 << 7 )
#define BIT_8 ( 1 << 8 )
/**
 * @brief   Task_One 事件发送
 * @param   arg
 * @return  NULL
*/
void Task_One(void *arg)
{
    
    
    bool SetFlag = false;
    EventGroupHandle_t EventGroupHandle = (EventGroupHandle_t)arg;
    while (1){
    
    
        SetFlag = !SetFlag;
        if( SetFlag ){
    
    
            xEventGroupSetBits(EventGroupHandle,BIT_0);
            ESP_LOGI(TAG, "Task_One set BIT_0");
        } else {
    
     
            xEventGroupSetBits(EventGroupHandle,BIT_4);
            ESP_LOGI(TAG, "Task_One set BIT_4");
        }
        vTaskDelay(3000/portTICK_PERIOD_MS);
    }
}
/**
 * @brief   Task_One 事件接收
 * @param   arg
 * @return  NULL
*/
void Task_Two(void *arg)
{
    
    
    EventBits_t uxBits; 
    EventGroupHandle_t EventGroupHandle = (EventGroupHandle_t)arg;
    while (1){
    
    
        uxBits = xEventGroupWaitBits(
                                     EventGroupHandle,  /* 正在测试的事件组。*/ 
                                     BIT_0 | BIT_4,     /* 事件组中要等待的位。*/ 
                                     pdTRUE,            /* BIT_0 & BIT_4 应该在返回之前被清除。*/ 
                                     pdFALSE,           /* 不要等待两个位,任何一个位都可以。*/ 
                                     portMAX_DELAY );   /* 等待最多 100 毫秒以设置任一位。*/
        ESP_LOGI(TAG, "Task_Two BIT_0 | BIT_4 was set Value:%d",uxBits);
        vTaskDelay(1000/portTICK_PERIOD_MS);
    }
}
/**
 * @brief   创建函数初始化
 * @param   NULL
 * @return  NULL
 */
void EventGroupWait_Init(void)
{
    
    
    EventGroupHandle_t EventGroupHandle  = NULL;
    EventGroupHandle = xEventGroupCreate();  // 创建事件组
    if(EventGroupHandle != NULL){
    
    
        // 创建任务一
        xTaskCreate(Task_One,
                    "Task_One",
                    2048,
                    (void *)EventGroupHandle,
                    1,
                    NULL);
        // 创建任务二
        xTaskCreate(Task_Two,
                    "Task_Two",
                    2048,
                    (void *)EventGroupHandle,
                    2,
                    NULL);
        ESP_LOGI(TAG,"task Create ok");
    }
}

事件组同步

/**
 * @file 17_EventGroupSync.c
 * @author WSP
 * @brief 事件组同步 
 * @version 0.1
 * @date 2022-10-20
 *
 * @copyright Copyright (c) 2022
 *
 */
#include "FreeRTOS_Include.h"

const static char *TAG = "APP_EventGroupSync";

#define BIT_0 ( 1 << 0 )
#define BIT_1 ( 1 << 1 )
#define BIT_2 ( 1 << 2 )
#define BIT_3 ( 1 << 3 )
#define BIT_4 ( 1 << 4 )
#define BIT_5 ( 1 << 5 )
#define BIT_6 ( 1 << 6 )
#define BIT_7 ( 1 << 7 )
#define BIT_8 ( 1 << 8 )

#define ALL_SYNC_BITS   ( BIT_1 | BIT_2 | BIT_3)

/**
 * @brief   Task_One
 * @param   arg
 * @return  NULL
*/
void Task_One(void *arg)
{
    
    
    EventGroupHandle_t EventGroupHandle = (EventGroupHandle_t)arg;
    while (1) {
    
    
        vTaskDelay(1000/portTICK_PERIOD_MS);
        ESP_LOGI(TAG, "Task_Two BIT_1 was set Value");
        xEventGroupSync(
                        EventGroupHandle,  /* 正在测试的事件组。*/ 
                        BIT_1,             /* 事件组中要等待的位。*/ 
                        ALL_SYNC_BITS,     /* BIT_0 & BIT_4 应该在返回之前被清除。*/ 
                        portMAX_DELAY );   /* 等待最多 100 毫秒以设置任一位。*/
        vTaskDelay(5000/portTICK_PERIOD_MS);
    }
}
/**
 * @brief   Task_Two
 * @param   arg
 * @return  NULL
*/
void Task_Two(void *arg)
{
    
    
    EventGroupHandle_t EventGroupHandle = (EventGroupHandle_t)arg;
    while (1) {
    
    
        vTaskDelay(2000/portTICK_PERIOD_MS);
        ESP_LOGI(TAG, "Task_Two BIT_2 was set Value");
        xEventGroupSync(
                        EventGroupHandle,  /* 正在测试的事件组。*/ 
                        BIT_2,             /* 事件组中要等待的位。*/ 
                        ALL_SYNC_BITS,     /* BIT_0 & BIT_4 应该在返回之前被清除。*/ 
                        portMAX_DELAY );   /* 等待最多 100 毫秒以设置任一位。*/        
        vTaskDelay(5000/portTICK_PERIOD_MS);
    }
}
/**
 * @brief   Task_Three
 * @param   arg
 * @return  NULL
*/
void Task_Three(void *arg)
{
    
    
    EventGroupHandle_t EventGroupHandle = (EventGroupHandle_t)arg;
    while (1){
    
    
        vTaskDelay(3000/portTICK_PERIOD_MS);
        ESP_LOGI(TAG, "Task_Two BIT_3 was set Value");
        xEventGroupSync(
                        EventGroupHandle,  /* 正在测试的事件组。*/ 
                        BIT_3,             /* 事件组中要等待的位。*/ 
                        ALL_SYNC_BITS,     /* BIT_0 & BIT_4 应该在返回之前被清除。*/ 
                        portMAX_DELAY );   /* 等待最多 100 毫秒以设置任一位。*/
        ESP_LOGI(TAG, "ALL_SYNC_BITS was set Value");
        vTaskDelay(5000/portTICK_PERIOD_MS);
        printf("\n\r");
    }
}
/**
 * @brief   创建函数初始化
 * @param   NULL
 * @return  NULL
 */
void EventGroupSync_Init(void)
{
    
    
    EventGroupHandle_t EventGroupHandle  = NULL;
    EventGroupHandle = xEventGroupCreate();  // 创建事件组
    if(EventGroupHandle != NULL){
    
    
        // 创建任务一
        xTaskCreate(Task_One,
                    "Task_One",
                    2048,
                    (void *)EventGroupHandle,
                    1,
                    NULL);
        // 创建任务二
        xTaskCreate(Task_Two,
                    "Task_Two",
                    2048,
                    (void *)EventGroupHandle,
                    2,
                    NULL);
        // 创建任务三
        xTaskCreate(Task_Three,
                    "Task_Three",
                    2048,
                    (void *)EventGroupHandle,
                    2,
                    NULL);
        ESP_LOGI(TAG,"task Create ok");
    }
    vTaskDelay(2000/portTICK_PERIOD_MS);        // 延时等待
    ESP_LOGI(TAG,"APP_task_Core_Control enter INTERRUPTS");
}

猜你喜欢

转载自blog.csdn.net/believe666/article/details/127205644
今日推荐