一种高效定时器模块的设计与实现
摘要: 在设计一款车身中央控制器的过程中,需要设计很多定时应用,为此设计了一种高效定时器模块,该模块在单个硬件定时器的基础上模拟实现了多个软件定时器,节省了硬件及软件资源,简化了程序编写;描述了软件定时器的设计原理、结构设计、驱动程序设计及其应用。
关键字:定时器模块;软件定时器;驱动程序
引言
在嵌入式系统的设计中,时间特性在很多应用中都是一个很重要的参数,很多控制逻辑和协议的实现,需要用到计时、超时和统计功能,时间长短的计时及精度、周期定时和超时的设定成为某些控制逻辑和协议的关键条件。笔者在为某车型设计其车身中央控制器时,输入条件的判定、输出逻辑的控制和LIN协议的实现都包含一些时间特性相关的功能[1],为此笔者设计了一个高效的定时器模块。下面就从设计原理、结构设计、定时器管理及应用上讲述下该定时器模块的设计与实现。
设计原理
在车身控制器(以下以BCM来代称)的设计中,其定时功能可以分为两类,一个是TIMEOUT超时,一个是COUNTER计时,前者超时时间已知,超时则触发相关操作,后者是计时请求,在一种状态发生变化时统计新的状态的维持时间。通过对BCM定时功能及特性进行分析,发现其定时应用的特点为:
1、定时精度要求不高,但定时数量比较多;
2、TIMEOUT超时中,有循环定时,也有单次定时和多次定时。
由于硬件资源有限,不可能为每一个定时应用单独分配一个硬件定时器,所以采用单个硬件定时器模拟多个软件定时器的方法,来满足应用中的定时需要[2]。首先根据定时应用的特点和分类,设计软件定时器的数据结构,以结构体数组的形式将这些软件定时器组织起来,数组成员便是各个软件定时器节点;然后在驱动程序的设计中设计良好的API接口,该API接口足够清晰,提供统一的调用接口,可以涵盖定时器所有功能,这样便在一个硬件定时器上实现了多个软件定时器。下面便详述一下定时器结构和驱动程序设计。
定时器结构设计
由于软件定时器数量繁多,根据定时应用的实现方式及特征设计一个良好的数据结构是非常必要的[3]。在其结构体设计中,其成员变量可以描述所有的“定时特征”并且提供良好的可读写接口。其定义如下所示:
typedef struct {
TimerState timer_state;
ulong timeout;
ulong duration;
unsigned cycle:1;
unsigned overow_ag:1;
unsigned cnt_times:8;
TimerId timer_id;
}Timer;
timer_state有STALL和RUNNING两种取值,表示该定时器是否处于运转状态;timeout是超时应用的超时值,duration表示定时器启动以来的计时时间长度;cycle表示该定时是周期定时还是单次定时;cnt_times是对多次定时(既非周期也非单次)的统计,当定时次数到达后,则停止该定时器;overow_ag标识是否发生超时溢出;所有的“软件定时器节点”组成Timer数组,其数据成员由timer_id枚举,其枚举类型TimerId定义如下所示:
typedef enum{
FEEDWATCHDOG_300MS,
INPUT_DETECT_MS,
LIN_TIMESLOT_MS,
SPEED_PULSE_ACCUMU_200MS,
ALLDR_LOCK_200MS,
ALARM_30S,
IGNITION_OFF_60S,
...
...
MAX_TIMER_NUM
}TimerId;
这样,定义数组Timer TIMER[MAX_TIMER_NUM],在初始化中,TIMER [i].timer_id=i;之后通过TIMER[timer_id]即可枚举某软件定时器节点。
定时器管理
定时器管理包括启动、运行、停止、重启和读取计时时间等功能[4],相应API函数定义如下:
void TimerStart(TimerId timer_id,ulong timeout,Bool cycle,uchar cnt_times);
void TimerReStart(TimerId timer_id);
void TimerTick(void);
void TimerStop(TimerId timer_id);
void TimerStall(TimerId timer_id);
ulong TimerGet(TimerId timer_id);
启动定时器函数如下:
#dene RTIPERIOD 2
void TimerStart(TimerId timer_id,ulong timeout,Bool cycle,uchar cnt_times)
{
TIMER[timer_id].timer_state=RUNNING;
TIMER[timer_id].duration=0;
TIMER[timer_id].timeout=timeout/RTIPERIOD;
TIMER[timer_id].cycle=cycle;
TIMER[timer_id].cnt_times=cnt_times;
TIMER[timer_id].timer_id=timer_id;
}
可见,启动某个软件定时器便是设置由timer_id枚举的TIMER数组成员的各个成员变量,下面详细介绍软件定时器的运行。
作为所有软件定时器的基准源,硬件定时器设定为2ms的周期定时,在时钟中断服务程序中全局时钟嘀嗒Jiffs累加,TimerTicked置1,软件定时器运行函数如下:
void TimerTick(void)
{
uint timer_index;
if(0==TimerTicked)
{
return ;
}
for(ti
- VxWorks实时操作系统下MPC8260ATM驱动的实现(11-11)
- Linux内核解读入门(11-09)
- Linux操作系统网络驱动程序编写(04-11)
- Linux系统对ISA总线DMA的实现(06-19)
- 基于MPEG-4的嵌入式多媒体监控系统中压缩/解压卡的设计与实现(10-15)
- Windows CE下驱动程序开发基础(04-10)