1. 重改定时器

2. 增加HList
This commit is contained in:
coffee 2026-04-01 15:14:31 +08:00
parent fa9a7df818
commit 9cebbd2bc7
6 changed files with 409 additions and 192 deletions

View File

@ -140,6 +140,14 @@ uint8_t HDProtocolCurrSend(const void *data, int len);
*/
void HDProtocolSendPort(uint8_t dst, const void *data, int len);
/**
* @brief ()
* @param dst
* @param data
* @param len
*/
void HDProtocolDirectSendPort(uint8_t dst, const void *data, int len);
/**
* @brief (, , HDProtocolGetDest )
* @param src

108
include/HList.h Normal file
View File

@ -0,0 +1,108 @@
/**
* : 2026-04-01
* : coffee
* :
* list,
*/
#ifndef _H_LIST_H_
#define _H_LIST_H_
#include <stddef.h>
#include <stdint.h>
typedef struct HList {
struct HList *next;
struct HList *prev;
} HList;
#define HLIST_HEAD_INIT(name) { &(name), &(name) }
#define HLIST_HEAD(name) HList name = HLIST_HEAD_INIT(name)
#define HLIST_CONTAINER_OF(ptr, type, member) \
((type *)((uint8_t *)(ptr) - offsetof(type, member)))
#define HLIST_ENTRY(ptr, type, member) \
HLIST_CONTAINER_OF(ptr, type, member)
#define HLIST_FIRST_ENTRY(head, type, member) \
HLIST_ENTRY((head)->next, type, member)
#define HLIST_LAST_ENTRY(head, type, member) \
HLIST_ENTRY((head)->prev, type, member)
#define HLIST_FOR_EACH(pos, head) \
for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next)
#define HLIST_FOR_EACH_TYPE(pos, head) \
for (HList *(pos) = (head)->next; (pos) != (head); (pos) = (pos)->next)
#define HLIST_FOR_EACH_SAFE(pos, n, head) \
for ((pos) = (head)->next, (n) = (pos)->next; (pos) != (head); \
(pos) = (n), (n) = (pos)->next)
#define HLIST_FOR_EACH_SAFE_TYPE(pos, n, head) \
for (HList *(pos) = (head)->next, (n) = (pos)->next; (pos) != (head); \
(pos) = (n), (n) = (pos)->next)
/**
* @brief
*/
void HListInit(HList *list);
/**
* @brief
*/
uint8_t HListIsSelf(const HList *list);
/**
* @brief
*/
uint8_t HListEmpty(const HList *head);
/**
* @brief
*/
size_t HListLen(const HList *head);
/**
* @brief
*/
void HListAdd(HList *node, HList *head);
/**
* @brief
*/
void HListAddTail(HList *node, HList *head);
/**
* @brief ,
*/
void HListDel(HList *node);
/**
* @brief
*/
void HListReplace(HList *oldNode, HList *newNode);
/**
* @brief
*/
void HListMove(HList *node, HList *head);
/**
* @brief
*/
void HListMoveTail(HList *node, HList *head);
/**
* @brief
* @return , NULL
*/
HList *HListPop(HList *head);
#endif // _H_LIST_H_

View File

@ -10,15 +10,11 @@
#include <stdint.h>
// 定时器注册最大数量
#ifndef HTIMER_REGISTER_MAX
#define HTIMER_REGISTER_MAX (5)
#endif
#include "HList.h"
// 无效值
#ifndef HTIMER_INVALID
#define HTIMER_INVALID -1
#define HTIMER_INVALID (NULL)
#endif
// 检查添加定时任务超出限制后进入死循环, 方便调试
@ -38,21 +34,28 @@ typedef enum
} eHTimerFlags;
typedef void (*HTimerCallType)();
typedef int16_t HTimer_t;
typedef void * HTimer_t;
///< 注册的定时器信息, 定义为数组, 数量由外部控制
typedef struct HTimerInfo {
uint32_t flags : 1; ///< 定时器标志, eTimerFlags
volatile uint32_t enable: 2; ///< 定时器使能
uint32_t curr : 1; ///< 当前回调者
uint32_t duration : 28; ///< 定时触发时长, 毫秒为计数单元
uint32_t duration : 31; ///< 定时触发时长, 毫秒为计数单元
uint32_t lastTime; ///< 上次触发时间
HTimerCallType call; ///< 定时触发函数
#if HTIMER_USE_USERDATA
long userData; ///< 用户数据
#endif
HList node; ///< 定时器节点
uint8_t id; ///< 定时器ID
} HTimerInfo;
typedef struct TimeRegisterInfo {
HList workNode; ///< 工作节点
HList idleNode; ///< 空闲节点
#if HTIMER_USE_USERDATA
HList *currNode; ///< 当前节点
#endif
} TimeRegisterInfo;
///< 初始化毫秒定时器, 需要传递获取毫秒的函数
void HTimerInitMs(uint32_t (*func)(void));
@ -61,7 +64,14 @@ void HTimerInitMs(uint32_t (*func)(void));
uint32_t HTimerGetMs();
/**
* @brief
* @brief ()
* @param info
* @param len
*/
void HTimerInitRegister(TimeRegisterInfo *info, uint8_t len);
/**
* @brief ()
* @param id ID
* @param info ,
* @param infoLen
@ -69,24 +79,15 @@ uint32_t HTimerGetMs();
*/
uint8_t HTimerRegisterTimerInfo(uint8_t id, HTimerInfo *info, uint16_t infoLen);
///< 移除定时器信息
void HTimerRemoveRegister(uint8_t id);
///< 运行定时器可执行任务, 需要在主循环中调用
void HTimerRun(uint8_t id);
///< 添加一个定时任务, 添加失败返回 HTIMER_INVALID, ms不超过24比特
///< 添加一个定时任务, 添加失败返回 HTIMER_INVALID, ms不超过31比特
HTimer_t HTimerAdd(uint8_t id, uint32_t ms, HTimerCallType call, eHTimerFlags flags);
///< 移除一个定时任务
void HTimerRemove(HTimer_t index);
///< 在定时器回调任务中获取当前定时器ID
uint8_t HTimerGetCurrentId();
///< 在定时器回调任务中获取当前定时器调用者索引, 不存在返回 HTIMER_INVALID
HTimer_t HTimerGetCurrentCaller(uint8_t id);
#if HTIMER_USE_USERDATA
///< 设置定时器用户数据
void HTimerSetUserData(HTimer_t index, long data);
@ -94,12 +95,13 @@ void HTimerSetUserData(HTimer_t index, long data);
///< 获取定时器用户数据, 不存在返回 0
long HTimerGetUserData(HTimer_t index);
///< 定时器回调时, 获取对应的定时器用户数据, 不存在返回 0
long HTimerGetCurrCallUserData();
///< 获取当前调用定时器的用户数据
long HTimerGetCurrCallUserData(uint8_t id);
#else
static inline void HTimerSetUserData(HTimer_t index, long data) {}
static inline long HTimerGetUserData(HTimer_t index) { return 0; }
static inline long HTimerGetCurrCallUserData() { return 0; }
static inline long HTimerGetCurrCallUserData(uint8_t id) { return 0; }
#endif
#endif //__H_TIMER_H__

View File

@ -301,6 +301,24 @@ void HDProtocolSendPort(uint8_t dst, const void *data, int len)
sInfo.writeCall(&sInfo.info[dst], (const uint8_t *)data, len);
}
void HDProtocolDirectSendPort(uint8_t dst, const void *data, int len)
{
if (data == NULL || len == 0) {
return;
}
if (sInfo.writeCall == NULL || sInfo.info == NULL) {
return;
}
if (dst >= sInfo.infoLen) {
LogE("index[%d] is out of range[%d]", dst, sInfo.infoLen);
return;
}
sInfo.writeCall(&sInfo.info[dst], (const uint8_t *)data, len);
}
void HDProtocolTmpSend(uint8_t src, uint8_t feedbackRoute, const void *data, int len, uint8_t needReadCount, uint8_t waitCount)
{
if (data == NULL || len == 0) {

128
src/HList.c Normal file
View File

@ -0,0 +1,128 @@
/**
* : 2026-04-01
* : coffee
* :
*/
#include "HList.h"
static void __HListAdd(HList *node, HList *prev, HList *next) {
next->prev = node;
node->next = next;
node->prev = prev;
prev->next = node;
}
static void __HListDel(HList *prev, HList *next) {
next->prev = prev;
prev->next = next;
}
void HListInit(HList *list) {
if (list == NULL) {
return;
}
list->next = list;
list->prev = list;
}
uint8_t HListIsSelf(const HList *list) {
if (list == NULL) {
return 0;
}
return (list->next == list && list->prev == list) ? 1u : 0u;
}
uint8_t HListEmpty(const HList *head) {
if (head == NULL) {
return 1;
}
return (head->next == head) ? 1u : 0u;
}
size_t HListLen(const HList *head) {
size_t len = 0;
const HList *pos;
if (head == NULL) {
return 0;
}
for (pos = head->next; pos != head; pos = pos->next) {
++len;
}
return len;
}
void HListAdd(HList *node, HList *head) {
if (node == NULL || head == NULL) {
return;
}
__HListAdd(node, head, head->next);
}
void HListAddTail(HList *node, HList *head) {
if (node == NULL || head == NULL) {
return;
}
__HListAdd(node, head->prev, head);
}
void HListDel(HList *node) {
if (node == NULL || node->next == NULL || node->prev == NULL) {
return;
}
__HListDel(node->prev, node->next);
HListInit(node);
}
void HListReplace(HList *oldNode, HList *newNode) {
if (oldNode == NULL || newNode == NULL ||
oldNode->next == NULL || oldNode->prev == NULL) {
return;
}
newNode->next = oldNode->next;
newNode->next->prev = newNode;
newNode->prev = oldNode->prev;
newNode->prev->next = newNode;
HListInit(oldNode);
}
void HListMove(HList *node, HList *head) {
if (node == NULL || head == NULL) {
return;
}
HListDel(node);
HListAdd(node, head);
}
void HListMoveTail(HList *node, HList *head) {
if (node == NULL || head == NULL) {
return;
}
HListDel(node);
HListAddTail(node, head);
}
HList *HListPop(HList *head) {
HList *node;
if (HListEmpty(head)) {
return NULL;
}
node = head->next;
HListDel(node);
return node;
}

View File

@ -11,90 +11,102 @@
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)
#define CHECK_VALUE (0x7FFFFFFF)
struct __attribute__((packed)) TimeRegisterInfo {
uint16_t enable : 1; ///< 定时器使能
uint16_t curr : 1; ///< 当前定时器
uint16_t len : 14; ///< 定时器个数
HTimerInfo *timers; ///< 定时器
struct __attribute__((packed)) TimerInfo {
TimeRegisterInfo *info;
uint8_t infoLen;
};
static struct TimeRegisterInfo sTimeRegisters[HTIMER_REGISTER_MAX];
static struct TimerInfo sInfo;
static void CallTimer(uint8_t id, int16_t index) {
if (id >= HTIMER_REGISTER_MAX) {
static void InsertWorkNode(uint8_t id, HList *node) {
if (id >= sInfo.infoLen) {
LogD("error id[%d]", id);
return ;
}
if (index < 0 || index >= sTimeRegisters[id].len) {
LogD("error index[%d], len[%d]", index, sTimeRegisters[id].len);
HTimerInfo *info = HLIST_ENTRY(node, HTimerInfo, node);
const uint32_t triggerTime = info->lastTime + info->duration;
HList *entry = NULL;
HLIST_FOR_EACH(entry, &sInfo.info[id].workNode) {
HTimerInfo *nodeInfo = HLIST_ENTRY(entry, HTimerInfo, node);
if ((nodeInfo->lastTime + nodeInfo->duration) < triggerTime) {
continue;
}
HListAddTail(node, entry);
return;
}
HListAddTail(node, entry);
}
static void CallTimer(uint8_t id, HList *node) {
if (id >= sInfo.infoLen) {
LogD("error id[%d]", id);
return ;
}
sTimeRegisters[id].curr = 1;
sTimeRegisters[id].timers[index].curr = 1;
if (sTimeRegisters[id].timers[index].flags == kHTimerOnce) {
sTimeRegisters[id].timers[index].enable = 0;
#if HTIMER_USE_USERDATA
sInfo.info[id].currNode = node;
#endif
HTimerInfo *info = HLIST_ENTRY(node, HTimerInfo, node);
if (info->call) {
info->call();
}
#if HTIMER_USE_USERDATA
sInfo.info[id].currNode = NULL;
#endif
info->lastTime = GetCurrentMs();
if (!HListIsSelf(node)) {
return;
}
sTimeRegisters[id].timers[index].call();
sTimeRegisters[id].curr = 0;
sTimeRegisters[id].timers[index].curr = 0;
sTimeRegisters[id].timers[index].lastTime = GetCurrentMs();
// 如果是单次的, 直接移动到空闲队列, 循环的, 按触发时间重新插入工作队列
if (info->flags == kHTimerOnce) {
HListAddTail(node, &sInfo.info[id].idleNode);
} else {
InsertWorkNode(id, node);
}
}
static int16_t AddTimerData(uint8_t id, uint32_t duration, HTimerCallType call, eHTimerFlags flags) {
static HList * 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) {
if (id >= sInfo.infoLen) {
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;
#if HTIMER_USE_USERDATA
sTimeRegisters[id].timers[i].userData = 0;
#endif
return CREATE_INDEX(id, i);
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;
}
LogD("timers full, id[%d], duration[%d], flags[%d]", id, duration, flags);
return HTIMER_INVALID;
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;
}
void HTimerInitMs(uint32_t (*func)(void)) {
@ -109,32 +121,30 @@ uint32_t HTimerGetMs() {
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;
void HTimerInitRegister(TimeRegisterInfo *info, uint8_t len)
{
sInfo.info = info;
sInfo.infoLen = len;
for (uint8_t i = 0; i < len; ++i) {
HListInit(&info[i].workNode);
HListInit(&info[i].idleNode);
}
if (sTimeRegisters[id].enable == 1) {
LogD("id[%d] already register", id);
return 0;
}
memset(info, 0, infoLen);
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 ;
uint8_t HTimerRegisterTimerInfo(uint8_t id, HTimerInfo *info, uint16_t infoLen) {
if (id >= sInfo.infoLen) {
LogD("error id[%d], max[%d]", id, sInfo.infoLen);
return 0;
}
sTimeRegisters[id].enable = 0;
sTimeRegisters[id].len = 0;
sTimeRegisters[id].timers = 0;
memset(info, 0, sizeof(*info) * 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;
}
void HTimerRun(uint8_t id) {
@ -142,38 +152,33 @@ void HTimerRun(uint8_t id) {
return ;
}
if (id >= HTIMER_REGISTER_MAX) {
if (id >= sInfo.infoLen) {
return ;
}
if (sTimeRegisters[id].enable == 0) {
// 检查是否有任务
if (HListEmpty(&sInfo.info[id].workNode)) {
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;
HList readyNode;
HListInit(&readyNode);
// 工作队列按触发时间有序, 只需要连续取出队头的就绪任务
while (!HListEmpty(&sInfo.info[id].workNode)) {
HTimerInfo *info = HLIST_FIRST_ENTRY(&sInfo.info[id].workNode, HTimerInfo, node);
uint32_t diff = GetCurrentMs() - info->lastTime;
uint32_t timeDuration = info->duration;
if (diff < timeDuration) {
continue;
break;
}
CallTimer(id, i);
HListMoveTail(&info->node, &readyNode);
}
// 执行就绪队列
while (!HListEmpty(&readyNode)) {
HList *node = HListPop(&readyNode);
CallTimer(id, node);
}
}
@ -194,47 +199,9 @@ void HTimerRemove(HTimer_t index) {
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;
HTimerInfo *info = HLIST_ENTRY(index, HTimerInfo, node);
HListDel(&info->node);
HListAddTail(&info->node, &sInfo.info[info->id].idleNode);
}
#if HTIMER_USE_USERDATA
@ -244,19 +211,8 @@ void HTimerSetUserData(HTimer_t index, long data)
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].userData = data;
HTimerInfo *info = HLIST_ENTRY(index, HTimerInfo, node);
info->userData = data;
}
long HTimerGetUserData(HTimer_t index)
@ -265,25 +221,22 @@ long HTimerGetUserData(HTimer_t index)
return 0;
}
const uint8_t id = GET_ID(index);
index = GET_INDEX(index);
if (id >= HTIMER_REGISTER_MAX) {
LogD("error id[%d]", id);
return 0;
}
if (index < 0 || index >= sTimeRegisters[id].len) {
LogD("error index[%d]", index);
return 0;
}
return sTimeRegisters[id].timers[index].userData;
HTimerInfo *info = HLIST_ENTRY(index, HTimerInfo, node);
return info->userData;
}
long HTimerGetCurrCallUserData()
long HTimerGetCurrCallUserData(uint8_t id)
{
HTimer_t index = HTimerGetCurrentCaller(HTimerGetCurrentId());
return HTimerGetUserData(index);
}
#endif
if (id >= sInfo.infoLen) {
return 0;
}
if (sInfo.info[id].currNode == NULL) {
return 0;
}
HTimerInfo *info = HLIST_ENTRY(sInfo.info[id].currNode, HTimerInfo, node);
return info->userData;
}
#endif // HTIMER_USE_USERDATA