diff --git a/include/HTimer.h b/include/HTimer.h index 41fede3..9a7240a 100644 --- a/include/HTimer.h +++ b/include/HTimer.h @@ -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; ///< 初始化毫秒定时器, 需要传递获取毫秒的函数 diff --git a/src/HTimer.c b/src/HTimer.c index ba29320..be6bf25 100644 --- a/src/HTimer.c +++ b/src/HTimer.c @@ -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