FreeRTOS的事件组和任务通知源码分析
一、事件组和任务通知介绍
事件组可以用来广播,当事件发生时,所有符合条件的任务都会被唤醒;任务通知时高效的任务间通信方式,但是只能给单个任务发送单个数据。
二、关键结构体
typedef struct xEventGroupDefinition
{
EventBits_t uxEventBits; // 一个整数,每个bit表示一个事件
List_t xTasksWaitingForBits; // 等待事件发生的task挂在这个队列上
} EventGroup_t;
三、事件组创建和删除函数
// 创建
EventGroupHandle_t xEventGroupCreate( void )
{
EventGroup_t *pxEventBits;
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); // 分配空间
pxEventBits->uxEventBits = 0; // 设置uxEventBits
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); // 初始化队列
return ( EventGroupHandle_t ) pxEventBits; // 返回句柄
}
// 删除
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
vTaskSuspendAll(); // 停止任务
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) // 如果删除时还有任务在等待事件发生
{
vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); // 将任务遍历移除
}
vPortFree( pxEventBits ); // 释放空间
( void ) xTaskResumeAll(); // 任务开始
}
四、事件组设置事件和等待事件
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
{
List_t *pxList;
BaseType_t xMatchFound = pdFALSE;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
pxList = &( pxEventBits->xTasksWaitingForBits ); // 等待队列
pxListEnd = listGET_END_MARKER( pxList ); // 队列尾
vTaskSuspendAll(); // 停止任务
pxListItem = listGET_HEAD_ENTRY( pxList ); // 队列头
pxEventBits->uxEventBits |= uxBitsToSet; // 设置bit
while( pxListItem != pxListEnd ) // 遍历
{
pxNext = listGET_NEXT( pxListItem );
... // 寻找uxBitsToClear
pxListItem = pxNext;
}
pxEventBits->uxEventBits &= ~uxBitsToClear; // 清空bit
( void ) xTaskResumeAll(); // 开始任务
return pxEventBits->uxEventBits;
}
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
{
}
五、任务发出通知
#define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL )
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
{
TCB_t * pxTCB; // 任务的TCB结构体,传入参数xTaskToNotify
BaseType_t xReturn = pdPASS;
uint8_t ucOriginalNotifyState; // 记录通知状态
pxTCB = ( TCB_t * ) xTaskToNotify;
taskENTER_CRITICAL(); // 关中断
ucOriginalNotifyState = pxTCB->ucNotifyState; // 记录原始通知状态
pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; // 当前任务接收到通知,pending
switch( eAction )
{
case eSetBits :
pxTCB->ulNotifiedValue |= ulValue; // 设置通知值bit
break;
case eIncrement :
( pxTCB->ulNotifiedValue )++; // 通知值计数值++
break;
case eSetValueWithOverwrite :
pxTCB->ulNotifiedValue = ulValue; // 覆写通知值
break;
case eSetValueWithoutOverwrite :
if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
{
pxTCB->ulNotifiedValue = ulValue;
}
else
{
xReturn = pdFAIL; // 原来有值,写失败
}
break;
case eNoAction:
break; // 什么也不做
}
if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) // 如果被通知的任务原来在等待通知状态
{
( void ) uxListRemove( &( pxTCB->xStateListItem ) ); // 将任务从等待状态改变list移除
prvAddTaskToReadyList( pxTCB ); // 加入就绪队列
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) // 如果被唤醒任务的优先级更高
{
taskYIELD_IF_USING_PREEMPTION(); // 重新调度
}
}
taskEXIT_CRITICAL(); // 开中断
return xReturn;
}
六、任务取出通知
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
{
uint32_t ulReturn;
taskENTER_CRITICAL(); // 关中断
if( pxCurrentTCB->ulNotifiedValue == 0UL ) // 正在执行的任务通知值为0
{
pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION; // 标记状态为等待通知
if( xTicksToWait > ( TickType_t ) 0 ) // 有设置等待时间
{
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); // 将当前任务加入等待list
portYIELD_WITHIN_API(); // 调度
}
}
taskEXIT_CRITICAL(); // 开中断
taskENTER_CRITICAL(); // 关中断
ulReturn = pxCurrentTCB->ulNotifiedValue; // 记录当前的通知值
if( ulReturn != 0UL ) // 接收到通知
{
if( xClearCountOnExit != pdFALSE ) // 函数返回前清0标志
{
pxCurrentTCB->ulNotifiedValue = 0UL;
}
else
{
pxCurrentTCB->ulNotifiedValue = ulReturn - ( uint32_t ) 1; // 值减1
}
}
pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; // 重设task的通知状态为等待接收通知
taskEXIT_CRITICAL(); // 开中断
return ulReturn; // 返回收到通知后得我通知值
}

浙公网安备 33010602011771号