关于ucos中os_tmr.c中的代码分析

   我本身也是个初学者,喜欢嵌入式而自学ucos系统,ucos是个开源的代码,短小而又简单,这是我学习的笔记,希望能对喜欢ucos的人有一点帮助,因本人也是初学者,如有错误迎指点。一般的书多是2.5版本,没有os_tmr.c,所以我写了关于这部分代码的分析。

我读ucos.中的os_tmr.c:

        我想这个文件里就是为了写一个建立在操作系统的定时器,原来我们学的时钟节拍就像cpu总线时钟脉冲一样。我们建立的是定时器结构体,在os_tmr.c中有一个函数OSTmr_Task()这个函数对定时器结构体的信息进行处理,在定时时间到了时候,该定时器中的一个指向回调函数的指针就调用这个回调节器函数进行工作,当然,你要写回调函数,不然就什么也不做,以前做过ucos移植的人知道要写一个硬件定时器中断函数,这回要加个OSTmrSignal()这里有个发送信号。我们学硬件时知道,用到硬件定时器时要给它一个计算脉冲。这个软件定时器也要一个计算脉冲。我们建立的定时器结构体都会挂到OSTmrWheelTbl[OS_TMR_CFG_WHEEL_SIZE]上面,OS_TMR_CFG_WHEEL+SIZE是要自己定义的,至于挂到OSTmrWheelTbl[0]OSTmrWheelTbl[OS_TMR_CFG_WHEEL_SIZE-1]哪一个上,只要看一下OSTmr_Link (OS_TMR *ptmr, INT8U type)就明白了,而且一个OSTmrWheelTbl[n]上可以挂很多个定时器结构体。

一、定时器的建立:

        定时器是在我们的应用程序中建立的,

OS_TMR  *OSTmrCreate (INT32U           dly,

                      INT32U           period,

                      INT8U           opt,

                      OS_TMR_CALLBACK  callback,

                      void            *callback_arg,

                      INT8U           *pname,

                      INT8U           *perr)

想使用定时器那些函数要在os_cfg.h中定义OS_TMR_EN

返回值是os_tmr结构体(定义在ucos_ii.h中)。

typedef  struct  os_tmr {

INT8U            OSTmrType;                      

OS_TMR_CALLBACK  OSTmrCallback;                  

void            *OSTmrCallbackArg;               

void            *OSTmrNext;                     

    void           *OSTmrPrev;

INT32U           OSTmrMatch;                OSTmrTime == OSTmrMatch定时器到时间了。  

INT32U           OSTmrDly;                       

INT32U           OSTmrPeriod;                    

#if OS_TMR_CFG_NAME_EN > 0u

INT8U           *OSTmrName;                     

#endif

INT8U            OSTmrOpt;                      

INT8U            OSTmrState;                                                                                                              

} OS_TMR;

OSTmrType类型定义在ucos_ii.h中:OS_TMR_TYPE

OS_ARG_CHK_EN要在os_cfg.h中定义一下,来确定要不要一些功能。

OS_TMR_CFG_NAME_EN要你自己在os_cfg.h中定义,来控制要不要用OSTmrName

OSTmrStateucos_ii.h中有以下几种类型:

       OS_TMR_STATE_UNUSED  不存在这个定时器                                    

       OS_TMR_STATE_RUNNING 这个定时器正在运行 

          OS_TMR_STATE_COMPLETED这个定时器已经跑完了                                 

       OS_TMR_STATE_STOPPED  这个定时器停止了  

参数:

1、  Dly           定时时间,如果是这个定时器只用一次,那么就用这个,如果定时器要反复用那么它是第一次时用,以后用period

2、  Period      定时器从复用时会用到这个作定时时间。

3、  Opt          这里有两种选项,告诉我们是只用一次还是反复使用。只用一次OS_TMR_OPT_ONE_SHOT,反复使用OS_TMR_OPT_PERIODIC。这些定义在ucos_ii.h中。

定时器选项有五种

#define  OS_TMR_OPT_NONE                   0u   没有选择

#define  OS_TMR_OPT_ONE_SHOT               1u   定时器不会自动重复使用

#define  OS_TMR_OPT_PERIODIC                  2u   定时器会自动重装

#define  OS_TMR_OPT_CALLBACK                 3u   OSTmrStop()中使用,调用回调函数,但不带参数

#define  OS_TMR_OPT_CALLBACK_ARG           4u    也是OSTmrStop()中使用,调用回调函数,但有参数。

4、  Callback   指向回调函数的指针,这个函数这样声明,void mycallback(OS_TMR *ptmr,  void p_arg );

5、  Callback_arg     参数给callback的。

6、  Pname     定时器的名字

7、  Perr     错误指针*         OS_ERR_NONE                          没有错误

                               OS_ERR_TMR_INVALID_DLY                无效的定时时间

                               OS_ERR_TMR_INVALID_PERIOD             无效的周期

                          OS_ERR_TMR_INVALID_OPT                                 无效的选项

                               OS_ERR_TMR_ISR                        在中断中调用

                              OS_ERR_TMR_NON_AVAIL                 空的定时器用光了,这个和task一样意思。

用到的函数OSTmr_Alloc()得到一个定时器结构体。

二、删除一个定时器,也是在我们的功能函数中使用,返回为是否成功删除。

BOOLEAN  OSTmrDel (OS_TMR  *ptmr,

                   INT8U   *perr)

1、  Ptmr 指向定时器结构体。

2、  Perr  指向错误的指针。

这里用到这两个函数OSTmr_Unlink(ptmr); 如果是定时器在工作时,要用它解除OSTmrState= OS_TMR_STATE_STOPPED                        

                  OSTmr_Free(ptmr);  释放这个定时器结构体。

三、得到定时器名字的函数,返回名字的长度。

INT8U  OSTmrNameGet (OS_TMR   *ptmr,

                     INT8U   **pdest, 指向了一个指向定时器名字地址指针的指针。

                     INT8U    *perr)

四、定时器还有多长时间溢出。返回还有多长时间溢出。

INT32U  OSTmrRemainGet (OS_TMR  *ptmr,

                        INT8U   *perr)

五、获得定时器状态的函数,返回状态。             

INT8U  OSTmrStateGet (OS_TMR  *ptmr,

                      INT8U   *perr)

六、启动你的定时器,返回是否成功启动。           你的应用程序使用它

BOOLEAN  OSTmrStart (OS_TMR   *ptmr,             要用到OSTmr_Unlink()和OSTmr_Link()先

                     INT8U    *perr)            解除,再重新用这个定时器

七、停止定时器,返回是否成功停止。              你的应用程序使用它 

BOOLEAN  OSTmrStop (OS_TMR  *ptmr,

                    INT8U    opt,

                    void    *callback_arg,  这个也是个函数

                    INT8U   *perr)

回调函数在这里使用,callback()。

OptOS_TMR_OPT_NONE不使用回调函数。

OS_TMR_OPT_CALLBACK使用回调函数不用参数。

OS_TMR_OPT_CALLBACK_ARG要使用参数。

八、发送信号,这个是在timer tick中使用要您写到ISR

INT8U  OSTmrSignal (void)返回信号量。

九、从定时器池中得到一个结构体。在建构函数中用

static  OS_TMR  *OSTmr_Alloc (void)

十、释放定时器,中删除函数中用

static  void  OSTmr_Free (OS_TMR *ptmr)

十一、OSTmr_Init(void),OSInit()中用。

十二、static  void  OSTmr_InitTask (void)OSTmr_Init中使用。用来建立一个任务OSTmr_Task()

十三、OSTmr_Task()这个是调度你建立的定时器用的,一但定时时间到就调用回调函数。

我们建立的定时器都进入定时器轮盘里OSTmrWheelTbl[]

十四、static  void  OSTmr_Link (OS_TMR  *ptmr,         //OSTmrState = OS_TMR_STATE_RUNNING

                          INT8U    type)

Ptmr->OSTmrMatch的确定方法   

if (type == OS_TMR_LINK_PERIODIC) {                          

        ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;

    } else {

        if (ptmr->OSTmrDly == 0) {

            ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;

        } else {

            ptmr->OSTmrMatch = ptmr->OSTmrDly    + OSTmrTime;

        }

    }

挂载定时器时spoke  = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE);

pspoke = &OSTmrWheelTbl[spoke];这样确定的置位,当OSTmrTime加到和OSTmrMatch相等时一定会来以这个spoke为下标的数组里找该定时器。至于定义一个OSTmrWheelTbl[]而不是把你所有建立的定时器串成一串是怕一起处理浪费时间吧,这样可以一次少处理几个定时器。

我想看了OSTmr_Task (void *p_arg)这个函数的人可能会好奇为什么用那种方法挂载定时器,当定时时间到了时会找到OSTmrWheelTbl[]正确的下标,并在那个OSTmrWheelTbl[ok]里找到该定时器吧。其实你可以算一下,定义OS_TMR_CFG_WHEEL_SIZE=8,然后在OSTmrTime=6时建立一个定时器(假如定时器只工作一次),OSTmrDly=12,那个这个定时器会挂到OSTmrWheelTbl[2]中,当OSTmrTime加到18时它就会去

OSTmrWheelTbl[2]找该定时器。

十五、static  void  OSTmr_Unlink (OS_TMR *ptmr)释放定时器结构体用它把该定时器从定时器轮中卸下。   

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值