1. 修改定时器支持中断版本
This commit is contained in:
parent
6a368bd720
commit
74e9b455fc
@ -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;
|
||||
|
||||
///< 初始化毫秒定时器, 需要传递获取毫秒的函数
|
||||
|
||||
161
src/HTimer.c
161
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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user