xt-sdk 文档 v1.0.3
xt-sdk 嵌入式 SDK API 参考
载入中...
搜索中...
未找到
xt_timer2 - 软件定时器

版本:0.2 | 日期:2026-06-13 | 路径: components/xt_task/xt_timer2.h


一、概述

xt_timer2 是 xt-sdk 的新版软件定时器模块,采用对象化设计、单链表管理、new/delete 生命周期。参考 cmsis_os2 osTimer 设计,v2.1 相比 v2.0 大幅简化。

特性 v2.0 v2.1
内存管理 静态分配 + 空闲池 new/delete 动态分配,支持编译期切换内存池
链表 空闲链表 + 工作链表 仅工作链表
凭据机制 15-bit key 自增校验 无(用户全程管理生命周期)
回收 到期自动回收 到期摘下,用户自行管理
API 数量 18 个 17 个

1.1 设计原则

  • 单实例 :全局只有一个 handler,一条工作链表
  • 一次性定时器 :不支持周期模式,如需重复触发请在回调中 start
  • 用户管理内存 : new 动态分配, delete 释放;静态对象用 {0} + setup
  • 临界区保护 :所有链表操作在 XT_TIMER2_CRIT_ENTRY/EXIT 内完成

1.2 依赖

依赖 用途
xt_list.h 双向循环链表:工作链表 + 快照链表
XT_CRIT_ENTRY/EXIT 临界区宏(通过 XT_TIMER2_CRIT_* 可覆盖)
xt_tick_get() 硬件 tick 源(非自定义模式)
xt_error.h XT_EOK 、 XT_EINVAL 等错误码

二、核心概念

2.1 定时器对象

struct xt_timer2 {
struct xt_list_node node; // NULL=未初始化, 自指向=游离, 其他=在链上
volatile xt_timer2_cb_t cb_func; // 超时回调
void *user_data; // 回调透传数据
xt_tick2_t tick_timeout; // 绝对超时 tick
#if XT_TIMER2_DEBUG
volatile uint16_t magic; // Magic 校验值 0x159D
#endif
};
void(* xt_timer2_cb_t)(xt_timer2_t *t, void *user_data)
定时器回调函数类型
uint32_t xt_tick2_t
tick 类型,32 位无符号
定时器对象
volatile uint16_t magic
volatile xt_timer2_cb_t cb_func
struct xt_list_node node
void * user_data
xt_tick2_t tick_timeout

node 的三种状态:

  • node.next == NULL — 未初始化(需 setup 或 new 初始化)
  • node.next == &node — 游离(已从链表摘下,如到期后回调前)
  • 其他 — 在工作链表上

2.2 回调类型

typedef void (*xt_timer2_cb_t)(xt_timer2_t *t, void *user_data);
struct xt_timer2 xt_timer2_t
定时器句柄(前向声明)

回调在 临界区外 执行,可自由调用 timer2 API。


三、API 参考

以下为函数签名大纲,完整的参数说明、返回值、注意事项请查看 xt_timer2(硬件定时器) 。

3.1 生命周期

函数签名 说明
xt_timer2_t *xt_timer2_new(xt_timer2_cb_t timer_cb, void *user_data) 动态分配并初始化定时器(可直接 start)
xt_err_t xt_timer2_delete(xt_timer2_t *t) 删除定时器并释放内存(自动摘链)
xt_err_t xt_timer2_setup(xt_timer2_t *t, xt_timer2_cb_t timer_cb, void *user_data) 配置静态定时器的回调和用户数据(不启动)

3.2 运行控制

函数签名 说明
xt_err_t xt_timer2_start(xt_timer2_t *t, xt_tick2_t tick_timeout) 启动/重启定时器(先摘后挂,等价 restart)
xt_err_t xt_timer2_stop(xt_timer2_t *t) 停止定时器(摘下链表,幂等)
bool xt_timer2_is_running(xt_timer2_t *t) 查询是否在工作链表上(遍历确认)

3.3 属性修改

函数签名 说明
xt_err_t xt_timer2_set_cb(xt_timer2_t *t, xt_timer2_cb_t cb) 设置回调函数
xt_err_t xt_timer2_set_user_data(xt_timer2_t *t, void *user_data) 设置用户数据

3.4 主循环

函数签名 说明
xt_tick2_t xt_timer2_handler(void) 三阶段处理,返回下次需等待的最小 tick 数
xt_tick2_t xt_timer2_remain(xt_tick2_t timeout_tick) 计算剩余 tick(有符号差值,回绕安全)

3.5 系统管理

函数签名 说明
void xt_timer2_sys_setup(xt_timer2_t *pool_buf, size_t pool_count) 初始化内存池(new 之前调用)
void xt_timer2_sys_reset(void) 重置运行时状态(仅测试/调试用)
void xt_timer2_enable_custom_tick(bool enable) 启停自定义 tick 模式

3.6 Tick 控制

函数签名 说明
void xt_tick2_inc(xt_tick2_t inc) 推进自定义 tick
void xt_tick2_set(xt_tick2_t val) 设置自定义 tick 值
xt_tick2_t xt_tick2_get(void) 获取当前 tick(ISR 安全)

四、Handler 三阶段详解

4.1 阶段1:快照到期定时器

临界区内遍历 s_working_head:
├─ MAGIC 异常 → assert + xt_list_remove → continue
├─ remain() > 0 → continue(未到期)
└─ 到期 → xt_list_remove + 挂入 fire_snap

4.2 阶段2:执行回调

while (fire_snap 不为空):
t = fire_snap.next 取出
xt_list_remove(&t->node) → 自指向(游离)
cb = t->cb_func; user_data = t->user_data → 快照
cb(t, user_data) → 回调
无后续处理

4.3 阶段3:计算剩余时间

临界区内遍历 s_working_head:
remain = xt_timer2_remain(t->tick_timeout)
next_timeout = min(next_timeout, remain)

返回值: UINT32_MAX = 空闲; 0 = 刚处理完到期定时器(应重调 handler);其他 = 需等待的 tick 数。

4.4 关键场景

回调中 delete(self)

void cb_delete_self(xt_timer2_t *t, void *ud) {
xt_timer2_delete(t); // 安全:t 已从 fire_snap 摘下,fire_snap 遍历不受影响
}
xt_err_t xt_timer2_delete(xt_timer2_t *t)
删除定时器并释放内存

回调中 start(self) —— 单次变多次

void cb_restart(xt_timer2_t *t, void *ud) {
xt_timer2_start(t, 100); // start 先摘后挂,若自指向则跳过 remove
}
xt_err_t xt_timer2_start(xt_timer2_t *t, xt_tick2_t tick_timeout)
启动/重启定时器,挂入工作链表

阶段1 已把 t 摘入 fire_snap → 阶段2 回调中 start → 去掉自指向,挂回 s_working_head → 阶段3 重新计算 → 下次到期再次触发。

回调中 start(other) —— 跨定时器重调度

void cb_start_other(xt_timer2_t *t, void *ud) {
xt_timer2_start(s_other, 300); // s_other 在 s_working_head 上,先摘后挂
}

同时到期多个

阶段1 遍历工作链表收集所有到期定时器到 fire_snap → 阶段2 逐个执行回调 → 全部处理完毕 → 阶段3 工作链表为空返回 UINT32_MAX 。

timeout=0 立即触发

xt_timer2_start(&t, 0); // tick_timeout = now + 0
xt_timer2_handler(); // remain(now) <= 0 → 阶段1 收集 → 阶段2 触发
xt_tick2_t xt_timer2_handler(void)
定时器主循环处理函数,需在主循环中周期性调用

五、内存分配

5.1 编译期切换

默认使用 xt_calloc / xt_free 。定义 XT_TIMER2_USE_POOL 后切换为内部内存池:

// 编译前定义此宏即可启用内存池
#define XT_TIMER2_USE_POOL

内部实现:

#if defined(XT_TIMER2_USE_POOL)
# define XT_TIMER2_MALLOC(count, size) pool_alloc(count, size)
# define XT_TIMER2_FREE(ptr) pool_free(ptr)
#else
# define XT_TIMER2_MALLOC(count, size) xt_calloc(count, size)
# define XT_TIMER2_FREE(ptr) xt_free(ptr)
#endif

5.2 使用内存池

编译前定义 XT_TIMER2_USE_POOL ,然后调用 xt_timer2_sys_setup(pool_array, pool_size) 注册池:

xt_timer2_t pool[10];
xt_timer2_sys_setup(pool, 10); // 注册池
void xt_timer2_sys_setup(xt_timer2_t *pool_buf, size_t pool_count)
初始化定时器子系统内存池

六、临界区

xt_timer2.c 定义了独立的临界区宏:

#if !defined(XT_TIMER2_CRIT_STAT)
# define XT_TIMER2_CRIT_STAT() XT_CRIT_STAT()
#endif
#if !defined(XT_TIMER2_CRIT_ENTRY)
# define XT_TIMER2_CRIT_ENTRY() XT_CRIT_ENTRY()
#endif
#if !defined(XT_TIMER2_CRIT_EXIT)
# define XT_TIMER2_CRIT_EXIT() XT_CRIT_EXIT()
#endif

无 OS 环境可编译前重定义为空宏。


七、反模式

反模式 问题 正确做法
对静态对象调 delete 释放栈/全局内存 静态对象永远不 delete
对已 delete 的指针调 API use-after-free delete 后置 NULL
setup 运行中的定时器 竞态 先 stop 再 setup
tick_timeout > XT_TIMER2_TIMEOUT_MAX 回绕不安全 返回 XT_EINVAL

八、常见模式

7.1 静态定时器

xt_timer2_t t = {0};
xt_timer2_setup(&t, my_callback, my_data);
xt_timer2_start(&t, 1000);
xt_err_t xt_timer2_setup(xt_timer2_t *t, xt_timer2_cb_t timer_cb, void *user_data)
配置定时器回调函数和用户数据(不启动)

7.2 动态定时器

xt_timer2_t *t = xt_timer2_new(my_callback, my_data);
if (t != NULL) {
xt_timer2_start(t, 1000);
}
// ... 到期后 ...
xt_timer2_t * xt_timer2_new(xt_timer2_cb_t timer_cb, void *user_data)
动态分配并初始化一个定时器

7.3 回调中重调度(单次变多次)

void my_cb(xt_timer2_t *t, void *ud) {
do_work();
xt_timer2_start(t, 500); // 500 tick 后再触发
}

8.4 回调中停止另一个定时器

void cb_t1(xt_timer2_t *t, void *ud) {
xt_timer2_stop(g_t2); // 撤销 t2
}
xt_err_t xt_timer2_stop(xt_timer2_t *t)
停止定时器,从工作链表摘下

九、v2.0 → v2.1 迁移

v2.0 API v2.1 替代
xt_timer2_put/get xt_timer2_new/delete
xt_timer2_close/close_not_safe xt_timer2_stop + xt_timer2_delete
xt_timer2_restart xt_timer2_start(先摘后挂)
xt_timer2_run xt_timer2_setup + xt_timer2_start
xt_timer2_detach 不需要(回调后自动游离)
xt_timer2_get_key 不需要(无 key)
xt_timer2_reset xt_timer2_sys_reset

十、测试

测试套件位于 tests/xt_timer2/ :

cd tests/xt_timer2
xt --target windows/simulator fullclean build
xt --target windows/simulator run