2021SC@SDUSC
软件定时器的数据结构
软件定时器控制块
每个软件定时器都有对应的软件定时器控制块,每个软件定时器控制块都包含了软件定时器的基本信息,如软件定时器的状态、软件定时器工作模式、软件定时器的周期,剩余时间,以及软件定时器回调函数等信息。
typedef struct k_timer_st {
#if TOS_CFG_OBJECT_VERIFY_EN > 0u
knl_obj_t knl_obj;
#endif
k_timer_callback_t cb;
void *cb_arg;
k_list_t list;
k_tick_t expires;
k_tick_t delay;
k_tick_t period;
k_opt_t opt;
timer_state_t state;
} k_timer_t;
软件定时器的工作模式
#define TOS_OPT_TIMER_ONESHOT (k_opt_t)(0x0001u)
#define TOS_OPT_TIMER_PERIODIC (k_opt_t)(0x0002u)
TOS_OPT_TIMER_ONESHOT :单次模式,软件定时器在超时后,只会执行一次回调函数,它的状态将被设置为TIMER_STATE_COMPLETED ,不再重新执行它的回调函数,当然,用户还是可以重新启动这个单次模式的软件定时器,它并未被删除。
TOS_OPT_TIMER_PERIODIC :周期模式 ,软件定时器在超时后,会执行对应的回调函数,同时根据软件定时器控制块中的period成员变量的值再重新插入软件定时器列表中,这个定时器会按照指定的定时时间循环执行(周期性执行)回调函数,直到用户将定时器删除。
软件定时器的状态
定时器状态有以下几种:
typedef enum timer_state_en {
TIMER_STATE_UNUSED,
TIMER_STATE_STOPPED,
TIMER_STATE_RUNNING,
TIMER_STATE_COMPLETED
} timer_state_t;
TIMER_STATE_UNUSED :未使用状态。TIMER_STATE_STOPPED :创建了软件定时器,但此时软件定时器未启动或者处于停止状态,调用tos_timer_create() 函数接口或者在软件定时器启动后调用tos_timer_stop() 函数接口后,定时器将变成该状态。TIMER_STATE_RUNNING :软件定时器处于运行状态,在定时器被创建后调用tos_timer_start() 函数接口,定时器将变成该状态,表示定时器运行时的状态。TIMER_STATE_COMPLETED :软件定时器已到期,只有在软件定时器的模式选择为TOS_OPT_TIMER_ONESHOT 时才可能发生,表示软件定时器已经完成了。
创建软件定时器
函数
__API__ k_err_t tos_timer_create(k_timer_t *tmr,
k_tick_t delay,
k_tick_t period,
k_timer_callback_t callback,
void *cb_arg,
k_opt_t opt);
参数
tmr 软件定时器控制块指针 delay 软件定时器第一次运行的延迟时间间隔 period 软件定时器的周期 callback 软件定时器的回调函数,在超时时调用(由用户自己定义) cb_arg 用于回调函数传入的形参(void指针类型) opt 软件定时器的工作模式(单次 / 周期)
创建软件定时器过程
- 判断传入的参数是否正确:软件定时器控制块不为
null ,回调函数不为null ,如果是创建周期模式的软件定时器,那么 period 参数则不可以为0 ,而如果是单次模式的软件定时器,参数delay 则不可以为0 ,无论是何种模式的软件定时器,delay 参数与 period 参数都不可以为K_ERR_TIMER_PERIOD_FOREVER 。 - 根据传入的参数将软件定时器控制块的成员变量赋初值,软件定时器状态
state 被设置为TIMER_STATE_STOPPED ,expires 则被设置为0 ,因为还尚未启动软件定时器。 - 调用
tos_list_init() 函数将软件定时器控制块中可挂载到k_tick_list 列表的节点初始化。
__API__ k_err_t tos_timer_create(k_timer_t *tmr,
k_tick_t delay,
k_tick_t period,
k_timer_callback_t callback,
void *cb_arg,
k_opt_t opt)
{
TOS_PTR_SANITY_CHECK(tmr);
TOS_PTR_SANITY_CHECK(callback);
if (opt == TOS_OPT_TIMER_PERIODIC && period == (k_tick_t)0u) {
return K_ERR_TIMER_INVALID_PERIOD;
}
if (opt == TOS_OPT_TIMER_ONESHOT && delay == (k_tick_t)0u) {
return K_ERR_TIMER_INVALID_DELAY;
}
if (opt != TOS_OPT_TIMER_ONESHOT && opt != TOS_OPT_TIMER_PERIODIC) {
return K_ERR_TIMER_INVALID_OPT;
}
if (delay == TOS_TIME_FOREVER) {
return K_ERR_TIMER_DELAY_FOREVER;
}
if (period == TOS_TIME_FOREVER) {
return K_ERR_TIMER_PERIOD_FOREVER;
}
#if TOS_CFG_OBJECT_VERIFY_EN > 0u
knl_object_init(&tmr->knl_obj, KNL_OBJ_TYPE_TIMER);
#endif
tmr->state = TIMER_STATE_STOPPED;
tmr->delay = delay;
tmr->expires = (k_tick_t)0u;
tmr->period = period;
tmr->opt = opt;
tmr->cb = callback;
tmr->cb_arg = cb_arg;
tos_list_init(&tmr->list);
return K_ERR_NONE;
}
销毁软件定时器
软件定时器销毁函数是根据软件定时器控制块直接销毁的,销毁之后软件定时器的所有信息都会被清除,而且不能再次使用这个软件定时器,如果软件定时器处于运行状态,那么就需要将被销毁的软件定时器停止,然后再进行销毁操作。 其过程如下:
- 判断软件定时器是否有效,然后根据软件定时器状态判断软件定时器是否创建,如果是未使用状态
TIMER_STATE_UNUSED ,则直接返回错误代码K_ERR_TIMER_INACTIVE 。 - 如果软件定时器状态是 运行状态
TIMER_STATE_RUNNING ,那么调用timer_takeoff() 函数将软件定时器停止。 - 最后调用
timer_reset() 函数将软件定时器控制块的内容重置,主要是将软件定时器的状态设置为未使用状态TIMER_STATE_UNUSED ,将对应的回调函数设置为null 。
__API__ k_err_t tos_timer_destroy(k_timer_t *tmr)
{
TOS_PTR_SANITY_CHECK(tmr);
#if TOS_CFG_OBJECT_VERIFY_EN > 0u
if (!knl_object_verify(&tmr->knl_obj, KNL_OBJ_TYPE_TIMER)) {
return K_ERR_OBJ_INVALID;
}
#endif
if (tmr->state == TIMER_STATE_UNUSED) {
return K_ERR_TIMER_INACTIVE;
}
if (tmr->state == TIMER_STATE_RUNNING) {
timer_takeoff(tmr);
}
timer_reset(tmr);
return K_ERR_NONE;
}
|