新闻中心

EEPW首页>嵌入式系统>设计应用> 关于ucos中os_tmr.c中的代码分析

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

作者: 时间:2016-11-24 来源:网络 收藏
我本身也是个初学者,喜欢 嵌入式而自学 ucos系统,u cos是个开源的代码,短小而又简单,这是我学习的笔记,希望能对喜欢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
OSTmrState在ucos_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()中使用,调用回调函数,但有参数。
  1. Callback指向回调函数的指针,这个函数这样声明,void mycallback(OS_TMR *ptmr,void p_arg );
  2. Callback_arg参数给callback的。
  3. Pname定时器的名字
  4. 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()。
Opt 为OS_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)释放定时器结构体用它把该定时器从定时器轮中卸下。


关键词:ucosos_tmrc代码分

评论


技术专区

关闭