事件的等待与通知

本文详细介绍了嵌入式操作系统中事件控制块的实现原理与设计,包括事件等待与通知的流程,以及如何通过事件控制块进行任务状态切换。文章提供了具体的代码实现,如事件控制块初始化、等待事件、唤醒任务等函数。

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. 【李述铜】从0到1自己动手写嵌入式操作系统
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值