1. 修改定时器支持中断版本

This commit is contained in:
coffee 2026-04-04 17:51:09 +08:00
parent 6a368bd720
commit 74e9b455fc
2 changed files with 118 additions and 58 deletions

View File

@ -14,7 +14,7 @@
// 无效值
#ifndef HTIMER_INVALID
#define HTIMER_INVALID (NULL)
#define HTIMER_INVALID (-1)
#endif
// 检查添加定时任务超出限制后进入死循环, 方便调试
@ -34,12 +34,14 @@ typedef enum
} eHTimerFlags;
typedef void (*HTimerCallType)();
typedef void * HTimer_t;
typedef int16_t HTimer_t;
///< 注册的定时器信息, 定义为数组, 数量由外部控制
typedef struct HTimerInfo {
uint32_t flags : 1; ///< 定时器标志, eTimerFlags
uint32_t duration : 31; ///< 定时触发时长, 毫秒为计数单元
uint32_t enable : 2; ///< 定时器使能
uint32_t curr : 1; ///< 当前回调者
uint32_t duration : 28; ///< 定时触发时长, 毫秒为计数单元
uint32_t lastTime; ///< 上次触发时间
HTimerCallType call; ///< 定时触发函数
#if HTIMER_USE_USERDATA
@ -51,10 +53,9 @@ typedef struct HTimerInfo {
typedef struct TimeRegisterInfo {
HList workNode; ///< 工作节点
HList idleNode; ///< 空闲节点
#if HTIMER_USE_USERDATA
HList *currNode; ///< 当前节点
#endif
HTimerInfo *timers; ///< 定时器信息
uint8_t schedu : 1; ///< 需要重新调度工作队列
uint8_t len : 7; ///< 定时器个数
} TimeRegisterInfo;
///< 初始化毫秒定时器, 需要传递获取毫秒的函数

View File

@ -11,7 +11,10 @@
static uint32_t (*GetCurrentMs)(void);
#define CHECK_VALUE (0x7FFFFFFF)
#define CHECK_VALUE (0x0FFFFFFF)
#define CREATE_INDEX(id, index) ((id << 8) | index)
#define GET_ID(index) ((index >> 8) & 0xFF)
#define GET_INDEX(index) (index & 0xFF)
struct __attribute__((packed)) TimerInfo {
@ -22,11 +25,6 @@ struct __attribute__((packed)) TimerInfo {
static struct TimerInfo sInfo;
static void InsertWorkNode(uint8_t id, HList *node) {
if (id >= sInfo.infoLen) {
LogD("error id[%d]", id);
return ;
}
HTimerInfo *info = HLIST_ENTRY(node, HTimerInfo, node);
const uint32_t triggerTime = info->lastTime + info->duration;
HList *entry = NULL;
@ -50,31 +48,30 @@ static void CallTimer(uint8_t id, HList *node) {
return ;
}
#if HTIMER_USE_USERDATA
sInfo.info[id].currNode = node;
#endif
HTimerInfo *info = HLIST_ENTRY(node, HTimerInfo, node);
// 检查是不是已经删除的定时器
if (info->enable == 0) {
return ;
}
if (info->flags == kHTimerOnce) {
info->enable = 0;
}
info->curr = 1;
if (info->call) {
info->call();
}
#if HTIMER_USE_USERDATA
sInfo.info[id].currNode = NULL;
#endif
info->curr = 0;
info->lastTime = GetCurrentMs();
if (!HListIsSelf(node)) {
return;
}
// 如果是单次的, 直接移动到空闲队列, 循环的, 按触发时间重新插入工作队列
if (info->flags == kHTimerOnce) {
HListAddTail(node, &sInfo.info[id].idleNode);
} else {
InsertWorkNode(id, node);
if (info->enable) {
// 定时器还活跃, 需要重新调度回工作队列
sInfo.info[id].schedu = 1;
}
}
static HList * AddTimerData(uint8_t id, uint32_t duration, HTimerCallType call, eHTimerFlags flags) {
static HTimer_t AddTimerData(uint8_t id, uint32_t duration, HTimerCallType call, eHTimerFlags flags) {
if (!GetCurrentMs) {
LogD("GetCurrentMs not init");
return HTIMER_INVALID;
@ -90,23 +87,31 @@ static HList * AddTimerData(uint8_t id, uint32_t duration, HTimerCallType call,
return HTIMER_INVALID;
}
HList *node = HListPop(&sInfo.info[id].idleNode);
if (node == NULL) {
LogD("timers full, id[%d], duration[%d], flags[%d]", id, duration, flags);
return HTIMER_INVALID;
sInfo.info[id].schedu = 1;
for (uint16_t i = 0; i < sInfo.info[id].len; ++i) {
if (sInfo.info[id].timers[i].enable) {
continue;
}
// 防中断导致数据重叠
sInfo.info[id].timers[i].enable = 1;
if (sInfo.info[id].timers[i].enable != 1) {
continue;
}
sInfo.info[id].timers[i].duration = duration;
sInfo.info[id].timers[i].lastTime = GetCurrentMs();
sInfo.info[id].timers[i].call = call;
sInfo.info[id].timers[i].flags = flags;
#if HTIMER_USE_USERDATA
sInfo.info[id].timers[i].userData = 0;
#endif
sInfo.info[id].timers[i].enable = 2;
return CREATE_INDEX(id, i);
}
HTimerInfo *info = HLIST_ENTRY(node, HTimerInfo, node);
info->duration = duration;
info->lastTime = GetCurrentMs();
info->call = call;
info->flags = flags;
#if HTIMER_USE_USERDATA
info->userData = 0;
#endif
InsertWorkNode(id, node);
return node;
LogD("timers full, id[%d], duration[%d], flags[%d]", id, duration, flags);
return HTIMER_INVALID;
}
void HTimerInitMs(uint32_t (*func)(void)) {
@ -123,11 +128,11 @@ uint32_t HTimerGetMs() {
void HTimerInitRegister(TimeRegisterInfo *info, uint8_t len)
{
memset(info, 0, sizeof(*info) * len);
sInfo.info = info;
sInfo.infoLen = len;
for (uint8_t i = 0; i < len; ++i) {
HListInit(&info[i].workNode);
HListInit(&info[i].idleNode);
}
}
@ -138,10 +143,11 @@ uint8_t HTimerRegisterTimerInfo(uint8_t id, HTimerInfo *info, uint16_t infoLen)
}
memset(info, 0, sizeof(*info) * infoLen);
sInfo.info[id].timers = info;
sInfo.info[id].len = infoLen;
for (uint16_t i = 0; i < infoLen; ++i) {
info[i].id = id;
HListInit(&info[i].node);
HListAddTail(&info[i].node, &sInfo.info[id].idleNode);
}
return 1;
@ -156,6 +162,23 @@ void HTimerRun(uint8_t id) {
return ;
}
do {
if (sInfo.info[id].schedu == 0) {
break;
}
// 清空工作队列, 重新添加
HListInit(&sInfo.info[id].workNode);
for (uint16_t i = 0; i < sInfo.info[id].len; ++i) {
if (sInfo.info[id].timers[i].enable != 2) {
continue;
}
HListInit(&sInfo.info[id].timers[i].node);
InsertWorkNode(id, &sInfo.info[id].timers[i].node);
}
} while (0);
// 检查是否有任务
if (HListEmpty(&sInfo.info[id].workNode)) {
return ;
@ -199,9 +222,20 @@ void HTimerRemove(HTimer_t index) {
return ;
}
HTimerInfo *info = HLIST_ENTRY(index, HTimerInfo, node);
HListDel(&info->node);
HListAddTail(&info->node, &sInfo.info[info->id].idleNode);
const uint8_t id = GET_ID(index);
index = GET_INDEX(index);
if (id >= sInfo.infoLen) {
LogD("error id[%d]", id);
return ;
}
if (index < 0 || index >= sInfo.info[id].len) {
LogD("error index[%d]", index);
return ;
}
sInfo.info[id].timers[index].enable = 0;
sInfo.info[id].schedu = 1;
}
#if HTIMER_USE_USERDATA
@ -211,18 +245,40 @@ void HTimerSetUserData(HTimer_t index, long data)
return ;
}
HTimerInfo *info = HLIST_ENTRY(index, HTimerInfo, node);
info->userData = data;
const uint8_t id = GET_ID(index);
index = GET_INDEX(index);
if (id >= sInfo.infoLen) {
LogD("error id[%d]", id);
return ;
}
if (index < 0 || index >= sInfo.info[id].len) {
LogD("error index[%d]", index);
return ;
}
sInfo.info[id].timers[index].userData = data;
}
long HTimerGetUserData(HTimer_t index)
{
if (index == HTIMER_INVALID) {
if (index == HTIMER_INVALID) {
return 0;
}
HTimerInfo *info = HLIST_ENTRY(index, HTimerInfo, node);
return info->userData;
const uint8_t id = GET_ID(index);
index = GET_INDEX(index);
if (id >= sInfo.infoLen) {
LogD("error id[%d]", id);
return 0;
}
if (index < 0 || index >= sInfo.info[id].len) {
LogD("error index[%d]", index);
return 0;
}
return sInfo.info[id].timers[index].userData;
}
long HTimerGetCurrCallUserData(uint8_t id)
@ -231,12 +287,15 @@ long HTimerGetCurrCallUserData(uint8_t id)
return 0;
}
if (sInfo.info[id].currNode == NULL) {
return 0;
for (uint16_t i = 0; i < sInfo.info[id].len; ++i) {
if (sInfo.info[id].timers[i].curr == 0) {
continue;
}
return sInfo.info[id].timers[i].userData;
}
HTimerInfo *info = HLIST_ENTRY(sInfo.info[id].currNode, HTimerInfo, node);
return info->userData;
return 0;
}
#endif // HTIMER_USE_USERDATA