1 事件的等待与通知
1.1 概述
现有的任务状态切换图:

事件控制块的等待与通知:任务进入事件控制块等待队列中暂停运行,事件发送时通知任务从对列移除继续运行。

新的任务状态切换图:

1.2 设计原理
等待事件控制块:

1.3 设计实现
事件控制块等待:

从事件控制块中唤醒:

从事件控制块中移除:
时钟节拍处理中添加等待超市处理:

tEvent.h:
/*************************************** Copyright (c)******************************************************
** File name : tEvent.h
** Latest modified Date : 2016-06-01
** Latest Version : 0.1
** Descriptions : tinyOS的事件控制结构实现
**
**--------------------------------------------------------------------------------------------------------
** Created by : 01课堂 lishutong
** Created date : 2016-06-01
** Version : 1.0
** Descriptions : The original version
**
**--------------------------------------------------------------------------------------------------------
** Copyright : 版权所有,禁止用于商业用途
** Author Blog : http://ilishutong.com
**********************************************************************************************************/
#ifndef TEVENT_H
#define TEVENT_H
#include "tConfig.h"
#include "tLib.h"
#include "tTask.h"
// Event类型
typedef enum _tEventType {
tEventTypeUnknown = 0, // 未知类型
}tEventType;
// Event控制结构
typedef struct _tEvent {
tEventType type; // Event类型
tList waitList; // 任务等待列表
}tEvent;
/**********************************************************************************************************
** Function name : tEventInit
** Descriptions : 初始化事件控制块
** parameters : event 事件控制块
** parameters : type 事件控制块的类型
** Returned value : 无
***********************************************************************************************************/
void tEventInit (tEvent * event, tEventType type);
/**********************************************************************************************************
** Function name : tEventWait
** Descriptions : 让指定在事件控制块上等待事件发生
** parameters : event 事件控制块
** parameters : task 等待事件发生的任务
** parameters : msg 事件消息存储的具体位置
** parameters : state 消息类型
** parameters : timeout 等待多长时间
** Returned value : 优先级最高的且可运行的任务
***********************************************************************************************************/
void tEventWait (tEvent * event, tTask * task, void * msg, uint32_t state, uint32_t timeout);
/**********************************************************************************************************
** Function name : tEventWakeUp
** Descriptions : 从事件控制块中唤醒首个等待的任务
** parameters : event 事件控制块
** parameters : msg 事件消息
** parameters : result 告知事件的等待结果
** Returned value : 首个等待的任务,如果没有任务等待,则返回0
***********************************************************************************************************/
tTask * tEventWakeUp (tEvent * event, void * msg, uint32_t result);
/**********************************************************************************************************
** Function name : tEventRemoveTask
** Descriptions : 将任务从其等待队列中强制移除
** parameters : task 待移除的任务
** parameters : result 告知事件的等待结果
** Returned value : 无
***********************************************************************************************************/
void tEventRemoveTask (tTask * task, void * msg, uint32_t result);
#endif /* TEVENT_H */
tEvent.c:
/*************************************** Copyright (c)******************************************************
** File name : tEvent.c
** Latest modified Date : 2016-06-01
** Latest Version : 0.1
** Descriptions : tinyOS的事件控制结构实现
**
**--------------------------------------------------------------------------------------------------------
** Created by : 01课堂 lishutong
** Created date : 2016-06-01
** Version : 1.0
** Descriptions : The original version
**
**--------------------------------------------------------------------------------------------------------
** Copyright : 版权所有,禁止用于商业用途
** Author Blog : http://ilishutong.com
**********************************************************************************************************/
#include "tinyOS.h"
/**********************************************************************************************************
** Function name : tEventInit
** Descriptions : 初始化事件控制块
** parameters : event 事件控制块
** parameters : type 事件控制块的类型
** Returned value : 无
***********************************************************************************************************/
void tEventInit (tEvent * event, tEventType type)
{
event->type = type;
tListInit(&event->waitList);
}
/**********************************************************************************************************
** Function name : tEventWait
** Descriptions : 让指定在事件控制块上等待事件发生
** parameters : event 事件控制块
** parameters : task 等待事件发生的任务
** parameters : msg 事件消息存储的具体位置
** parameters : state 消息类型
** parameters : timeout 等待多长时间
** Returned value : 优先级最高的且可运行的任务
***********************************************************************************************************/
void tEventWait (tEvent * event, tTask * task, void * msg, uint32_t state, uint32_t timeout)
{
// 进入临界区
uint32_t status = tTaskEnterCritical();
task->state |= state << 16; // 标记任务处于等待某种事件的状态
task->waitEvent = event; // 设置任务等待的事件结构
task->eventMsg = msg; // 设置任务等待事件的消息存储位置
// 因有时候需要接受消息,所以需要接受区
task->waitEventResult = tErrorNoError; // 清空事件的等待结果
// 将任务从就绪队列中移除
tTaskSchedUnRdy(task);
// 将任务插入到等待队列中
tListAddLast(&event->waitList, &task->linkNode);
// 如果发现有设置超时,在同时插入到延时队列中
// 当时间到达时,由延时处理机制负责将任务从延时列表中移除,同时从事件列表中移除
if (timeout)
{
tTimeTaskWait(task, timeout);
}
// 退出临界区
tTaskExitCritical(status);
}
/**********************************************************************************************************
** Function name : tEventWakeUp
** Descriptions : 从事件控制块中唤醒首个等待的任务
** parameters : event 事件控制块
** parameters : msg 事件消息
** parameters : result 告知事件的等待结果
** Returned value : 首个等待的任务,如果没有任务等待,则返回0
***********************************************************************************************************/
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;
}
/**********************************************************************************************************
** Function name : tEventRemoveTask
** Descriptions : 将任务从其等待队列中强制移除
** parameters : task 待移除的任务
** parameters : result 告知事件的等待结果
** Returned value : 无
***********************************************************************************************************/
void tEventRemoveTask (tTask * task, void * msg, uint32_t result)
{
// 进入临界区
uint32_t status = tTaskEnterCritical();
// 将任务从所在的等待队列中移除
// 注意,这里没有检查waitEvent是否为空。既然是从事件中移除,那么认为就不可能为空
tListRemove(&task->waitEvent->waitList, &task->linkNode);
// 设置收到的消息、结构,清除相应的等待标志位
task->waitEvent = (tEvent *)0;
task->eventMsg = msg;
task->waitEventResult = result;
task->state &= ~TINYOS_TASK_WAIT_MASK;
// 退出临界区
tTaskExitCritical(status);
}
参考资料:
本文详细介绍了嵌入式操作系统中事件控制块的实现原理与设计,包括事件等待与通知的流程,以及如何通过事件控制块进行任务状态切换。文章提供了具体的代码实现,如事件控制块初始化、等待事件、唤醒任务等函数。
1万+

被折叠的 条评论
为什么被折叠?



