事件标志组的实现
- 事件标志组的原理与创建
- 事件标志组的等待与通知
- 事件标志组的删除与状态查询
1、事件标志组的原理与创建
typedef struct _tFlagGroup
{
// 事件控制块
tEvent event;
// 当前事件标志
uint32_t flags;
}tFlagGroup;
void tFlagGroupInit (tFlagGroup * flagGroup, uint32_t flags)
{
tEventInit(&flagGroup->event, tEventTypeFlagGroup);
flagGroup->flags = flags;
}
2、事件标志组的等待与通知
###任务二中首先调用tFlagGroupWait
tFlagGroupWait(&flagGroup1, TFLAGGROUP_CLEAR_ALL, 0x4, &resultFlags, 10);
##函数原型:
/**********************************************************************************************************
** Function name: tFlagGroupWait
** Descriptions : 等待事件标志组中特定的标志
** parameters : flagGroup 等待的事件标志组
** parameters : waitType 等待的事件类型
** parameters : requstFlag 请求的事件标志
** parameters : resultFlag 等待标志结果
** parameters : waitTicks 当等待的标志没有满足条件时,等待的ticks数,为0时表示永远等待
** Returned value : 等待结果,tErrorResourceUnavaliable.tErrorNoError,tErrorTimeout
*********************************************************************** ************************************/
uint32_t tFlagGroupWait (tFlagGroup * flagGroup, uint32_t waitType, uint32_t requestFlag,uint32_t * resultFlag, uint32_t waitTicks)
{
uint32_t result;
uint32_t flags = requestFlag;
//进入临界区:
uint32_t status = tTaskEnterCritical();
//检查并消耗掉事件标志
result = tFlagGroupCheckAndConsume(flagGroup, waitType, &flags);
if (result != tErrorNoError)
{
// 如果事件标志不满足条件,则插入到等待队列中
currentTask->waitFlagsType = waitType;
currentTask->eventFlags = requestFlag;
tEventWait(&flagGroup->event, currentTask, (void *)0, tEventTypeFlagGroup, waitTicks);
//退出临界区
tTaskExitCritical(status);
// 再执行一次事件调度,以便于切换到其它任务
tTaskSched();
*resultFlag = currentTask->eventFlags;
result = currentTask->waitEventResult;
}
else
{
*resultFlag = flags;
tTaskExitCritical(status);
}
return result;
}
#检查并消耗掉事件标志:
result = tFlagGroupCheckAndConsume(flagGroup, waitType, &flags);
#函数原型:
/**********************************************************************************************************
** Function name: tFlagGroupCheckAndConsume
** Descriptions : 辅助函数。检查并消耗掉事件标志
** parameters : flagGroup 等待初始化的事件标志组
** parameters : type 事件标志检查类型
** parameters : flags 待检查事件标志存储地址和检查结果存储位置
** Returned value : tErrorNoError 事件匹配;tErrorResourceUnavaliable 事件未匹配
***********************************************************************************************************/
static uint32_t tFlagGroupCheckAndConsume (tFlagGroup * flagGroup, uint32_t type, uint32_t * flags)
{
uint32_t srcFlags = *flags;
uint32_t isSet = type & TFLAGGROUP_SET;
uint32_t isAll = type & TFLAGGROUP_ALL;
uint32_t isConsume = type & TFLAGGROUP_CONSUME;
// 有哪些类型的标志位出现
// flagGroup->flags & flags:计算出哪些位为1
// ~flagGroup->flags & flags:计算出哪位为0
uint32_t calcFlag = isSet ? (flagGroup->flags & srcFlags) : (~flagGroup->flags & srcFlags);
// 所有标志位出现, 或者做任意标志位出现,满足条件
if (((isAll != 0) && (calcFlag == srcFlags)) || ((isAll == 0) && (calcFlag != 0)))
{
// 是否消耗掉标志位
if (isConsume)
{
if (isSet)
{
// 清除为1的标志位,变成0
flagGroup->flags &= ~srcFlags;
}
else
{
// 清除为0的标志位,变成1
flagGroup->flags |= srcFlags;
}
}
*flags = calcFlag;
return tErrorNoError;
}
*flags = calcFlag;
return tErrorResourceUnavaliable;
}
#任务1中:通知事件标志组中的任务有新的标志发生
tFlagGroupNotify(&flagGroup1, 0, 0x6);
#原型:
3、事件标志组的删除与状态查询
/**********************************************************************************************************
** Function name: tFlagGroupNotify
** Descriptions : 通知事件标志组中的任务有新的标志发生
** parameters : flagGroup 事件标志组
** parameters : isSet 是否是设置事件标志
** parameters : flags 产生的事件标志
***********************************************************************************************************/
void tFlagGroupNotify (tFlagGroup * flagGroup, uint8_t isSet, uint32_t flags)
{
tList *waitList;
tNode * node;
tNode * nextNode;
uint8_t sched = 0;
uint32_t status = tTaskEnterCritical();
if (isSet) {
flagGroup->flags |= flags; // 置1事件
} else {
flagGroup->flags &= ~flags; // 清0事件
}
// 遍历所有的等待任务, 获取满足条件的任务,加入到待移除列表中
waitList = &flagGroup->event.waitList;
for (node = waitList->headNode.nextNode; node != &(waitList->headNode); node = nextNode) {
uint32_t result;
tTask *task = tNodeParent(node, tTask, linkNode);
uint32_t flags = task->eventFlags;
nextNode = node->nextNode;
// 检查标志
result = tFlagGroupCheckAndConsume(flagGroup, task->waitFlagsType, &flags);
if (result == tErrorNoError) {
// 唤醒任务
task->eventFlags = flags;
tEventWakeUpTask(&flagGroup->event, task, (void *)0, tErrorNoError);
sched = 1;
}
}
// 如果有任务就绪,则执行一次调度
if (sched)
{
tTaskSched();
}
tTaskExitCritical(status);
}
#获取事件标志组中特定的标志
/**********************************************************************************************************
** Function name: tFlagGroupNoWaitGet
** Descriptions : 获取事件标志组中特定的标志
** parameters : flagGroup 获取的事件标志组
** parameters : waitType 获取的事件类型
** parameters : requstFlag 请求的事件标志
** parameters : resultFlag 等待标志结果
** Returned value : 获取结果,tErrorResourceUnavaliable.tErrorNoError
***********************************************************************************************************/
uint32_t tFlagGroupNoWaitGet (tFlagGroup * flagGroup, uint32_t waitType, uint32_t requestFlag, uint32_t * resultFlag)
{
uint32_t flags = requestFlag;
uint32_t status = tTaskEnterCritical();
uint32_t result = tFlagGroupCheckAndConsume(flagGroup, waitType, &flags);
tTaskExitCritical(status);
*resultFlag = flags;
return status;
}