定时器管理
简介
定时器按照执行的次数,可分为两种:一种是单次触发定时器,即只会触发一次超时,之后该定时器停止;另外一种是周期性定时器,即按照设定的时间周期性地超时,除非被手动停止。这两种模式可以在创建/初始化时通过OS_TIMER_FLAG_ONE_SHOT和OS_TIMER_FLAG_PERIODIC来指定,默认为OS_TIMER_FLAG_ONE_SHOT。
按照超时函数执行的上下文环境,可分为两种:一种是HARD_TIMER模式,在中断上下文环境中执行,使用这种定时器时需要注意超时函数应尽量短,且不应该有会导致任务挂起的操作;另外一种是SOFT_TIMER,在任务环境中执行。这两种模式可以在创建/初始化时通过OS_TIMER_FLAG_HARD_TIMER和OS_TIMER_FLAG_SOFT_TIMER来指定,默认为OS_TIMER_FLAG_HARD_TIMER。
重要定义及数据结构
宏定义
#define OS_TIMER_FLAG_ONE_SHOT 0x0 /**< one shot timer */
#define OS_TIMER_FLAG_PERIODIC 0x2 /**< periodic timer */
#define OS_TIMER_FLAG_HARD_TIMER 0x0 /**< hard timer,the timer's callback function will be called in tick isr. */
#define OS_TIMER_FLAG_SOFT_TIMER 0x4 /**< soft timer,the timer's callback function will be called in timer task. */
定义 | 说明 |
---|---|
OS_TIMER_FLAG_ONE_SHOT | 一次性定时器 |
OS_TIMER_FLAG_PERIODIC | 周期性定时器 |
OS_TIMER_FLAG_HARD_TIMER | HARD_TIMER,回调函数在tick中断服务程序中被执行 |
OS_TIMER_FLAG_SOFT_TIMER | SOFT_TIMER,回调函数在timer task中被执行 |
枚举
enum os_timer_ctrl_cmd
{
OS_TIMER_CTRL_SET_TIME = 0x0,
OS_TIMER_CTRL_GET_TIME,
OS_TIMER_CTRL_SET_ONESHOT,
OS_TIMER_CTRL_SET_PERIODIC
};
定义 | 说明 |
---|---|
OS_TIMER_CTRL_SET_TIME | 设置定时器的超时时间 |
OS_TIMER_CTRL_GET_TIME | 获取定时器的超时时间 |
OS_TIMER_CTRL_SET_ONESHOT | 设置定时器为一次性定时器 |
OS_TIMER_CTRL_SET_PERIODIC | 设置定时器为周期性定时器 |
结构体
struct os_timer
{
os_object_t parent; /* Inherit from os_object. */
os_list_node_t row[OS_TIMER_SKIP_LIST_LEVEL];
void (*timeout_func)(void *parameter); /* Timeout function. */
void *parameter; /* Timeout function's parameter. */
os_tick_t init_tick; /* Timer timeout tick. */
os_tick_t timeout_tick; /* Timeout tick. */
};
struct os_timer重要参数 | 说明 |
---|---|
row | 跳表节点,用于将该定时器句柄添加到定时器跳表中 |
timeout_func | 超时函数 |
parameter | 超时函数的参数 |
init_tick | 超时时间(以tick为单位) |
timeout_tick | 超时时刻的系统时间(即定时器启动时的系统时间加上init_tick) |
API列表
接口 | 说明 |
---|---|
os_timer_init | 定时器静态方式初始化,即定时器对象由使用者提供 |
os_timer_deinit | 定时器反初始化, os_timer_init()匹配使用 |
os_timer_create | 定时器动态创建并初始化,与os_timer_init()达到的效果一样,区别在于内存通过动态申请的方式获得 |
os_timer_destroy | 定时器动态销毁,与os_timer_create()匹配使用 |
os_timer_start | 启动定时器 |
os_timer_stop | 停止定时器 |
os_timer_control | 控制或更改定时器的属性 |
os_timer_init
该函数用于以静态方式初始化定时器,即定时器对象由使用者提供,其函数原型如下:
void os_timer_init(os_timer_t *timer,
const char *name,
void (*timeout)(void *parameter),
void *parameter,
os_tick_t time,
os_uint8_t flag);
参数 | 说明 |
---|---|
timer | 定时器句柄(定时器控制块指针),其空间由使用者提供 |
name | 定时器名字 |
timeout | 超时函数,时间达到时此函数被调用 |
parameter | 超时函数的参数 |
time | 超时时间 |
flag | 参数,可配置两种属性:第一种为设定单次定时器OS_TIMER_FLAG_ONE_SHOT或周期定时器OS_TIMER_FLAG_PERIODIC;第二种为设定硬件定时器OS_TIMER_FLAG_HARD_TIMER或软件定时器OS_TIMER_FLAG_SOFT_TIMER;这两种属性可以取“或”的关系 |
返回 | 说明 |
无 | 无 |
os_timer_deinit
该函数用于反初始化静态定时器,会把该定时器从系统容器的定时器链表中删除,其函数原型如下:
void os_timer_deinit(os_timer_t *timer);
参数 | 说明 |
---|---|
timer | 定时器句柄 |
返回 | 说明 |
无 | 无 |
os_timer_create
该函数用于以动态方式创建定时器,会为定时器控制块分配内存并初始化,与os_timer_init()达到的效果一样,函数原型如下:
os_timer_t *os_timer_create(const char *name,
void (*timeout)(void *parameter),
void *parameter,
os_tick_t time,
os_uint8_t flag);
参数 | 说明 |
---|---|
name | 定时器名字 |
timeout | 超时函数,时间达到时此函数被调用 |
parameter | 超时函数的参数 |
time | 超时时间 |
flag | 参数,可配置两种属性:第一种为设定单次定时器OS_TIMER_FLAG_ONE_SHOT或周期定时器OS_TIMER_FLAG_PERIODIC;第二种为设定硬件定时器OS_TIMER_FLAG_HARD_TIMER或软件定时器OS_TIMER_FLAG_SOFT_TIMER;这两种属性可以取“或”的关系 |
返回 | 说明 |
非OS_NULL | 定时器句柄 |
OS_NULL | 创建失败 |
os_timer_destroy
该函数用于销毁动态创建的定时器,会把该定时器从定时器链表中删除,并释放定时器控制块的内存,其函数原型如下:
os_err_t os_timer_destroy(os_timer_t *timer);
参数 | 说明 |
---|---|
timer | 定时器句柄 |
返回 | 说明 |
OS_EOK | 定时器销毁成功 |
os_timer_start
该函数用于启动定时器,函数原型如下:
os_err_t os_timer_start(os_timer_t *timer);
参数 | 说明 |
---|---|
timer | 定时器句柄 |
返回 | 说明 |
OS_EOK | 启动成功 |
os_timer_stop
该函数用于停止定时器,函数原型如下:
os_err_t os_timer_stop(os_timer_t *timer);
参数 | 说明 |
---|---|
timer | 定时器句柄 |
返回 | 说明 |
OS_EOK | 停止成功 |
OS_ERROR | 停止失败,定时器之前已处于停止状态 |
os_timer_control
该函数用于控制或者修改定时器的属性,其函数原型如下:
os_err_t os_timer_control(os_timer_t *timer, enum os_timer_ctrl_cmd cmd, void *arg);
参数 | 说明 |
---|---|
timer | 定时器句柄 |
cmd | 控制命令,具体参考枚举定义os_timer_ctrl_cmd |
arg | 若cmd为OS_TIMER_CTRL_GET_TIME,则arg为读取的超时时间;若cmd为OS_TIMER_CTRL_SET_TIME,则arg为设置的超时时间 |
返回 | 说明 |
OS_EOK | 控制或者修改成功 |
使用示例
静态定时器使用示例
本例利用静态方式分别初始化了一个周期性定时器和一次性定时器,过一段时间后反初始化
#include <oneos_config.h>
#include <os_dbg.h>
#include <os_assert.h>
#include <shell.h>
#include <os_timer.h>
#define TEST_TAG "TEST"
static os_timer_t timer_s1;
static os_timer_t timer_s2;
void timer_s1_timeout(void *parameter)
{
LOG_W(TEST_TAG, "timer_s1 PERIODIC");
}
void timer_s2_timeout(void *parameter)
{
LOG_W(TEST_TAG, "timer_s2 ONE_SHOT");
}
void static_timer_sample(void)
{
os_timer_init(&timer_s1, "timer_s1", timer_s1_timeout, OS_NULL, 100, OS_TIMER_FLAG_PERIODIC | OS_TIMER_FLAG_SOFT_TIMER);
LOG_W(TEST_TAG, "===timer_s1 start===");
os_timer_start(&timer_s1);
os_task_delay(550);
LOG_W(TEST_TAG, "===timer_s1 deinit===");
os_timer_deinit(&timer_s1);
os_timer_init(&timer_s2, "timer_s2", timer_s2_timeout, OS_NULL, 100, OS_TIMER_FLAG_ONE_SHOT | OS_TIMER_FLAG_SOFT_TIMER);
LOG_W(TEST_TAG, "===timer_s2 start===");
os_timer_start(&timer_s2);
os_task_delay(550);
LOG_W(TEST_TAG, "===timer_s2 deinit===");
os_timer_deinit(&timer_s2);
}
SH_CMD_EXPORT(static_timer, static_timer_sample, "test static timer");
运行结果如下:
sh />static_timer
W/TEST: ===timer_s1 start===
W/TEST: timer_s1 PERIODIC
W/TEST: timer_s1 PERIODIC
W/TEST: timer_s1 PERIODIC
W/TEST: timer_s1 PERIODIC
W/TEST: timer_s1 PERIODIC
W/TEST: ===timer_s1 deinit===
W/TEST: ===timer_s2 start===
W/TEST: timer_s2 ONE_SHOT
W/TEST: ===timer_s2 deinit===
动态定时器使用示例
本例用动态方式分别创建了一个周期性定时器和一次性定时器,过一段时间后再销毁定时器
#include <oneos_config.h>
#include <os_dbg.h>
#include <os_assert.h>
#include <shell.h>
#include <os_timer.h>
#define TEST_TAG "TEST"
void timer_d1_timeout(void *parameter)
{
LOG_W(TEST_TAG, "timer_d1 PERIODIC");
}
void timer_d2_timeout(void *parameter)
{
LOG_W(TEST_TAG, "timer_d2 ONE_SHOT");
}
void dynamic_timer_sample(void)
{
static os_timer_t *timer_d1;
static os_timer_t *timer_d2;
timer_d1 = os_timer_create("timer_d1", timer_d1_timeout, OS_NULL, 100, OS_TIMER_FLAG_PERIODIC | OS_TIMER_FLAG_SOFT_TIMER);
if (!timer_d1)
{
LOG_W(TEST_TAG, "===timer_d1 create err===");
return;
}
LOG_W(TEST_TAG, "===timer_d1 start===");
os_timer_start(timer_d1);
os_task_delay(550);
LOG_W(TEST_TAG, "===timer_d1 destroy===");
os_timer_destroy(timer_d1);
timer_d2 = os_timer_create("timer_d2", timer_d2_timeout, OS_NULL, 100, OS_TIMER_FLAG_ONE_SHOT | OS_TIMER_FLAG_SOFT_TIMER);
if (!timer_d2)
{
LOG_W(TEST_TAG, "===timer_d2 create err===");
return;
}
LOG_W(TEST_TAG, "===timer_d2 start===");
os_timer_start(timer_d2);
os_task_delay(550);
LOG_W(TEST_TAG, "===timer_d2 destroy===");
os_timer_destroy(timer_d2);
}
SH_CMD_EXPORT(dynamic_timer, dynamic_timer_sample, "test dynamic timer");
运行结果如下:
sh />dynamic_timer
W/TEST: ===timer_d1 start===
W/TEST: timer_d1 PERIODIC
W/TEST: timer_d1 PERIODIC
W/TEST: timer_d1 PERIODIC
W/TEST: timer_d1 PERIODIC
W/TEST: timer_d1 PERIODIC
W/TEST: ===timer_d1 destroy===
W/TEST: ===timer_d2 start===
W/TEST: timer_d2 ONE_SHOT
W/TEST: ===timer_d2 destroy===
定时器控制命令使用示例
本例创建定时器后,通过OS_TIMER_CTRL_GET_TIME获取定时器的超时时间,通过OS_TIMER_CTRL_SET_TIME改变超时时间,通过OS_TIMER_CTRL_SET_ONESHOT/OS_TIMER_CTRL_SET_PERIODIC来设置定时器单次执行或周期执行
#include <oneos_config.h>
#include <os_dbg.h>
#include <os_assert.h>
#include <shell.h>
#include <os_timer.h>
#define TEST_TAG "TEST"
void timer_ctrl_timeout(void *parameter)
{
LOG_W(TEST_TAG, "timer_ctrl_timeout");
}
void control_timer_sample(void)
{
os_tick_t init_tick;
static os_timer_t *timer_ctrl;
timer_ctrl = os_timer_create("timer_ctrl", timer_ctrl_timeout, OS_NULL, 100, OS_TIMER_FLAG_PERIODIC | OS_TIMER_FLAG_SOFT_TIMER);
OS_ASSERT(OS_NULL != timer_ctrl);
LOG_W(TEST_TAG, "===timer start===");
os_timer_start(timer_ctrl);
os_task_delay(550);
LOG_W(TEST_TAG, "===timer stop===");
os_timer_stop(timer_ctrl);
os_timer_control(timer_ctrl, OS_TIMER_CTRL_GET_TIME, &init_tick);
LOG_W(TEST_TAG, "get timeout :%d", init_tick);
init_tick += 100;
LOG_W(TEST_TAG, "set timeout :%d", init_tick);
os_timer_control(timer_ctrl, OS_TIMER_CTRL_SET_TIME, &init_tick);
LOG_W(TEST_TAG, "===timer start===");
os_timer_start(timer_ctrl);
os_task_delay(550);
LOG_W(TEST_TAG, "set oneshot ");
os_timer_control(timer_ctrl, OS_TIMER_CTRL_SET_ONESHOT, OS_NULL);
os_task_delay(550);
LOG_W(TEST_TAG, "set periodic ");
os_timer_control(timer_ctrl, OS_TIMER_CTRL_SET_PERIODIC, OS_NULL);
LOG_W(TEST_TAG, "===timer start===");
os_timer_start(timer_ctrl);
os_task_delay(550);
LOG_W(TEST_TAG, "===timer destroy===");
os_timer_destroy(timer_ctrl);
}
SH_CMD_EXPORT(control_timer, control_timer_sample, "test control timer");
执行结果如下:
sh />control_timer
W/TEST: ===timer start===
W/TEST: timer_ctrl_timeout
W/TEST: timer_ctrl_timeout
W/TEST: timer_ctrl_timeout
W/TEST: timer_ctrl_timeout
W/TEST: timer_ctrl_timeout
W/TEST: ===timer stop===
W/TEST: get timeout :100
W/TEST: set timeout :200
W/TEST: ===timer start===
W/TEST: timer_ctrl_timeout
W/TEST: timer_ctrl_timeout
W/TEST: set oneshot
W/TEST: timer_ctrl_timeout
W/TEST: set periodic
W/TEST: ===timer start===
W/TEST: timer_ctrl_timeout
W/TEST: timer_ctrl_timeout
W/TEST: ===timer destroy===