FreeRTOS专栏16:事件标志组

1 事件标志组简介:

事件标志组:

之前介绍了使用信号量来完成同步,但是使用信号量来同步的话,任务只能与单个的事件或任务进行同步。有时候某个任务可能会需要与多个事件或任务进行同步,此时信号量就无能为力了。FreeRTOS 提供了一个可选的解决方法,那就是事件标志组

事件位和事件组:

事件组数据结构:

2 创建事件标志组:

事件标志组结构体(包括一个变量和一个等待事件的任务列表):

typedef struct xEventGroupDefinition
{
	EventBits_t uxEventBits;
	List_t xTasksWaitingForBits;		/*< List of tasks waiting for a bit to be set. */

	#if( configUSE_TRACE_FACILITY == 1 )
		UBaseType_t uxEventGroupNumber;
	#endif
} EventGroup_t;

3 设置 / 清除事件位:

4 获取事件标志组值:

5 等待指定的事件位:

参数说明:

事件标志组测试实验:

start_task:用来创建其他两个个任务和事件标志组;

eventsetbit_task:读取按键值和串口指令,根据不同的按键值将事件标志组中相应的事件位置 1,用来模拟事件的发生;

eventgroup_task:同时等待事件标志组中的多个事件位,当这些事件位都置 1 的话就执行相应的处理;

代码如下所示:

#define EVENT_BIT_1   (1 << 1)
#define EVENT_BIT_2   (1 << 2)

void event_set_bit_task(void *pvParameters)
{
  EventBits_t event_value;
  for (;;)
  {
    if (key_scan(KEY1_GPIO_Port, KEY1_Pin) == KEY_ON)
    {
      xEventGroupSetBits(event_group_handle, EVENT_BIT_1);
      event_value = xEventGroupGetBits(event_group_handle);
      printf("发送事件位EVENT_BIT_1,事件位的值为%#X\n", event_value & (0X0F));
    }
    vTaskDelay(50);
  }
}

void event_group_task(void *pvParameters)
{
  EventBits_t uxBits;
  for (;;)
  {
    uxBits = xEventGroupWaitBits(event_group_handle,	
					                       EVENT_BIT_1 | EVENT_BIT_2,	
					                       pdTRUE,	
                                 pdTRUE,	
					                       portMAX_DELAY);	
    printf("全部事件位获取成功,事件组的值为%#x\r\n", uxBits);
    vTaskDelay(50);
  }
}

void EXTI15_10_IRQHandler(void)
{
  BaseType_t xHigherPriorityTaskWoken, xResult;
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */
  if (__HAL_GPIO_EXTI_GET_FLAG(KEY2_Pin))
  {
    xHigherPriorityTaskWoken = pdFALSE;
    xResult = xEventGroupSetBitsFromISR(
							event_group_handle,	
							EVENT_BIT_2, 
							&xHigherPriorityTaskWoken);
    if (xResult == pdPASS)
    {
      printf("KEY2外部中断出发,发送事件位EVENT_BIT_2,事件组的值为%#X\r\n", 
             xEventGroupGetBits(event_group_handle));
      portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    }
  }
  __HAL_GPIO_EXTI_CLEAR_FLAG(KEY2_Pin);
}

测试结果如下所示:

注意,这里出现了FreeRTOS的报错,原因是在中断中进入了临界段。外部中断的优先级为6,而屏蔽优先级的值为5,所以会因为冲突而报错,导致第二次获取事件值出错,但最后的运行结果是正确的。

#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )

EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventBits_t uxReturn;

	taskENTER_CRITICAL();
	{
		traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );

		/* The value returned is the event group value prior to the bits being
		cleared. */
		uxReturn = pxEventBits->uxEventBits;

		/* Clear the bits. */
		pxEventBits->uxEventBits &= ~uxBitsToClear;
	}
	taskEXIT_CRITICAL();

	return uxReturn;
}
发布了184 篇原创文章 · 获赞 100 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/dingyc_ee/article/details/104128745