11基础概述
1.1 基本作用
事件标志的作用类似于全局型的flag,多个标志组合在一起构成事件标志组,这里先分析一下事件标志组于全局flag的区别:
使用事件标志组可以让 FreeRTOS内核有效地管理任务,而全局变量是无法做到的,任务的超时等机制需要用户自己去实现
使用了全局变量就要防止多任务的访问冲突,而使用事件标志组则处理好了这个问题,用户无需担心
使用事件标志组可以有效地解决中断服务程序和任务之间的同步问题
1.2 运行原理如上图:
任务1在一个循环中等待事件的到来,等待时处于阻塞状态,即任务挂起状态。阻塞的时间可用设置。当有事件位被置位时,执行处理事件。
任务1的处理事件可以触发事件(给自身的任务触发事件),但这种方式触发后,只能等程序再次运行到xEventGroupWaitBits才能处理
任务2或其它任务可以触发事件(这是比较常用的用法),这样,在任务2触发事件后,任务1可以从阻塞态变为就绪态,如果任务1的优先级较高,则任务1开始运行,执行处理事件,实现任务间的同步
中断中也可以可以触发事件(这也是比较常用的用法),作用也是实现同步,只是需要使用加FromISR后缀的API函数
1.3 事件组的最大位数事件标志存储在一个EventBits_t类型的变量中,该变量在事件组结构体中定义,事件标志组的可用位数通过宏定义确定:
configUSE_16_BIT_TICKS定义为1,uxEventBits是16位的,低8位用来存储事件组
configUSE_16_BIT_TICKS 定义为0,uxEventBits是32位的,低24位用来存储事件组
注:高8位用于系统内核使用,不可用户使用!
22源码分析
首先来看一下事件控制块:
2.1 事件控制块除了事件标志组变量之外,FreeRTOS还使用了一个链表来记录等待事件的任务,所有在等待此事件的任务均会被挂载在等待事件列表xTasksWaitingForBits
#if( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxEventGroupNumber; #endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t ucStaticallyAllocated; #endif} EventGroup_t;2.2 创建事件标志组
主要功能是为事件标志组控制块分配内存以及创建一个任务等待列表
EventGroupHandle_t xEventGroupCreate( void ){ EventGroup_t *pxEventBits;
/* 为事件标志组控制块分配内存 */ pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
if( pxEventBits != NULL ) { pxEventBits->uxEventBits = 0; /*创建一个列表*/ vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
#if( configSUPPORT_STATIC_ALLOCATION == 1 ) { pxEventBits->ucStaticallyAllocated = pdFALSE; } #endif /* configSUPPORT_STATIC_ALLOCATION */
traceEVENT_GROUP_CREATE( pxEventBits ); } else { traceEVENT_GROUP_CREATE_FAILED(); }
return ( EventGroupHandle_t ) pxEventBits;}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */