diff --git a/include/HDRPC.h b/include/HDRPC.h index bef6b95..99158e3 100644 --- a/include/HDRPC.h +++ b/include/HDRPC.h @@ -29,7 +29,7 @@ #endif // 使用64位 -// #define HDRPC_USE_64 +#define HDRPC_USE_64 // 数值类型 #ifdef HDRPC_USE_64 @@ -38,6 +38,9 @@ typedef uint64_t HDRPCValue_t; typedef uint32_t HDRPCValue_t; #endif +// 发送后配置索引id +typedef int16_t HDRPCIndexId_t; + /** * 类型数据, 多节字节按照大端解析: * 0x00: 用户数据, 数据首个字节为长度 @@ -111,15 +114,25 @@ typedef void (*HDRPCCallback)(HDRPCSession *session, uint8_t exception); typedef void (*HDRPCSendDataCall)(HDRPCSession *session); // 对端发送RPC数据到本地端解析后的处理 typedef void (*HDRPCReadDataCall)(HDRPCSession *session); +// 超时回调 +typedef void (*HDRPCTimeoutCall)(); // 调用缓存, 内存由用户提供 typedef struct __attribute__((packed)) HDRPCCallBuffer { - uint8_t enbale : 1; ///< 是否启用 - uint8_t skipExce: 1; ///< 跳过异常 - uint8_t nameLen : 6; ///< 函数名长度 - uint32_t lastTime; ///< 上次调用时间 - const char *name; ///< 函数名 - HDRPCCallback callback; ///< 回调 + uint32_t enbale : 1; ///< 是否启用 + uint32_t skipExce : 1; ///< 跳过异常 + uint32_t nameLen : 6; ///< 函数名长度 +#ifdef HDRPC_TIMEOUT + uint32_t isTimeout : 1; ///< 已经超时 + uint32_t delayMs : 23; ///< 等待超时时间(ms) +#endif + uint16_t funcCode; ///< 功能码 + uint32_t lastTime; ///< 上次调用时间 + const char *name; ///< 函数名 + HDRPCCallback callback; ///< 回调 +#ifdef HDRPC_TIMEOUT + HDRPCTimeoutCall timeout; ///< 超时回调, 就算超时只要没有覆盖还是会调用正常回调 +#endif } HDRPCCallBuffer; #ifndef __COUNT_ARGS_IMPL @@ -167,6 +180,8 @@ void HDRPCSetExceptionNotSkip(HDRPCSession *session, uint8_t enable); */ #define HDRPCCreate(_name, _len) HDRPCArgs _args##_name[_len + 1]; HDRPCSession _session##_name; HDRPCInitSession(&_session##_name, _args##_name, _len + 1); HDRPCSession *_name = &_session##_name +#define HDRPCReset(_name, _len) HDRPCInitSession(&_session##_name, _args##_name, _len + 1) + /** * @brief 用于辅助宏添加数据到session * @param session RPC参数会话 @@ -270,12 +285,17 @@ void HDRPCReadCallData(void *data, uint16_t len); /** * @brief 发送数据 * @param session 参数会话 + * @param funcCode 功能码 + * @param callBack 功能回调 * @param funcName 函数名称 * @param nameLen 名称长度 + * @param timeout 超时回调 + * @return int16_t id索引(返回-1无效) */ -void _HDRPCSendData(HDRPCSession *session, uint16_t funcCode, HDRPCCallback callBack, const char *funcName, uint8_t nameLen); -#define HDRPCSendData(session, code, func) _HDRPCSendData(session, code, func, #func, sizeof(#func) - 1) -#define HDRPCSendDataNotCall(session, code) _HDRPCSendData(session, code, NULL, NULL, 0) +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) +#define HDRPCSendDataNotCall(session, code) _HDRPCSendData(session, code, NULL, NULL, 0, NULL) +#define HDRPCSendDataTimeout(session, code, func, timeout) _HDRPCSendData(session, code, func, #func, sizeof(#func) - 1, timeout) /** * @brief 参数会话转换成发送数据 @@ -286,4 +306,29 @@ void _HDRPCSendData(HDRPCSession *session, uint16_t funcCode, HDRPCCallback call */ uint16_t HDRPCConvSendData(HDRPCSession *session, uint8_t *data, uint16_t len); +/** + * @brief 设置超时时间 + * @brief idIndex 发送返回的id索引 + * @brief delayMs 超时时间(ms) + */ +void HDRPCSetDelayTime(int16_t idIndex, uint16_t delayMs); + +/** + * @brief 移除任务 + * @brief idIndex 发送返回的id索引 + */ +void HDRPCRemoveTask(int16_t idIndex); + +/** + * @brief 获取对于任务的回调函数 + * @param idIndex 发送返回的id索引 + * @return 无效返回NULL + */ +HDRPCCallback HDRPCGetCallBack(int16_t idIndex); + +/** + * @brief 运转RPC, 主要用于处理超时 + */ +void HDRPCRun(); + #endif // __HDRPC_H__ diff --git a/include/HTimer.h b/include/HTimer.h index 8320f59..73dc1e9 100644 --- a/include/HTimer.h +++ b/include/HTimer.h @@ -34,6 +34,7 @@ typedef enum } eHTimerFlags; typedef void (*HTimerCallType)(); +typedef int16_t HTimer_t; ///< 注册的定时器信息, 定义为数组, 数量由外部控制 typedef struct HTimerInfo { @@ -59,7 +60,7 @@ uint32_t HTimerGetMs(); * @param infoLen 定时器信息长度 * @return HTIMER_INVALID 注册失败, 返回定时器ID */ -int16_t HTimerRegisterTimerInfo(uint8_t id, HTimerInfo *info, uint16_t infoLen); +HTimer_t HTimerRegisterTimerInfo(uint8_t id, HTimerInfo *info, uint16_t infoLen); ///< 移除定时器信息 void HTimerRemoveRegister(uint8_t id); @@ -68,15 +69,15 @@ void HTimerRemoveRegister(uint8_t id); void HTimerRun(uint8_t id); ///< 添加一个定时任务, 添加失败返回 HTIMER_INVALID, ms不超过24比特 -int16_t HTimerAdd(uint8_t id, uint32_t ms, HTimerCallType call, eHTimerFlags flags); +HTimer_t HTimerAdd(uint8_t id, uint32_t ms, HTimerCallType call, eHTimerFlags flags); ///< 移除一个定时任务 -void HTimerRemove(uint8_t id, int16_t index); +void HTimerRemove(uint8_t id, HTimer_t index); ///< 在定时器回调任务中获取当前定时器ID uint8_t HTimerGetCurrentId(); ///< 在定时器回调任务中获取当前定时器调用者索引, 不存在返回 HTIMER_INVALID -int16_t HTimerGetCurrentCaller(uint8_t id); +HTimer_t HTimerGetCurrentCaller(uint8_t id); #endif //__H_TIMER_H__ diff --git a/include/HUIPageManage.h b/include/HUIPageManage.h index 8fe6e27..ad2331f 100644 --- a/include/HUIPageManage.h +++ b/include/HUIPageManage.h @@ -46,6 +46,7 @@ #define UIPAGE_SWITCH_FUNC(func, ...) UIPAGE_CASE_RET(kCallSwitchPage, func, __VA_ARGS__) #define UIPAGE_INDEX_FUNC(func, ...) UIPAGE_CASE(kCallIndexSave, func, __VA_ARGS__) +#define UIPAGE_EVENT_FUNC(func, ...) UIPAGE_CASE(kCallNotifyEvent, func, __VA_ARGS__) #define UIPAGE_INIT_SHOW_FUNC(init, show) UIPAGE_INIT_FUNC(init); UIPAGE_SHOW_FUNC(show) #define UIPAGE_DEINIT_HIDE_FUNC(deinit, hide) UIPAGE_FREE_FUNC(deinit); UIPAGE_HIDE_FUNC(hide) @@ -54,6 +55,10 @@ // 对应事件的data转换具体类型宏 #define UI_CALL_INDEX_TYPE(value) ((HUiPageIndex_t *)value) +#define UI_CALL_EVENT_TYPE(value) ((HUiPageEvent_t *)value) + +// HD集成任务处理 +#define HD_UIPAGE_EVENT_FUNC(func) UIPAGE_CASE(kCallNotifyEvent, func, *(UI_CALL_EVENT_TYPE(UIPAGE_DATA))) /** ================================================================= */ @@ -68,9 +73,11 @@ enum eCallCmd kCallHidePage, ///< 退出页面, 此事件如果是返回触发的可以存储索引数据 kCallSwitchPage, ///< 切换页面, 对应页面返回false时则不切换, 所有切换都会触发这个事件 kCallIndexSave, ///< 存储当前索引事件, 通知此事件说明当前不是返回事件(cmd, HUiPageIndex_t *nextPage, 1); + kCallNotifyEvent, ///< 通知事件, 传递一个参数 }; typedef uint8_t HUiPageIndex_t; +typedef uint32_t HUiPageEvent_t; ///< cmd命令, data数据, len数据长度 typedef uint8_t (*pageCallType_t)(uint16_t cmd, void *data, uint16_t len); @@ -86,6 +93,9 @@ void HUIPageSetHome(HUiPageIndex_t page); // 因为有些页面可能不用HUIPageBack来返回, 所以需要兼容这种情况 void HUIPageSwitch(HUiPageIndex_t page); +// 通知当前页面事件任务 +void HUIPageNotifyEvent(HUiPageEvent_t event); + // 切换到主页 void HUIPageSwitchHome(); diff --git a/src/HDRPC.c b/src/HDRPC.c index 3d69ec5..3d69f9a 100644 --- a/src/HDRPC.c +++ b/src/HDRPC.c @@ -23,10 +23,25 @@ struct __attribute__((packed)) RPCInfo { HDRPCSession *readCallSession; ///< 对端RPC会话 uint8_t callLen; ///< 本地RPC调用缓存长度 + uint8_t useCallLen; ///< 当前使用的本地RPC调用缓存长度 + uint8_t timeoutCallLen; ///< 本地RPC超时缓存长度 }; static struct RPCInfo sInfo; +static void FreeItem(uint8_t index) +{ + if (sInfo.localCallBuffer[index].enbale) { + --sInfo.useCallLen; + if (sInfo.localCallBuffer[index].isTimeout) { + --sInfo.timeoutCallLen; + } + } + + memset(&sInfo.localCallBuffer[index], 0, sizeof(HDRPCCallBuffer)); + LogD("useCallLen[%d], timeoutCallLen[%d]", sInfo.useCallLen, sInfo.timeoutCallLen); +} + static void UpdateTimeout(HDRPCCallBuffer *callBuff) { if (callBuff == NULL) { return ; @@ -36,15 +51,63 @@ static void UpdateTimeout(HDRPCCallBuffer *callBuff) { return ; } - uint32_t curr = HDLogGetTime(); #ifdef HDRPC_TIMEOUT - if (curr - callBuff->lastTime > HDRPC_TIMEOUT) { - callBuff->enbale = 0; - LogD("Call[%s] Timeout", callBuff->name); + if (callBuff->isTimeout == 1) { + return ; + } + + const uint32_t curr = HDLogGetTime(); + if (curr - callBuff->lastTime > callBuff->delayMs) { + callBuff->isTimeout = 1; + ++sInfo.timeoutCallLen; + LogD("Call[%s] Timeout, buffLen[%d]", callBuff->name, sInfo.timeoutCallLen); + if (callBuff->timeout) { + callBuff->timeout(); + } } #endif } +static void UpdateCallTimeout(uint8_t index) { +#ifdef HDRPC_TIMEOUT + if (sInfo.localCallBuffer[index].enbale == 0) { + return ; + } + + if (sInfo.localCallBuffer[index].isTimeout == 0) { + return ; + } + + FreeItem(index); +#endif +} + +static void OffSomeBuff(uint8_t index, uint16_t func, const char *funcName, uint8_t len) { + if (sInfo.localCallBuffer[index].enbale == 0) { + return ; + } + +#ifdef HDRPC_TIMEOUT + if (sInfo.localCallBuffer[index].isTimeout == 0) { + return ; + } +#endif + + if (sInfo.localCallBuffer[index].funcCode != func) { + return ; + } + + if (sInfo.localCallBuffer[index].nameLen != len) { + return ; + } + + if (strncmp(sInfo.localCallBuffer[index].name, funcName, len) != 0) { + return ; + } + + FreeItem(index); +} + static void Call(HDRPCSession *session, uint16_t exception) { if (session == NULL) { LogD("Session is nullptr"); @@ -54,13 +117,11 @@ static void Call(HDRPCSession *session, uint16_t exception) { // 不是用户数据, 说明不需要回调 const uint8_t index = session->index - 1; if (session->index > 0 && session->args[index].type != kHDRPCUserData) { - LogD("func type[0x%x] Not call", session->args[index].type); + LogD("func[0x%x] type[0x%x] Not call", session->func, session->args[index].type); return ; } - uint16_t i = 0; - for (; i < sInfo.callLen; ++i) { - UpdateTimeout(&sInfo.localCallBuffer[i]); + for (uint16_t i = 0; i < sInfo.callLen; ++i) { if (sInfo.localCallBuffer[i].enbale == 0) { continue; } @@ -74,55 +135,59 @@ static void Call(HDRPCSession *session, uint16_t exception) { } if (exception != kHDRPCNotException && sInfo.localCallBuffer[i].skipExce == 1) { - sInfo.localCallBuffer[i].enbale = 0; LogD("Call[%s] Skip Exception", sInfo.localCallBuffer[i].name); + FreeItem(i); break; } LogD("Call[%s]", sInfo.localCallBuffer[i].name); - sInfo.localCallBuffer[i].callback(session, exception); + if (sInfo.localCallBuffer[i].callback) { + sInfo.localCallBuffer[i].callback(session, exception); + } + LogD("Call[%s] End", sInfo.localCallBuffer[i].name); - - sInfo.localCallBuffer[i].enbale = 0; - sInfo.localCallBuffer[i].nameLen = 0; - sInfo.localCallBuffer[i].name = NULL; + FreeItem(i); break; } - - for (++i; i < sInfo.callLen; ++i) { - UpdateTimeout(&sInfo.localCallBuffer[i]); - } } -static int16_t AddCall(HDRPCSession *session, HDRPCCallback callBack, const char *funcName, uint8_t nameLen) { - if (callBack == NULL || nameLen == 0) { +static int16_t AddCall(HDRPCSession *session, HDRPCCallback callBack, const char *funcName, uint8_t nameLen, HDRPCTimeoutCall timeout) { + int16_t result = -1; + if (session == NULL || callBack == NULL || nameLen == 0) { LogD("funcName[%s], len[%d] add Faild", funcName, nameLen); - return -1; + return result; } - int16_t result = -1; - int i = 0; - for (; i < sInfo.callLen; ++i) { - UpdateTimeout(&sInfo.localCallBuffer[i]); + const uint8_t isFulll = sInfo.useCallLen >= sInfo.callLen; + for (uint16_t i = 0; i < sInfo.callLen; ++i) { +#ifdef HDRPC_TIMEOUT + if (isFulll) { + // 如果满了就把已经超时的丢弃 + UpdateCallTimeout(i); + } +#endif + + OffSomeBuff(i, session->func, funcName, nameLen); if (sInfo.localCallBuffer[i].enbale == 1) { continue; } + ++sInfo.useCallLen; + sInfo.localCallBuffer[i].enbale = 1; + sInfo.localCallBuffer[i].funcCode = session->func; sInfo.localCallBuffer[i].skipExce = !session->exceptionNotSkip; sInfo.localCallBuffer[i].callback = callBack; sInfo.localCallBuffer[i].nameLen = nameLen; sInfo.localCallBuffer[i].name = funcName; + sInfo.localCallBuffer[i].timeout = timeout; + sInfo.localCallBuffer[i].delayMs = HDRPC_TIMEOUT; sInfo.localCallBuffer[i].lastTime = HDLogGetTime(); result = i; break; } - for (++i; i < sInfo.callLen; ++i) { - UpdateTimeout(&sInfo.localCallBuffer[i]); - } - if (result == -1) { LogD("add call is full, funcName[%s] faild, callLen[%d]", funcName, sInfo.callLen); } @@ -622,11 +687,12 @@ void HDRPCReadCallData(void *data, uint16_t len) ParseReadDataCall(session, data, len); } -void _HDRPCSendData(HDRPCSession *session, uint16_t funcCode, HDRPCCallback callBack, const char *funcName, uint8_t nameLen) +int16_t _HDRPCSendData(HDRPCSession *session, uint16_t funcCode, HDRPCCallback callBack, const char *funcName, uint8_t nameLen, HDRPCTimeoutCall timeout) { + int16_t result = -1; if (sInfo.writeCall == NULL) { LogD("Write Call is nullptr"); - return ; + return result; } if (session) { @@ -643,12 +709,14 @@ void _HDRPCSendData(HDRPCSession *session, uint16_t funcCode, HDRPCCallback call break; } - if (AddCall(session, callBack, funcName, nameLen) == -1) { + result = AddCall(session, callBack, funcName, nameLen, timeout); + if (result == -1) { LogD("Add Call[%s] faild", funcName); } } while (0); sInfo.writeCall(session); + return result; } @@ -675,3 +743,48 @@ uint16_t HDRPCConvSendData(HDRPCSession *session, uint8_t *data, uint16_t len) return useLen; } + +void HDRPCSetDelayTime(int16_t idIndex, uint16_t delayMs) +{ + if (idIndex <= 0 || idIndex >= sInfo.callLen) { + LogD("Invalid idIndex[%d]", idIndex); + return; + } + + sInfo.localCallBuffer[idIndex].delayMs = delayMs; +} + +HDRPCCallback HDRPCGetCallBack(int16_t idIndex) +{ + if (idIndex <= 0 || idIndex >= sInfo.callLen) { + LogD("Invalid idIndex[%d]", idIndex); + return NULL; + } + + return sInfo.localCallBuffer[idIndex].callback; +} + +void HDRPCRemoveTask(int16_t idIndex) +{ + if (idIndex <= 0 || idIndex >= sInfo.callLen) { + LogD("Invalid idIndex[%d]", idIndex); + return; + } + + if (sInfo.localCallBuffer[idIndex].enbale) { + LogD("Remove Task[%d], name[%s]", idIndex, sInfo.localCallBuffer[idIndex].name); + } + + FreeItem(idIndex); +} + +void HDRPCRun() +{ + if (sInfo.useCallLen - sInfo.timeoutCallLen == 0) { + return ; + } + + for (uint16_t i = 0; i < sInfo.callLen; ++i) { + UpdateTimeout(&sInfo.localCallBuffer[i]); + } +} diff --git a/src/HRingBuffer.c b/src/HRingBuffer.c index 629f7d6..a5b740a 100644 --- a/src/HRingBuffer.c +++ b/src/HRingBuffer.c @@ -84,6 +84,10 @@ static void SetRingBufferData(HRingBufferType *ringBuffer, HRingBufferLenType po } static uint8_t IsRingBufferFull(const HRingBufferType *ringBuffer) { + if (ringBuffer == NULL) { + return 1; + } + InitRingBuffer((HRingBufferType *)ringBuffer); const _HRingBufferBase *base = (const _HRingBufferBase *)ringBuffer; return (base->flag & kHRingBufferFull) == kHRingBufferFull; diff --git a/src/HTimer.c b/src/HTimer.c index 157ba50..561d6a4 100644 --- a/src/HTimer.c +++ b/src/HTimer.c @@ -2,6 +2,7 @@ #include "HTimer.h" #include "HDLog.h" +#include // 用于拷贝定时器文件使用可直接删除HDLog.h文件避免依赖 #ifndef LogD @@ -102,7 +103,7 @@ uint32_t HTimerGetMs() { return GetCurrentMs(); } -int16_t HTimerRegisterTimerInfo(uint8_t id, HTimerInfo *info, uint16_t infoLen) { +HTimer_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; @@ -169,9 +170,9 @@ void HTimerRun(uint8_t id) { } } -int16_t HTimerAdd(uint8_t id, uint32_t ms, HTimerCallType call, eHTimerFlags flags) { +HTimer_t HTimerAdd(uint8_t id, uint32_t ms, HTimerCallType call, eHTimerFlags flags) { #ifdef HTIMER_CHECK_INVALID_LOOP - int16_t result = AddTimerData(id, ms, call, flags); + HTimer_t result = AddTimerData(id, ms, call, flags); if (result == HTIMER_INVALID) { while (1); } @@ -181,7 +182,7 @@ int16_t HTimerAdd(uint8_t id, uint32_t ms, HTimerCallType call, eHTimerFlags fla #endif } -void HTimerRemove(uint8_t id, int16_t index) { +void HTimerRemove(uint8_t id, HTimer_t index) { if (id >= HTIMER_REGISTER_MAX) { LogD("error id[%d]", id); return ; @@ -205,7 +206,7 @@ uint8_t HTimerGetCurrentId() { return HTIMER_INVALID; } -int16_t HTimerGetCurrentCaller(uint8_t id) { +HTimer_t HTimerGetCurrentCaller(uint8_t id) { if (id >= HTIMER_REGISTER_MAX) { return HTIMER_INVALID; } diff --git a/src/HUIPageManage.c b/src/HUIPageManage.c index d8f8515..1970142 100644 --- a/src/HUIPageManage.c +++ b/src/HUIPageManage.c @@ -222,6 +222,11 @@ void HUIPageSwitch(HUiPageIndex_t page) { SwitchPage(page); } +void HUIPageNotifyEvent(HUiPageEvent_t event) +{ + pageManage.pageCall[pageManage.currPage](kCallNotifyEvent, &event, 1); +} + void HUIPageSwitchHome() { if (HUIPageClear() == 0) { return ;