From e76325dd2ea6251a08685c67204f2c33dcddc062 Mon Sep 17 00:00:00 2001 From: coffee Date: Tue, 21 Oct 2025 16:18:53 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E6=96=B0=E5=A2=9E=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/HDRPC.h | 4 +- include/HProtocolBind.h | 92 ++++++++++++++++++ include/HTimer.h | 4 +- src/HDRPC.c | 20 ++-- src/HProtocolBind.c | 200 ++++++++++++++++++++++++++++++++++++++++ src/HTimer.c | 8 +- 6 files changed, 313 insertions(+), 15 deletions(-) create mode 100644 include/HProtocolBind.h create mode 100644 src/HProtocolBind.c diff --git a/include/HDRPC.h b/include/HDRPC.h index 99158e3..0aa26d3 100644 --- a/include/HDRPC.h +++ b/include/HDRPC.h @@ -131,7 +131,7 @@ typedef struct __attribute__((packed)) HDRPCCallBuffer { const char *name; ///< 函数名 HDRPCCallback callback; ///< 回调 #ifdef HDRPC_TIMEOUT - HDRPCTimeoutCall timeout; ///< 超时回调, 就算超时只要没有覆盖还是会调用正常回调 + HDRPCTimeoutCall timeout; ///< 超时回调, 不为空时, 调用后释放 #endif } HDRPCCallBuffer; @@ -290,7 +290,7 @@ void HDRPCReadCallData(void *data, uint16_t len); * @param funcName 函数名称 * @param nameLen 名称长度 * @param timeout 超时回调 - * @return int16_t id索引(返回-1无效) + * @return int16_t id索引(返回-1则无存储返回回调) */ int16_t _HDRPCSendData(HDRPCSession *session, uint16_t funcCode, HDRPCCallback callBack, const char *funcName, uint8_t nameLen, HDRPCTimeoutCall timeout); #define HDRPCSendData(session, code, func) _HDRPCSendData(session, code, func, #func, sizeof(#func) - 1, NULL) diff --git a/include/HProtocolBind.h b/include/HProtocolBind.h new file mode 100644 index 0000000..736b396 --- /dev/null +++ b/include/HProtocolBind.h @@ -0,0 +1,92 @@ +/** + * 日期: 2025-10-18 + * 作者: coffee + * 描述: 协议绑定回调, 用于等待数据回送再执行, 避免阻塞主进程 + */ + +#ifndef _H_PROTOCOL_BIND_H_ +#define _H_PROTOCOL_BIND_H_ + + +#include + +// 需要处理的最大数量 +#ifndef HPROTOCOL_BIND_MAX +#define HPROTOCOL_BIND_MAX (2) +#endif + +// 协议绑定无效值 +#ifndef HPROTOCOL_BIND_INVALID +#define HPROTOCOL_BIND_INVALID (-1) +#endif + +///< 协议绑定索引 +typedef int16_t HProtocolBind_t; + +///< 协议ID +typedef uint8_t HProtocolBindId_t; + +///< 功能码 +typedef uint16_t HProtocolBindFunc_t; + +///< 协议回调 +typedef void (*HProtocolBindCallback)(HProtocolBind_t index, uint8_t* data, uint16_t len); +#define HPROTOCOL_BIND_CALL_ARGS HProtocolBind_t index, uint8_t* data, uint16_t len + +///< 协议会话 +typedef struct HProtocolBindInfo +{ + uint32_t enable : 2; ///< 是否启用 + uint32_t delayMs : 20; ///< 超时时间(ms) + uint32_t isTimeout : 1; ///< 是否超时 + HProtocolBindFunc_t func; ///< 功能码 + uint32_t lastTime; ///< 发送时间 + HProtocolBindCallback callback; ///< 回调, 超时时执行的数据和长度为空 +} HProtocolBindInfo; + +/** + * @brief 注册协议绑定信息 + * @param id 协议ID + * @param info 协议绑定信息 + * @param infoLen 协议绑定信息长度 + */ +uint8_t HProtocolBindRegister(uint8_t id, HProtocolBindInfo *info, uint8_t infoLen); + +/** + * @brief 绑定协议功能码等待回调 + * @param id 协议ID + * @param func 功能码 + * @param callback 回调 + * @param delayMs 超时时间(ms) + * @return HProtocolBind_t -1失败 + */ +HProtocolBind_t HProtocolBindAddTask(HProtocolBindId_t id, HProtocolBindFunc_t func, HProtocolBindCallback callback, uint32_t delayMs); + +/** + * @brief 删除协议绑定 + * @param index 绑定索引 + */ +void HProtocolBindRemoveTask(HProtocolBind_t index); + +/** + * @brief 查询是否超时, 用于超时回调检查 + * @param index 绑定索引 + * @return true超时 false未超时 + */ +uint8_t HProtocolBindIsTimeout(HProtocolBind_t index); + +/** + * @brief 更新协议数据 + * @param id 协议ID + * @param func 功能码 + * @param data 数据 + * @param len 数据长度 + */ +void HProtocolBindUpdateData(HProtocolBindId_t id, HProtocolBindFunc_t func, void* data, uint16_t len); + +/** + * @brief 调度协议绑定 + */ +void HProtocolBindRun(HProtocolBindId_t id); + +#endif // _H_PROTOCOL_BIND_H_ diff --git a/include/HTimer.h b/include/HTimer.h index 73dc1e9..4084cc4 100644 --- a/include/HTimer.h +++ b/include/HTimer.h @@ -58,9 +58,9 @@ uint32_t HTimerGetMs(); * @param id 定时器ID * @param info 定时器信息, 由外部提供定时器数组 * @param infoLen 定时器信息长度 - * @return HTIMER_INVALID 注册失败, 返回定时器ID + * @return 1成功 0失败 */ -HTimer_t HTimerRegisterTimerInfo(uint8_t id, HTimerInfo *info, uint16_t infoLen); +uint8_t HTimerRegisterTimerInfo(uint8_t id, HTimerInfo *info, uint16_t infoLen); ///< 移除定时器信息 void HTimerRemoveRegister(uint8_t id); diff --git a/src/HDRPC.c b/src/HDRPC.c index 3d69f9a..2c005b6 100644 --- a/src/HDRPC.c +++ b/src/HDRPC.c @@ -42,7 +42,7 @@ static void FreeItem(uint8_t index) LogD("useCallLen[%d], timeoutCallLen[%d]", sInfo.useCallLen, sInfo.timeoutCallLen); } -static void UpdateTimeout(HDRPCCallBuffer *callBuff) { +static void UpdateTimeout(uint8_t index, HDRPCCallBuffer *callBuff) { if (callBuff == NULL) { return ; } @@ -58,11 +58,17 @@ static void UpdateTimeout(HDRPCCallBuffer *callBuff) { const uint32_t curr = HDLogGetTime(); if (curr - callBuff->lastTime > callBuff->delayMs) { + if (callBuff->timeout) { + callBuff->timeout(); + } + callBuff->isTimeout = 1; ++sInfo.timeoutCallLen; LogD("Call[%s] Timeout, buffLen[%d]", callBuff->name, sInfo.timeoutCallLen); + + // 如果超时函数有效, 则超时后释放 if (callBuff->timeout) { - callBuff->timeout(); + FreeItem(index); } } #endif @@ -746,7 +752,7 @@ uint16_t HDRPCConvSendData(HDRPCSession *session, uint8_t *data, uint16_t len) void HDRPCSetDelayTime(int16_t idIndex, uint16_t delayMs) { - if (idIndex <= 0 || idIndex >= sInfo.callLen) { + if (idIndex < 0 || idIndex >= sInfo.callLen) { LogD("Invalid idIndex[%d]", idIndex); return; } @@ -756,8 +762,8 @@ void HDRPCSetDelayTime(int16_t idIndex, uint16_t delayMs) HDRPCCallback HDRPCGetCallBack(int16_t idIndex) { - if (idIndex <= 0 || idIndex >= sInfo.callLen) { - LogD("Invalid idIndex[%d]", idIndex); + if (idIndex < 0 || idIndex >= sInfo.callLen) { + LogD("Invalid idIndex[%d], len[%d]", idIndex, sInfo.callLen); return NULL; } @@ -766,7 +772,7 @@ HDRPCCallback HDRPCGetCallBack(int16_t idIndex) void HDRPCRemoveTask(int16_t idIndex) { - if (idIndex <= 0 || idIndex >= sInfo.callLen) { + if (idIndex < 0 || idIndex >= sInfo.callLen) { LogD("Invalid idIndex[%d]", idIndex); return; } @@ -785,6 +791,6 @@ void HDRPCRun() } for (uint16_t i = 0; i < sInfo.callLen; ++i) { - UpdateTimeout(&sInfo.localCallBuffer[i]); + UpdateTimeout(i, &sInfo.localCallBuffer[i]); } } diff --git a/src/HProtocolBind.c b/src/HProtocolBind.c new file mode 100644 index 0000000..11b271b --- /dev/null +++ b/src/HProtocolBind.c @@ -0,0 +1,200 @@ + + +#include "HProtocolBind.h" +#include "HDLog.h" +#include + +#ifndef LogD +#define LogD(...) +#endif + +#define CREATE_INDEX(id, index) ((id << 8) | index) +#define GET_ID(index) ((index >> 8) & 0xFF) +#define GET_INDEX(index) (index & 0xFF) + +struct __attribute__((packed)) BindInfo +{ + uint32_t enable : 1; ///< 绑定使能 + uint32_t curr : 1; ///< 当前绑定 + uint32_t useLen : 8; ///< 使用长度, 减少扫描次数 + uint32_t len : 8; ///< 绑定个数 + HProtocolBindInfo *binds; ///< 绑定 +}; + +static struct BindInfo sBindRegisters[HPROTOCOL_BIND_MAX]; + +static void FreeItem(uint8_t id, HProtocolBind_t index) { + --sBindRegisters[id].useLen; + memset(&sBindRegisters[id].binds[index], 0, sizeof(HProtocolBindInfo)); +} + +uint8_t HProtocolBindRegister(uint8_t id, HProtocolBindInfo *info, uint8_t infoLen) { + if (id >= HPROTOCOL_BIND_MAX) { + LogD("error id[%d], max[%d]", id, HPROTOCOL_BIND_MAX); + return 0; + } + + if (sBindRegisters[id].enable == 1) { + LogD("id[%d] already register", id); + return 0; + } + + sBindRegisters[id].binds = info; + sBindRegisters[id].len = infoLen; + sBindRegisters[id].enable = 1; + return 1; +} + +HProtocolBind_t HProtocolBindAddTask(HProtocolBindId_t id, HProtocolBindFunc_t func, HProtocolBindCallback callback, uint32_t delayMs) { + if (id >= HPROTOCOL_BIND_MAX) { + LogD("error id[%d], max[%d]", id, HPROTOCOL_BIND_MAX); + return HPROTOCOL_BIND_INVALID; + } + + if (sBindRegisters[id].enable == 0) { + LogD("not enable, id[%d]", id); + return HPROTOCOL_BIND_INVALID; + } + + if (callback == NULL) { + LogD("callback is null, id[%d]", id); + return HPROTOCOL_BIND_INVALID; + } + + for (uint16_t i = 0; i < sBindRegisters[id].len; ++i) { + if (sBindRegisters[id].binds[i].enable) { + continue; + } + + // 防中断导致数据重叠 + sBindRegisters[id].binds[i].enable = 1; + if (sBindRegisters[id].binds[i].enable != 1) { + continue; + } + + ++sBindRegisters[id].useLen; + sBindRegisters[id].binds[i].enable = 2; + sBindRegisters[id].binds[i].delayMs = delayMs; + sBindRegisters[id].binds[i].isTimeout = 0; + sBindRegisters[id].binds[i].func = func; + sBindRegisters[id].binds[i].lastTime = HDLogGetTime(); + sBindRegisters[id].binds[i].callback = callback; + + return CREATE_INDEX(id, i); + } + + LogD("bind full, id[%d], len[%d]", id, sBindRegisters[id].len); + return HPROTOCOL_BIND_INVALID; +} + +void HProtocolBindRemoveTask(HProtocolBind_t index) { + const uint8_t id = GET_ID(index); + index = GET_INDEX(index); + if (id >= HPROTOCOL_BIND_MAX) { + LogD("error id[%d], max[%d]", id, HPROTOCOL_BIND_MAX); + return ; + } + + if (index < 0 || index >= sBindRegisters[id].len) { + LogD("error index[%d], len[%d]", index, sBindRegisters[id].len); + return ; + } + + FreeItem(id, index); +} + +uint8_t HProtocolBindIsTimeout(HProtocolBind_t index) { + const uint8_t id = GET_ID(index); + index = GET_INDEX(index); + if (id >= HPROTOCOL_BIND_MAX) { + LogD("error id[%d], max[%d]", id, HPROTOCOL_BIND_MAX); + return 0; + } + + if (index < 0 || index >= sBindRegisters[id].len) { + LogD("error index[%d], len[%d]", index, sBindRegisters[id].len); + return 0; + } + + return sBindRegisters[id].binds[index].isTimeout; +} + +void HProtocolBindUpdateData(HProtocolBindId_t id, HProtocolBindFunc_t func, void* data, uint16_t len) { + if (id >= HPROTOCOL_BIND_MAX) { + LogD("error id[%d], max[%d]", id, HPROTOCOL_BIND_MAX); + return ; + } + + if (sBindRegisters[id].enable == 0) { + LogD("not enable, id[%d]", id); + return ; + } + + // 减少扫描次数 + if (sBindRegisters[id].useLen == 0) { + return ; + } + + for (uint16_t i = 0; i < sBindRegisters[id].len; ++i) { + if (sBindRegisters[id].binds[i].enable == 0) { + continue; + } + + if (sBindRegisters[id].binds[i].func != func) { + continue; + } + + if (sBindRegisters[id].binds[i].isTimeout) { + continue; + } + + // 可能是同一个功能码绑定多个回调 + if (sBindRegisters[id].binds[i].callback) { + sBindRegisters[id].binds[i].callback(CREATE_INDEX(id, i), (uint8_t*)data, len); + } + + // 回调后立即释放 + FreeItem(id, i); + } +} + +void HProtocolBindRun(HProtocolBindId_t id) +{ + if (id >= HPROTOCOL_BIND_MAX) { + LogD("error id[%d], max[%d]", id, HPROTOCOL_BIND_MAX); + return ; + } + + if (sBindRegisters[id].enable == 0) { + LogD("not enable, id[%d]", id); + return ; + } + + // 减少扫描次数 + if (sBindRegisters[id].useLen == 0) { + return ; + } + + for (uint16_t i = 0; i < sBindRegisters[id].len; ++i) { + if (sBindRegisters[id].binds[i].enable == 0) { + continue; + } + + if (sBindRegisters[id].binds[i].isTimeout) { + continue; + } + + if (HDLogGetTime() - sBindRegisters[id].binds[i].lastTime >= sBindRegisters[id].binds[i].delayMs) { + sBindRegisters[id].binds[i].isTimeout = 1; + } + + // 可能是同一个功能码绑定多个回调 + if (sBindRegisters[id].binds[i].callback) { + sBindRegisters[id].binds[i].callback(CREATE_INDEX(id, i), NULL, 0); + } + + // 回调后立即释放 + FreeItem(id, i); + } +} + diff --git a/src/HTimer.c b/src/HTimer.c index 561d6a4..badae65 100644 --- a/src/HTimer.c +++ b/src/HTimer.c @@ -103,21 +103,21 @@ uint32_t HTimerGetMs() { return GetCurrentMs(); } -HTimer_t HTimerRegisterTimerInfo(uint8_t id, HTimerInfo *info, uint16_t infoLen) { +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 HTIMER_INVALID; + return 0; } if (sTimeRegisters[id].enable == 1) { LogD("id[%d] already register", id); - return HTIMER_INVALID; + return 0; } sTimeRegisters[id].timers = info; sTimeRegisters[id].len = infoLen; sTimeRegisters[id].enable = 1; - return 0; + return 1; } void HTimerRemoveRegister(uint8_t id) {