一、事件
事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,但事件通信只能是事件类型的通信,无数据传输。与信号量不同的是,它可以实现一对多,多对多的同步。即一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理,也可以是几个事件都发生后才唤醒任务进行事件处理。同样,也可以是多个任务同步多个事件。
每一个事件组只需要很少的 RAM 空间来保存事件组的状态。事件组存储在一个 EventBits_t 类型的变量中,该变量在事件组结构体中定义 。在 STM32 中 , 我们一般 configUSE_16_BIT_TICKS 定义为 0,那么 uxEventBits 是 32 位的,有 24 个位用来实现事 件标志组。每一位代表一个事件,任务通过“逻辑与”或“逻辑或”与一个或多个事件建立关联,形成一个事件组。 事件的“逻辑或”也被称作是独立型同步,指的是任务感兴趣的所有事件任一件发生即可被唤醒;事件“逻辑与”则被称为是关联型同步,指的是任务感兴趣的若干事件都发生时才被唤醒,并且事件发生的时间可以不同步。
多任务环境下,任务、中断之间往往需要同步操作,一个事件发生会告知等待中的任务,即形成一个任务与任务、中断与任务间的同步。 事件可以提供一对多、多对多的同步操作。一对多同步模型:一个任务等待多个事件的触发,这种情况是比较常见的;多对多同步模型:多个任务等待多个事件的触发。任务可以通过设置事件位来实现事件的触发和等待操作。FreeRTOS 的事件仅用于同步,不提供数据传输功能。
在 FreeRTOS 事件中,每个事件获取的时候,用户可以选择感兴趣的事件,并且选择读取事件信息标记,它有三个属性,分别是逻辑与,逻辑或以及是否清除标记。当任务等待事件同步时,可以通过任务感兴趣的事件位和事件信息标记来判断当前接收的事件是否满足要求,如果满足则说明任务等待到对应的事件,系统将唤醒等待的任务;否则,任务会根据用户指定的阻塞超时时间继续等待下去。
二、配置过程
1、配置RCC、USART1、时钟84M
2、配置SYS,将Timebase Source修改为除滴答定时器外的其他定时器。
3、初始化LED的两个引脚、两个按键引脚
4、开启FreeRTOS,v1与v2版本不同,一般选用v1即可,但是如果要使用事件,则必须选择V2版本。
5、添加一个事件
6、创建两个线程。
三、API
1、创建一个事件组:osEventFlagsNew
Send_stackHandle = osThreadNew(Send_thread_entry, NULL, &Send_stack_attributes);
Receive_stackHandle = osThreadNew(Recevie_thread_entry, NULL,&Receive_stack_attributes);
2、删除事件组:osEventFlagsDelete
3、置位事件组中指定的位:osEventFlagsSet
4、获取事件组中的一个或者多个事件发生标志:osEventFlagsWait
5、清除事件组中指定的位:osEventFlagsClear
四、代码
1、发送事件
if( HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8)==0)
{
printf("key1 down!\n");
//触发一个事件1
osEventFlagsSet(myEvent01Handle,KEY1_EVENT);
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_9)==0)
{
printf("key2 down!\n");
//触发一个事件2
osEventFlagsSet(myEvent01Handle,KEY2_EVENT);
}
2、接收事件
uint32_t event=osEventFlagsWait(myEvent01Handle,
KEY1_EVENT|KEY2_EVENT,osFlagsWaitAll,osWaitForever);
if((event&(KEY1_EVENT|KEY2_EVENT))==(KEY1_EVENT|KEY2_EVENT))
{
printf("key1 and key2 down\n");
}