加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSSRSS-巴斯仪表网
您当前的位置:首页 > 电子发烧 > 单片机学习

VxWorks通用定时器设计与实现

时间:2013-09-08  来源:123485.com  作者:9stone

摘要:在进行网络通信设备开发时,需要使用通用定时器。本文在研究VxWorks系统看门狗函数的基础上,提出了基于看门狗函数的定制定时器的设计方法,可以使定制定时器的最小周期满足网络通信设备开发的需要 本文给出了定制定时器实现的思想。

1 概述
    VxWorks是WindRiver公司开发的具有工业领导地位的高性能实时操作系统内核,具有先进的网络功能,易于设计高效的嵌入式系统 目前已成为嵌入式操作系统的首选,并将其作为通信产品的软件平台。
    在进行网络通信设备开发时,需要用到定时器,如以周期为m秒对某个端口进行查询、以周期为n分对某个设备的性能数据进行统计等。而VxWorks只提供了像watchDog(看门狗),而没有提供一个通用的定时器。本文提出的通用定时器设计方法,占用系统资源少,运行效率高,并可根据需要定制满足要求的定时器。

2 通用定时器的基本原理
    虽然在Vxworks没有提供像windows中的定时器一样好用的定时器,但可以利用VxWorks的看门狗来实现定时器。对看门狗的操作函数主要有三个:创建看门狗函数WDOG_ID wdCreate(void);启动看门狗函数STATUS wdStart(WDOG_ID wdId,int delay,FUNCPTR pRoutine,int parameter);删除看门狗函数STATUS wdDelete(WDOG_ID wdId)。
通过对看门狗启动函数进行研究发现,如果能够在看门狗的响应函数中重新启动看门狗.那么就可以实现以一个固定的周期循环执行的定时器。以下是定时器的基本框架:

void settimer(int interval)
{ int in_interval;
m_interval=sysClkRateGet()*interval;/*将延时秒数转化为ticks数*/
gm wdID =wdCreate();/*创建看门狗*/
if(gm_perfHist_wdID = NULL)
{
printf("Could not create watchdog timer/n");
return ;
}
if(wdStart(gm_wdID,m_interval,(FUNCPTR)
action_func,interval) = ERROR)
/*启动看门狗*/
{
 printf ("Error in starting routine associated with timer/n");
wdDelete(gm_wdlD);/*如果启动看门狗不成功,则删除看门狗*/
return;
}
return;
}
void action_func(int interval)
{ int m_interval;
m_interval=sysClkRateGet()*interval;/*将延时秒数转化为ticks数*/
if(wdStart(gm_wdID,m_interval,(FUNCPTR)action_fnnc,interval)= ERROR)
/*启动看门狗*/
{
printf ("Error in starting routine associated with timer/n");
wdDelete(gm_wdID);
return;
}
/*执行用户函数*/
……
}
用户只需调用settimer并给出以秒为单位的定时器周期,就可以建立一个定时器。

3 通用定时器设计
    通过调用settimer可实现一个基本的定时器,但在程序中对定时器的要求比较复杂。如有可能在运行过程中,要求加人某个需用轮询的函数,这样就要建立一个较为通用的定时器。
3.1 通用定时器的设计思想
  通用定时器应能满足用户的要求.要能动态地将用户需轮询函数加入到定时器的轮询队列中。要实现动态加载用户需轮询函数,可将用户需轮询函数串接成一个链表(链表的每个结点称为一个定时器用户)。在每个定时器周期到期时,遍历定时器用户链表,执行用户函数,这样就可以实现动态加载用户需轮询函数。
  如果轮询周期与定时器周期相同,那么加入的用户轮询函数,在第一次执行时,其周期将会小于所要求的轮询周期,在最坏情况下,可能相差近一个周期。要解决这个问题可将定时器的周期设置为较小,且在定时器用户结点中记录用户的轮询周期和距离轮询周期到期所剩余时间,在定时器到期时,用剩余时间减去定时器周期,如果结果小于零,就执行用户函数。用这种方法可以解决第一次执行时的时差较大问题;另一方面,动态加载的用户函数可以以不同的周期进行轮询。
  另一个问题是在定时器到期时遍历定时器用户链表并执行相关用户函数时的效率:如果用户函数执行时间较长(如板间通信),由于函数的执行会影响链表下一个结点函数的执行。为解决这个问题可以为每个用户函数启动一个任务。但反复地为用户创建、删除任务,会加重系统的开销。解决这个问题可以在创建定时器用户时,就为定时器用户的响应函数创建一个任务,并将此任务挂起。当要求的轮询周期到期时,唤醒此任务;为了能够正确地对此任务进行操作,就要在定时器用户结点的数据结构中增加一个关联任务标识。在创建定时器用户时,由用户指明是否为其响应函数创建关联任务。这样,在定时器遍历定时器用户链表时,如果检测到关联任务为无效值时,就直接执行用户函数,而不创建新的任务。
  根据通用定时器的设计思想,可以设计出通用定时器结构如附图所示:
 
    系统初始化时,将设置并启动一个默认的周期为1秒的定时器0,此定时可以满足大部分用户的要求;如果此定时器不能满足用户的要求,也可以定制自己的定时器,在不需要使用定制的定时器时,要将其删除,否则由于定时器要占用一定的系统资源,而造成系统资源的浪费。但系统默认定时器0是无法删除的。
  用户可以将需要以一定周期运行的函数加入到符合要求的定时器的用户队列中,这样用户的函数就可以以一定周期运行 当用户认为已经加入定时器用户队列的函数,不需要再周期性运行时,可以将其从队列中删除。

3.3 通用定时器的数据结构
通用定时器的数据结构分为两部分,即定时器数据结构和定时器用户数据结构。

  1. 定时器数据结构:描述定时器的信息。包括用于标识此定时器的ID、用于分配定时器用户ID的有效索引值、定时器的周期、定时器所用的看门狗ID以及定时器用户队列
  2. 定时器用户数据结构:描述每个加入定时器的用户的信息。主要有定时器用户ID、用户指定的轮询周期、距离用户指定周期到期剩余时间、用户响应函数及响应函数所带的参数以及参数长度。为了方便不同用户使用,应将响应函数所带参数设置为无符号指针,这样用户就可以设置任何一种数据类型。如果用户参数较多,可以采用结构指针。

3.4 通用定时器的具体实现
通用定时器的实现主要包括下面几类函数:
①定时器核心实现函数:将定时器的实现框架进行扩充,使其能够以较小的周期运行。当一周期到期时,依次遍历定时器的用户链表,将每个定时器用户结点的剩余时间域减去定时器周期,如果小于零,说明用户指定的周期已经到期,则执行用户的响
应函数。如果此结点的关联任务ID域为一个有效值,则唤醒相应的任务,否则直接执行用户响应函数。
② 定时器初始化函数:主要完成的操作是首先设置一个全局的定时器链表针,建立一个系统默认定时器0,并启动这个默认定时器,在用户开始使用定时器时,一定要对定时器系统进行初始化。
③创建定制定时器函数:在系统初始化后默认创建了一个的定时器,但这个定时器可能不能完全满足用户的要求,有的可能要求首次运行其响应函数的时差精度小于1秒,因此定制定时器的周期允许小于1秒。考虑到VxWorks中的实际情况,这里规定定时的最小周期为0.1秒。wxWorks中的看门狗是以click为时间单位,1秒等于60个click。因此.如果要求的周期太小,导致定时器占用的CPU时间过长而降低系统性能。
要注意的是在vxWorks中不提供强制类型转换,所以,在使用此函数时,如果输入参数为整数则应以小数形式给出,例如:参数为15,则要输入15.0。
④ 删除定制定时器函数:当用户不再使用定制的定时器时,要删除自己创建的定制定时器。输入的参数为已经存在的定时器的ID
⑤ 创建定时器用户函数:要将一个需轮询的用户函数动态地加入到一个符台要求的定时器中,必须在这个定时器的定时器用户链表中为这个用户函数创建一个相应的结点,这样就可以按用户要求的周期去周期性地调用用户响应函数。根据通用定时器设计,如果用户响应函数执行时间较长则要为其创建一个任务。创建定时器用户时,需要指定以下参数:
timerID:定时器ID,如果使用默认定时器,则设
置为0;如果使用用户定制定时器,则要填入由定制定时器函数返回的定时器ID。
interval:用户要求的运行周期;
actionFunc:用户要求周期性运行的函数;
param:用户函数的参数指针;
pgram_fen:用户函数参数的长度;
createTask:是否为用户响应函数创建一个任务,1:创建,0:不创建。
⑥ 删除定时器用户函数:当用户不再需要对定期轮询某个函数时,要将其从定时器用户链表中删除。

4 定时器的应用
  在使用通用定时器之前,要先初始化定时器系统,这样就会在系统中,生成一个周期为1秒的定时器,如果用户要求的轮询时差精度大于1秒,则可将自己要轮询的函数,用创建定时器用户函数加入到默认定时器的定时器用户链表中,如果要求系统创建任务则将最尾一个参数设为1。
   如果系统默认的定时器0精度不能满足其要求,则用户可以用创建定制定时器函数创建一个定制的定时器。当此定时器不再需要时,要将它删除。
   本文设计的这个通用定时器,已经应用于一个实际的网络设备中,其运行平稳.占用系统资源少,且可以满足各种不同用户的需要。


分享到:
来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
栏目导航->单片机学习
  • 电子应用基础
  • 电源技术
  • 无线传输技术
  • 信号处理
  • PCB设计
  • EDA技术
  • 单片机学习
  • 电子工具设备
  • 技术文章
  • 精彩拆解欣赏
  • 推荐资讯
    使用普通运放的仪表放大器
    使用普通运放的仪表放
    3V与5V混合系统中逻辑器接口问题
    3V与5V混合系统中逻辑
    数字PID控制及其改进算法的应用
    数字PID控制及其改进
    恶劣环境下的高性价比AD信号处理数据采集系统
    恶劣环境下的高性价比
    栏目更新
    栏目热门