HCoreBase/src/HTimer.c
2025-10-27 23:50:20 +08:00

236 lines
5.8 KiB
C

#include "HTimer.h"
#include "HDLog.h"
#include <string.h>
// 用于拷贝定时器文件使用可直接删除HDLog.h文件避免依赖
#ifndef LogD
#define LogD(...)
#endif
static uint32_t (*GetCurrentMs)(void);
#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)) TimeRegisterInfo {
uint16_t enable : 1; ///< 定时器使能
uint16_t curr : 1; ///< 当前定时器
uint16_t len : 14; ///< 定时器个数
HTimerInfo *timers; ///< 定时器
};
static struct TimeRegisterInfo sTimeRegisters[HTIMER_REGISTER_MAX];
static void CallTimer(uint8_t id, int16_t index) {
if (id >= HTIMER_REGISTER_MAX) {
LogD("error id[%d]", id);
return ;
}
if (index < 0 || index >= sTimeRegisters[id].len) {
LogD("error index[%d], len[%d]", index, sTimeRegisters[id].len);
return ;
}
sTimeRegisters[id].curr = 1;
sTimeRegisters[id].timers[index].curr = 1;
if (sTimeRegisters[id].timers[index].flags == kHTimerOnce) {
sTimeRegisters[id].timers[index].enable = 0;
}
sTimeRegisters[id].timers[index].call();
sTimeRegisters[id].curr = 0;
sTimeRegisters[id].timers[index].curr = 0;
sTimeRegisters[id].timers[index].lastTime = GetCurrentMs();
}
static int16_t AddTimerData(uint8_t id, uint32_t duration, HTimerCallType call, eHTimerFlags flags) {
if (!GetCurrentMs) {
LogD("GetCurrentMs not init");
return HTIMER_INVALID;
}
if (id >= HTIMER_REGISTER_MAX) {
LogD("error id[%d]", id);
return HTIMER_INVALID;
}
if (sTimeRegisters[id].enable == 0) {
LogD("not enable, id[%d]", id);
return HTIMER_INVALID;
}
if ((duration & ~CHECK_VALUE) != 0) {
LogD("duration overflow, duration[%d]", duration);
return HTIMER_INVALID;
}
for (uint16_t i = 0; i < sTimeRegisters[id].len; ++i) {
if (sTimeRegisters[id].timers[i].enable) {
continue;
}
// 防中断导致数据重叠
sTimeRegisters[id].timers[i].enable = 1;
if (sTimeRegisters[id].timers[i].enable != 1) {
continue;
}
sTimeRegisters[id].timers[i].enable = 2;
sTimeRegisters[id].timers[i].duration = duration;
sTimeRegisters[id].timers[i].lastTime = GetCurrentMs();
sTimeRegisters[id].timers[i].call = call;
sTimeRegisters[id].timers[i].flags = flags;
return CREATE_INDEX(id, i);
}
LogD("timers full, id[%d], duration[%d], flags[%d]", id, duration, flags);
return HTIMER_INVALID;
}
void HTimerInitMs(uint32_t (*func)(void)) {
GetCurrentMs = func;
}
uint32_t HTimerGetMs() {
if (!GetCurrentMs) {
return 0;
}
return GetCurrentMs();
}
uint8_t HTimerRegisterTimerInfo(uint8_t id, HTimerInfo *info, uint16_t infoLen) {
if (id >= HTIMER_REGISTER_MAX) {
LogD("error id[%d], max[%d]", id, HTIMER_REGISTER_MAX);
return 0;
}
if (sTimeRegisters[id].enable == 1) {
LogD("id[%d] already register", id);
return 0;
}
sTimeRegisters[id].timers = info;
sTimeRegisters[id].len = infoLen;
sTimeRegisters[id].enable = 1;
return 1;
}
void HTimerRemoveRegister(uint8_t id) {
if (id >= HTIMER_REGISTER_MAX) {
return ;
}
sTimeRegisters[id].enable = 0;
sTimeRegisters[id].len = 0;
sTimeRegisters[id].timers = 0;
}
void HTimerRun(uint8_t id) {
if (!GetCurrentMs) {
return ;
}
if (id >= HTIMER_REGISTER_MAX) {
return ;
}
if (sTimeRegisters[id].enable == 0) {
return ;
}
if (sTimeRegisters[id].curr == 1) {
return ;
}
// 没必要每次都扫描, 当时间更新时再检查
static uint32_t lastMs[HTIMER_REGISTER_MAX];
if (lastMs[id] == GetCurrentMs()) {
return ;
}
lastMs[id] = GetCurrentMs();
for (uint16_t i = 0; i < sTimeRegisters[id].len; ++i) {
if (sTimeRegisters[id].timers[i].enable == 0) {
continue;
}
// 这里每次都获取最新时间是因为执行任务期间可能会导致时间变化
uint32_t diff = GetCurrentMs() - sTimeRegisters[id].timers[i].lastTime;
uint32_t timeDuration = sTimeRegisters[id].timers[i].duration;
if (diff < timeDuration) {
continue;
}
CallTimer(id, i);
}
}
HTimer_t HTimerAdd(uint8_t id, uint32_t ms, HTimerCallType call, eHTimerFlags flags) {
#ifdef HTIMER_CHECK_INVALID_LOOP
HTimer_t result = AddTimerData(id, ms, call, flags);
if (result == HTIMER_INVALID) {
while (1);
}
return result;
#else
return AddTimerData(id, ms, call, flags);
#endif
}
void HTimerRemove(HTimer_t index) {
if (index == HTIMER_INVALID) {
return ;
}
const uint8_t id = GET_ID(index);
index = GET_INDEX(index);
if (id >= HTIMER_REGISTER_MAX) {
LogD("error id[%d]", id);
return ;
}
if (index < 0 || index >= sTimeRegisters[id].len) {
LogD("error index[%d]", index);
return ;
}
sTimeRegisters[id].timers[index].enable = 0;
}
uint8_t HTimerGetCurrentId() {
for (uint8_t i = 0; i < HTIMER_REGISTER_MAX; ++i) {
if (sTimeRegisters[i].curr == 1) {
return i;
}
}
return HTIMER_INVALID;
}
HTimer_t HTimerGetCurrentCaller(uint8_t id) {
if (id >= HTIMER_REGISTER_MAX) {
return HTIMER_INVALID;
}
if (sTimeRegisters[id].curr == 0) {
return HTIMER_INVALID;
}
for (uint16_t i = 0; i < sTimeRegisters[id].len; ++i) {
if (sTimeRegisters[id].timers[i].curr == 1) {
return CREATE_INDEX(id, i);
}
}
return HTIMER_INVALID;
}