1. 修改定时器支持中断版本
This commit is contained in:
parent
6a368bd720
commit
74e9b455fc
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
// 无效值
|
// 无效值
|
||||||
#ifndef HTIMER_INVALID
|
#ifndef HTIMER_INVALID
|
||||||
#define HTIMER_INVALID (NULL)
|
#define HTIMER_INVALID (-1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 检查添加定时任务超出限制后进入死循环, 方便调试
|
// 检查添加定时任务超出限制后进入死循环, 方便调试
|
||||||
@ -34,12 +34,14 @@ typedef enum
|
|||||||
} eHTimerFlags;
|
} eHTimerFlags;
|
||||||
|
|
||||||
typedef void (*HTimerCallType)();
|
typedef void (*HTimerCallType)();
|
||||||
typedef void * HTimer_t;
|
typedef int16_t HTimer_t;
|
||||||
|
|
||||||
///< 注册的定时器信息, 定义为数组, 数量由外部控制
|
///< 注册的定时器信息, 定义为数组, 数量由外部控制
|
||||||
typedef struct HTimerInfo {
|
typedef struct HTimerInfo {
|
||||||
uint32_t flags : 1; ///< 定时器标志, eTimerFlags
|
uint32_t flags : 1; ///< 定时器标志, eTimerFlags
|
||||||
uint32_t duration : 31; ///< 定时触发时长, 毫秒为计数单元
|
uint32_t enable : 2; ///< 定时器使能
|
||||||
|
uint32_t curr : 1; ///< 当前回调者
|
||||||
|
uint32_t duration : 28; ///< 定时触发时长, 毫秒为计数单元
|
||||||
uint32_t lastTime; ///< 上次触发时间
|
uint32_t lastTime; ///< 上次触发时间
|
||||||
HTimerCallType call; ///< 定时触发函数
|
HTimerCallType call; ///< 定时触发函数
|
||||||
#if HTIMER_USE_USERDATA
|
#if HTIMER_USE_USERDATA
|
||||||
@ -51,10 +53,9 @@ typedef struct HTimerInfo {
|
|||||||
|
|
||||||
typedef struct TimeRegisterInfo {
|
typedef struct TimeRegisterInfo {
|
||||||
HList workNode; ///< 工作节点
|
HList workNode; ///< 工作节点
|
||||||
HList idleNode; ///< 空闲节点
|
HTimerInfo *timers; ///< 定时器信息
|
||||||
#if HTIMER_USE_USERDATA
|
uint8_t schedu : 1; ///< 需要重新调度工作队列
|
||||||
HList *currNode; ///< 当前节点
|
uint8_t len : 7; ///< 定时器个数
|
||||||
#endif
|
|
||||||
} TimeRegisterInfo;
|
} TimeRegisterInfo;
|
||||||
|
|
||||||
///< 初始化毫秒定时器, 需要传递获取毫秒的函数
|
///< 初始化毫秒定时器, 需要传递获取毫秒的函数
|
||||||
|
|||||||
161
src/HTimer.c
161
src/HTimer.c
@ -11,7 +11,10 @@
|
|||||||
|
|
||||||
static uint32_t (*GetCurrentMs)(void);
|
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 {
|
struct __attribute__((packed)) TimerInfo {
|
||||||
@ -22,11 +25,6 @@ struct __attribute__((packed)) TimerInfo {
|
|||||||
static struct TimerInfo sInfo;
|
static struct TimerInfo sInfo;
|
||||||
|
|
||||||
static void InsertWorkNode(uint8_t id, HList *node) {
|
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);
|
HTimerInfo *info = HLIST_ENTRY(node, HTimerInfo, node);
|
||||||
const uint32_t triggerTime = info->lastTime + info->duration;
|
const uint32_t triggerTime = info->lastTime + info->duration;
|
||||||
HList *entry = NULL;
|
HList *entry = NULL;
|
||||||
@ -50,31 +48,30 @@ static void CallTimer(uint8_t id, HList *node) {
|
|||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HTIMER_USE_USERDATA
|
|
||||||
sInfo.info[id].currNode = node;
|
|
||||||
#endif
|
|
||||||
HTimerInfo *info = HLIST_ENTRY(node, HTimerInfo, node);
|
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) {
|
if (info->call) {
|
||||||
info->call();
|
info->call();
|
||||||
}
|
}
|
||||||
#if HTIMER_USE_USERDATA
|
|
||||||
sInfo.info[id].currNode = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
info->curr = 0;
|
||||||
info->lastTime = GetCurrentMs();
|
info->lastTime = GetCurrentMs();
|
||||||
if (!HListIsSelf(node)) {
|
if (info->enable) {
|
||||||
return;
|
// 定时器还活跃, 需要重新调度回工作队列
|
||||||
}
|
sInfo.info[id].schedu = 1;
|
||||||
|
|
||||||
// 如果是单次的, 直接移动到空闲队列, 循环的, 按触发时间重新插入工作队列
|
|
||||||
if (info->flags == kHTimerOnce) {
|
|
||||||
HListAddTail(node, &sInfo.info[id].idleNode);
|
|
||||||
} else {
|
|
||||||
InsertWorkNode(id, node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if (!GetCurrentMs) {
|
||||||
LogD("GetCurrentMs not init");
|
LogD("GetCurrentMs not init");
|
||||||
return HTIMER_INVALID;
|
return HTIMER_INVALID;
|
||||||
@ -90,23 +87,31 @@ static HList * AddTimerData(uint8_t id, uint32_t duration, HTimerCallType call,
|
|||||||
return HTIMER_INVALID;
|
return HTIMER_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
HList *node = HListPop(&sInfo.info[id].idleNode);
|
sInfo.info[id].schedu = 1;
|
||||||
if (node == NULL) {
|
for (uint16_t i = 0; i < sInfo.info[id].len; ++i) {
|
||||||
LogD("timers full, id[%d], duration[%d], flags[%d]", id, duration, flags);
|
if (sInfo.info[id].timers[i].enable) {
|
||||||
return HTIMER_INVALID;
|
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);
|
LogD("timers full, id[%d], duration[%d], flags[%d]", id, duration, flags);
|
||||||
info->duration = duration;
|
return HTIMER_INVALID;
|
||||||
info->lastTime = GetCurrentMs();
|
|
||||||
info->call = call;
|
|
||||||
info->flags = flags;
|
|
||||||
#if HTIMER_USE_USERDATA
|
|
||||||
info->userData = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
InsertWorkNode(id, node);
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTimerInitMs(uint32_t (*func)(void)) {
|
void HTimerInitMs(uint32_t (*func)(void)) {
|
||||||
@ -123,11 +128,11 @@ uint32_t HTimerGetMs() {
|
|||||||
|
|
||||||
void HTimerInitRegister(TimeRegisterInfo *info, uint8_t len)
|
void HTimerInitRegister(TimeRegisterInfo *info, uint8_t len)
|
||||||
{
|
{
|
||||||
|
memset(info, 0, sizeof(*info) * len);
|
||||||
sInfo.info = info;
|
sInfo.info = info;
|
||||||
sInfo.infoLen = len;
|
sInfo.infoLen = len;
|
||||||
for (uint8_t i = 0; i < len; ++i) {
|
for (uint8_t i = 0; i < len; ++i) {
|
||||||
HListInit(&info[i].workNode);
|
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);
|
memset(info, 0, sizeof(*info) * infoLen);
|
||||||
|
sInfo.info[id].timers = info;
|
||||||
|
sInfo.info[id].len = infoLen;
|
||||||
for (uint16_t i = 0; i < infoLen; ++i) {
|
for (uint16_t i = 0; i < infoLen; ++i) {
|
||||||
info[i].id = id;
|
info[i].id = id;
|
||||||
HListInit(&info[i].node);
|
HListInit(&info[i].node);
|
||||||
HListAddTail(&info[i].node, &sInfo.info[id].idleNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -156,6 +162,23 @@ void HTimerRun(uint8_t id) {
|
|||||||
return ;
|
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)) {
|
if (HListEmpty(&sInfo.info[id].workNode)) {
|
||||||
return ;
|
return ;
|
||||||
@ -199,9 +222,20 @@ void HTimerRemove(HTimer_t index) {
|
|||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
HTimerInfo *info = HLIST_ENTRY(index, HTimerInfo, node);
|
const uint8_t id = GET_ID(index);
|
||||||
HListDel(&info->node);
|
index = GET_INDEX(index);
|
||||||
HListAddTail(&info->node, &sInfo.info[info->id].idleNode);
|
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
|
#if HTIMER_USE_USERDATA
|
||||||
@ -211,18 +245,40 @@ void HTimerSetUserData(HTimer_t index, long data)
|
|||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
HTimerInfo *info = HLIST_ENTRY(index, HTimerInfo, node);
|
const uint8_t id = GET_ID(index);
|
||||||
info->userData = data;
|
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)
|
long HTimerGetUserData(HTimer_t index)
|
||||||
{
|
{
|
||||||
if (index == HTIMER_INVALID) {
|
if (index == HTIMER_INVALID) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
HTimerInfo *info = HLIST_ENTRY(index, HTimerInfo, node);
|
const uint8_t id = GET_ID(index);
|
||||||
return info->userData;
|
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)
|
long HTimerGetCurrCallUserData(uint8_t id)
|
||||||
@ -231,12 +287,15 @@ long HTimerGetCurrCallUserData(uint8_t id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sInfo.info[id].currNode == NULL) {
|
for (uint16_t i = 0; i < sInfo.info[id].len; ++i) {
|
||||||
return 0;
|
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 0;
|
||||||
return info->userData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // HTIMER_USE_USERDATA
|
#endif // HTIMER_USE_USERDATA
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user