我本身也是个初学者,喜欢嵌入式而自学ucos系统,ucos是个开源的代码,短小而又简单,这是我学习的笔记,希望能对喜欢ucos的人有一点帮助,
我自身也是个初学者,喜爱嵌入式而自学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
OSTmrState在ucos_ii.h中有以下几种类型:
OS_TMR_STATE_UNUSED 不存在这个守时器
OS_TMR_STATE_RUNNING 这个守时器正在运转
OS_TMR_STATE_COMPLETED这个守时器现已跑完了
OS_TMR_STATE_STOPPED 这个守时器中止了
参数:
- Dly 守时时刻,假设是这个守时器只用一次,那么就用这个,假设守时器要重复用那么它是第一次时用,以后用period。
- Period 守时器从复用时会用到这个作守时时刻。
- 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_PERIOD
IC 2u
守时器会主动重装
#define
OS_TMR_OPT_CALLBACK
3u
OSTmrStop()中运用,调用回调函数,但不带参数
#define
OS_TMR_OPT_CALLBACK_ARG
4u
也是OSTmrStop()中运用,调用回调函数,但有参数。
- Callback 指向回调函数的指针,这个函数这样声明,void mycallback(OS_TMR *ptmr, void p_arg );
- Callback_arg 参数给callback的。
- Pname 守时器的姓名
- 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)
- Ptmr 指向守时器结构体。
- 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)开释守时器结构体用它把该守时器从守时器轮中卸下。
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/yingyong/5g/260062.html