事件控制块为信号量、邮箱、事件标志组、互斥信号量等的基础组件
解决以下问题
1、同步两个任务的运行
2、处理多个任务共享资源的冲突问题
3、任务间消息的传递
4、中断向任务传递事件标志,以唤醒任务执行
1、事件控制块
事件控制块的结构
typedef struct _tEvent{
tEventType type; //事件类型
tList waitList; //事件等待链表
}tEvent;
初始化事件控制块
void tEventInit(tEvent *event, tEventType type)
{
event->type=type;
tListInit(&event->waitList);
}
事件的等待
void tEventWait(tEvent *event,tTask * task,void *msg,uint32_t state,uint32_t timeout)
{
uint32_t status = tTaskEnterCritical();
task->waitEvent=event;
task->eventMsg=msg;
task->state|=state;
task->waitEventResult = tErrorNoError;
tTaskSchedUnRdy(task); //将任务从就绪队列中移除
tListAddLast(&event->waitList,&task->linkNode); //将任务插入到等待队列中
if(timeout)
{
tTimeTaskWait(task,timeout);
}
tTaskExitCritical(status);
}
事件的通知
tTask * tEventWakeUp (tEvent * event, void * msg, uint32_t result)
{
tNode * node;
tTask * task = (tTask * )0;
uint32_t status = tTaskEnterCritical();
if((node = tListRemoveFirst(&event->waitList)) != (tNode *)0)
{
task = (tTask *)tNodeParent(node, tTask, linkNode);
task->waitEvent = (tEvent *)0;
task->eventMsg = msg;
task->waitEventResult = result;
task->state &= ~TINYOS_TASK_WAIT_MASK;
if (task->delayTicks != 0)
{
tTimeTaskWakeUp(task); // 将任务从延时队列中移除
}
tTaskSchedRdy(task); // 将任务加入就绪队列
}
tTaskExitCritical(status);
return task;
}
2、计数信号量(不支持嵌套)
计数信号量的结构
typedef struct _tSem{
tEvent event;
uint32 count;
uint32 maxCount;
}tSem;
计数信号量的初始化
void tSemInit(tSem *sem,uint32_t startCount,uint32_t maxCount)
{
sem->maxCount=maxCount;
if(maxCount==0)
{
sem->count=startCount;
}
else
{
sem->count=(startCount>maxCount)?maxCount:startCount;
}
}
计数信号量的获取
uint32_t tSemwait(tSem *sem,uint32_t waitTicks)
{
uint32_t status = tTaskEnterCritical();
if(sem->count > 0)
{
sem->count--;
tTaskExitCritical(status);
return tErrorNoError;
}
else
{
tEventWait(&sem->event,currentTask,(void *)0,tEventTypeSem,waitTicks);
tTaskExitCritical(status);
tTaskSched(); //任务调度
return currentTask->waitEventResult;
}
}
计数信号量的释放
void tSemNotify (tSem * sem)
{
uint32_t status = tTaskEnterCritical();
if (tEventWaitCount(&sem->event) > 0)
{
tTask * task = tEventWakeUp(&sem->event, (void *)0, tErrorNoError );
if (task->prio < currentTask->prio)
{
tTaskSched();
}
}
else
{
++sem->count;
if ((sem->maxCount != 0) && (sem->count > sem->maxCount))
{
sem->count = sem->maxCount;
}
}
tTaskExitCritical(status);
}
3、邮箱
邮箱的结构
typedef struct _tMbox
{
tEvent event;
uint32_t count;
uint32_t read;
uint32_t write;
uint32_t maxCount;
void ** msgBuffer;
}tMbox;
邮箱的初始化
void tMboxInit (tMbox * mbox, void ** msgBuffer, uint32_t maxCount)
{
tEventInit(&mbox->event, tEventTypeMbox);
mbox->msgBuffer = msgBuffer;
mbox->maxCount = maxCount;
mbox->read = 0;
mbox->write = 0;
mbox->count = 0;
}
邮箱的获取
uint32_t tMboxWait (tMbox * mbox, void **msg, uint32_t waitTicks)
{
uint32_t status = tTaskEnterCritical();
if (mbox->count > 0)
{
--mbox->count;
*msg = mbox->msgBuffer[mbox->read++]; //取出消息
if (mbox->read >= mbox->maxCount)
{
mbox->read = 0;
}
tTaskExitCritical(status);
return tErrorNoError;
}
else
{
tEventWait(&mbox->event, currentTask, (void *)0, tEventTypeMbox, waitTicks); //将任务插入到事件队列
tTaskExitCritical(status);
tTaskSched();
*msg = currentTask->eventMsg;
return currentTask->waitEventResult;
}
}
邮箱的释放
uint32_t tMboxNotify (tMbox * mbox, void * msg, uint32_t notifyOption)
{
uint32_t status = tTaskEnterCritical();
if (tEventWaitCount(&mbox->event) > 0)
{
tTask * task = tEventWakeUp(&mbox->event, (void *)msg, tErrorNoError ); //唤醒任务
if (task->prio < currentTask->prio)
{
tTaskSched();
}
}
else
{
if (mbox->count >= mbox->maxCount)
{
tTaskExitCritical(status);
return tErrorResourceFull;
}
if (notifyOption & tMBOXSendFront) //优先获取该消息
{
if (mbox->read <= 0)
{
mbox->read = mbox->maxCount - 1;
}
else
{
--mbox->read;
}
mbox->msgBuffer[mbox->read] = msg;
}
else
{
mbox->msgBuffer[mbox->write++] = msg;
if (mbox->write >= mbox->maxCount)
{
mbox->write = 0;
}
}
mbox->count++; //消息计数
}
tTaskExitCritical(status);
return tErrorNoError;
}
4、事件标志组
事件标志组的结构
typedef struct _tFlagGroup
{
tEvent event;
uint32_t flags;
}tFlagGroup;
事件标志组的初始化
void tFlagGroupInit (tFlagGroup * flagGroup, uint32_t flags)
{
tEventInit(&flagGroup->event, tEventTypeFlagGroup);
flagGroup->flags = flags;
}
检查并消耗掉事件标志
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;
uint32_t calcFlag = isSet ? (flagGroup->flags & srcFlags) : (~flagGroup->flags & srcFlags);
if (((isAll != 0) && (calcFlag == srcFlags)) || ((isAll == 0) && (calcFlag != 0)))
{
if (isConsume)
{
if (isSet)
{
flagGroup->flags &= ~srcFlags;
}
else
{
flagGroup->flags |= srcFlags;
}
}
*flags = calcFlag;
return tErrorNoError;
}
*flags = calcFlag;
return tErrorResourceUnavaliable;
}
事件标志组的等待
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;
}
事件标志组的通知
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);
}
5、互斥信号量(支持嵌套)
互斥信号量的结构
typedef struct _tMutex
{
tEvent event;
uint32_t lockedCount; // 已被锁定的次数
tTask * owner; // 拥有者
uint32_t ownerOriginalPrio; // 拥有者原始的优先级
}tMutex;
互斥信号量的初始化
void tMutexInit (tMutex * mutex)
{
tEventInit(&mutex->event, tEventTypeMutex);
mutex->lockedCount = 0;
mutex->owner = (tTask *)0;
mutex->ownerOriginalPrio = TINYOS_PRO_COUNT;
}
互斥信号量的等待
uint32_t tMutexWait (tMutex * mutex, uint32_t waitTicks)
{
uint32_t status = tTaskEnterCritical();
if (mutex->lockedCount <= 0)
{
mutex->owner = currentTask;
mutex->ownerOriginalPrio = currentTask->prio;
mutex->lockedCount++;
tTaskExitCritical(status);
return tErrorNoError;
}
else
{
if (mutex->owner == currentTask)
{
mutex->lockedCount++;
tTaskExitCritical(status);
return tErrorNoError;
}
else // 优先级继承方式处理
{
if (currentTask->prio < mutex->owner->prio)
{
tTask * owner = mutex->owner;
if (owner->state == TINYOS_TASK_STATE_RDY) 拥有者任务处于就绪状态
{
tTaskSchedUnRdy(owner);
owner->prio = currentTask->prio; // 提升拥有者的优先级
tTaskSchedRdy(owner);
}
else
{
owner->prio = currentTask->prio;
}
}
tEventWait(&mutex->event, currentTask, (void *)0, tEventTypeMutex, waitTicks); // 当前任务进入等待队列
tTaskExitCritical(status);
tTaskSched();
return currentTask->waitEventResult;
}
}
}
互斥信号量的通知
uint32_t tMutexNotify (tMutex * mutex)
{
uint32_t status = tTaskEnterCritical();
if (mutex->lockedCount <= 0)
{
tTaskExitCritical(status);
return tErrorNoError;
}
if (mutex->owner != currentTask)
{
tTaskExitCritical(status);
return tErrorOwner;
}
if (--mutex->lockedCount > 0)
{
tTaskExitCritical(status);
return tErrorNoError;
}
if (mutex->ownerOriginalPrio != mutex->owner->prio)
{
if (mutex->owner->state == TINYOS_TASK_STATE_RDY)
{
tTaskSchedUnRdy(mutex->owner);
currentTask->prio = mutex->ownerOriginalPrio;
tTaskSchedRdy(mutex->owner);
}
else
{
currentTask->prio = mutex->ownerOriginalPrio;
}
}
if (tEventWaitCount(&mutex->event) > 0) // 检查是否有任务等待
{
tTask * task = tEventWakeUp(&mutex->event, (void *)0, tErrorNoError);
mutex->owner = task;
mutex->ownerOriginalPrio = task->prio;
mutex->lockedCount++;
if (task->prio < currentTask->prio)
{
tTaskSched();
}
}
tTaskExitCritical(status);
return tErrorNoError;
}
拥有者不加入到等待列表中,所以可实现嵌套
实现优先级继承