From 697fe56098c0e91d444bdef3b919cedc34fbcdb0 Mon Sep 17 00:00:00 2001 From: coffee Date: Wed, 17 Sep 2025 23:48:08 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E4=BF=AE=E5=A4=8D=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=202.=20=E4=BF=AE=E5=A4=8D=E7=8E=AF=E7=8A=B6?= =?UTF-8?q?=E7=BC=93=E5=86=B2=E5=8C=BA=E5=AD=98=E5=9C=A8=E4=B8=AD=E6=96=AD?= =?UTF-8?q?=E8=B6=8A=E4=BD=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/HDProtocolServer.h | 18 +++++++--- include/HTimer.h | 14 ++++---- src/HDProtocolServer.c | 68 +++++++++++++++++++++++++++++--------- src/HRingBuffer.c | 37 +++++++-------------- src/HTimer.c | 8 ++++- 5 files changed, 93 insertions(+), 52 deletions(-) diff --git a/include/HDProtocolServer.h b/include/HDProtocolServer.h index c7c4161..b2c6a85 100644 --- a/include/HDProtocolServer.h +++ b/include/HDProtocolServer.h @@ -29,7 +29,7 @@ #define HDPROTOCOL_DELAY_TIMEOUT (100) // 数据占用时间 -#define HDPROTOCOL_OCCUPY_TIMEOUT (3000) +#define HDPROTOCOL_OCCUPY_TIMEOUT (1000) enum eHDProtocolSupport @@ -37,6 +37,7 @@ enum eHDProtocolSupport kHDProtocolNone = 0x00, ///< 无协议, 不阻塞等待 kHDProtocolFpga = 0x01, ///< fpga协议, 独占解析端 kHDProtocolVP = 0x02, ///< vp协议, 独占解析端 + kHDProtocolTV = 0x04, ///< tv协议 }; /** @@ -51,10 +52,13 @@ typedef struct __attribute__((__packed__)) HDProtocolServerInfo uint8_t src; ///< 源数据口 uint8_t dst; ///< 目标数据口(如果需要始终转发可以修改该项目, 否则默认和src一样) uint8_t tmpDst; ///< 临时回送目标数据口(用于该指令需要先请求某个数据后才能回复的情况) - uint8_t tmpReadCount : 6; ///< 临时数据最大等待回复次数 + uint8_t tmpReadCount : 5; ///< 临时数据最大等待回复次数 uint8_t tmpEnable : 1; ///< 当前临时目标等待数据, 需要等待数据内部标记开启, 数据完成或者超时后自动关闭 uint8_t run : 1; ///< 内部标记当前正常读取, 如果再次触发解析, 则不等待 - uint8_t delayCount; ///< 延时等待次数(默认: 1), 每次等待时间为 HSCHEDULE_DELAY_TIMEOUT + uint8_t checkAlarm : 1; ///< 启动缓存报警检查 + uint8_t notifyAlarm : 1; ///< 通知缓存报警(内部管理) + uint8_t occupy : 1; ///< 内部标记当前正在占用 + uint8_t delayCount : 6; ///< 延时等待次数(默认: 1), 每次等待时间为 HSCHEDULE_DELAY_TIMEOUT } HDProtocolServerInfo; /** @@ -65,7 +69,7 @@ typedef struct __attribute__((__packed__)) HDProtocolServerInfo */ typedef int (*HDProtocolReadCallback)(HDProtocolServerInfo *info, uint8_t isTimeout); typedef void (*HDProtocolWriteCallback)(HDProtocolServerInfo *info, const uint8_t *data, int len); - +typedef void (*HDProtocolCheckAlarmCallback)(HDProtocolServerInfo *info); /** * @brief 设置协议回调函数 * @param readCall 读取回调函数 @@ -73,6 +77,12 @@ typedef void (*HDProtocolWriteCallback)(HDProtocolServerInfo *info, const uint8_ */ void HDProtocolSetCallback(HDProtocolReadCallback readCall, HDProtocolWriteCallback writeCall); +/** + * @brief 设置缓冲区报警回调, 需要立刻返回, 不能阻塞 + * @param checkCall 检查缓冲区报警回调函数 + */ +void HDProtocolCheckAlarmCall(HDProtocolCheckAlarmCallback checkCall); + /** * @brief 初始化协议信息结构, 将原始缓冲器转换成环状缓冲区(需要消耗一些字节) * @param info 协议信息结构 diff --git a/include/HTimer.h b/include/HTimer.h index 49ecf87..8320f59 100644 --- a/include/HTimer.h +++ b/include/HTimer.h @@ -13,7 +13,7 @@ // 定时器注册最大数量 #ifndef HTIMER_REGISTER_MAX -#define HTIMER_REGISTER_MAX (1) +#define HTIMER_REGISTER_MAX (5) #endif // 无效值 @@ -37,12 +37,12 @@ typedef void (*HTimerCallType)(); ///< 注册的定时器信息, 定义为数组, 数量由外部控制 typedef struct HTimerInfo { - uint32_t flags : 1; ///< 定时器标志, eTimerFlags - uint32_t enable : 1; ///< 定时器使能 - uint32_t curr : 1; ///< 当前回调者 - uint32_t duration : 29; ///< 定时触发时长, 毫秒为计数单元 - uint32_t lastTime; ///< 上次触发时间 - HTimerCallType call; ///< 定时触发函数 + uint32_t flags : 1; ///< 定时器标志, eTimerFlags + volatile uint32_t enable: 2; ///< 定时器使能 + uint32_t curr : 1; ///< 当前回调者 + uint32_t duration : 28; ///< 定时触发时长, 毫秒为计数单元 + uint32_t lastTime; ///< 上次触发时间 + HTimerCallType call; ///< 定时触发函数 } HTimerInfo; diff --git a/src/HDProtocolServer.c b/src/HDProtocolServer.c index 62ea52b..95e5d20 100644 --- a/src/HDProtocolServer.c +++ b/src/HDProtocolServer.c @@ -2,6 +2,7 @@ #include "HDProtocolServer.h" #include "HRingBuffer.h" +// #include "src/sys/inc/HDSystemTask.h" #include "HDLog.h" #include #include @@ -11,7 +12,8 @@ #define HDDelayMs(ms) #endif -#define OCCUPIED_MAX (5) +// 占用信息监测, 需要大于协议数量 +#define OCCUPIED_MAX (10) struct __attribute__((__packed__)) OccupiedInfo { @@ -23,11 +25,12 @@ struct __attribute__((__packed__)) OccupiedInfo { }; struct __attribute__((__packed__)) HScheduleRegisterInfo { - HDProtocolReadCallback readCall; ///< 读取回调 - HDProtocolWriteCallback writeCall; ///< 写入回调 - HDProtocolServerInfo *info; ///< 协议信息 - uint8_t infoLen; ///< 协议信息长度 - uint8_t useIndex; ///< 当前使用的索引 + HDProtocolReadCallback readCall; ///< 读取回调 + HDProtocolWriteCallback writeCall; ///< 写入回调 + HDProtocolCheckAlarmCallback checkAlarmCall; ///< 检查缓冲区报警回调 + HDProtocolServerInfo *info; ///< 协议信息 + uint8_t infoLen; ///< 协议信息长度 + uint8_t useIndex; ///< 当前使用的索引 }; static struct HScheduleRegisterInfo sInfo; @@ -38,7 +41,7 @@ static uint8_t IsOccupied(uint8_t currIndex, uint8_t protocol, uint8_t *occupied { if (currIndex >= OCCUPIED_MAX) { LogE("index[%d] out of range[%d]", currIndex, OCCUPIED_MAX); - return 1; + return 0; } for (int i = 0; i < OCCUPIED_MAX; ++i) { @@ -59,6 +62,7 @@ static uint8_t IsOccupied(uint8_t currIndex, uint8_t protocol, uint8_t *occupied return 0; } + // 被其他协议占用 sOccupiedInfo[i].waitOccupy = 1; return 1; } @@ -95,6 +99,8 @@ static void SetOccupied(uint8_t currIndex, uint8_t protocol, uint8_t enable) sOccupiedInfo[i].protocol = 0; sOccupiedInfo[i].occupyTime = 0; sOccupiedInfo[i].waitOccupy = 0; + + sInfo.info[currIndex].occupy = 0; return ; } @@ -111,6 +117,8 @@ static void SetOccupied(uint8_t currIndex, uint8_t protocol, uint8_t enable) sOccupiedInfo[index].index = currIndex; sOccupiedInfo[index].protocol = protocol; sOccupiedInfo[index].occupyTime = HDLogGetTime(); + + sInfo.info[currIndex].occupy = 1; } static void WaitRead(HDProtocolServerInfo *info) @@ -120,6 +128,7 @@ static void WaitRead(HDProtocolServerInfo *info) } for (int i = 0; i < info->delayCount; ++i) { + uint32_t curr = HDLogGetTime(); for (int j = 0; j < HDPROTOCOL_DELAY_TIMEOUT; ++j) { HDProtocolRun(); if (info->tmpEnable == 0) { @@ -130,6 +139,10 @@ static void WaitRead(HDProtocolServerInfo *info) if (info->run == 0) { HDDelayMs(1); } + + if (HDLogGetTime() - curr >= HDPROTOCOL_DELAY_TIMEOUT) { + break; + } } if (info->tmpEnable == 0) { @@ -137,6 +150,10 @@ static void WaitRead(HDProtocolServerInfo *info) } } + if (info->tmpEnable) { + LogD("wait tmp read not recv[%d]", info->src); + } + info->tmpEnable = 0; } @@ -145,6 +162,12 @@ static void ParseReadData(int index, int isTimeout) sInfo.useIndex = index; const int len = sInfo.readCall(&sInfo.info[index], isTimeout); sInfo.useIndex = sInfo.infoLen; + // 当前在中断, 且自身处于占用状态, 立刻返回 + if (sInfo.info[index].run && sInfo.info[index].occupy) { + return ; + } + + sInfo.info[index].notifyAlarm = 0; if (len == 0 && sInfo.info[index].tmpEnable) { // 临时路由转发数据 if (sInfo.info[index].tmpReadCount > 0) { @@ -169,6 +192,11 @@ void HDProtocolSetCallback(HDProtocolReadCallback readCall, HDProtocolWriteCallb sInfo.writeCall = writeCall; } +void HDProtocolCheckAlarmCall(HDProtocolCheckAlarmCallback checkCall) +{ + sInfo.checkAlarmCall = checkCall; +} + void HDProtocolInitInfo(HDProtocolServerInfo *info, uint8_t src, void *data, int dataLen) { if (info == NULL) { @@ -192,7 +220,7 @@ void _HDProtocolSetSupportProtocol(HDProtocolServerInfo *info, int len, ...) va_list args; va_start(args, len); for (int i = 0; i < len; ++i) { - info->supportProtocol |= (1 << va_arg(args, int)); + info->supportProtocol |= va_arg(args, int); } va_end(args); @@ -258,7 +286,7 @@ uint8_t HDProtocolGetDest(HDProtocolServerInfo *info) return 0; } - if (info->tmpEnable) { + if (info->tmpEnable && info == HDProtocolGetCurrInfo()) { return info->tmpDst; } @@ -295,13 +323,13 @@ void HDProtocolRead(uint8_t src, const void *data, int len) sInfo.info[src].run = 1; for (int i = 0; i < len; ++i) { if (HRingBufferFull(sInfo.info[src].readBuff)) { - // 只需要检查一次 - if (occupy == 0xff) { + // 当自身处于未占用时, 需要检查一次 + if (sInfo.info[src].occupy == 0) { occupy = IsOccupied(src, sInfo.info[src].supportProtocol, NULL); } - // 检查是否占用 - if (occupy == 0) { + // 自身处于占用状态或者当前可占用时执行读取 + if (sInfo.info[src].occupy || occupy == 0) { ParseReadData(src, 0); } } @@ -309,6 +337,16 @@ void HDProtocolRead(uint8_t src, const void *data, int len) HRingBufferAddDataOver(sInfo.info[src].readBuff, srcData[i]); } + // 协议开启缓存报警检测时, 且未通知过 + if (sInfo.info[src].checkAlarm && sInfo.info[src].notifyAlarm == 0 && sInfo.checkAlarmCall) { + const HRingBufferLenType readLen = HRingBufferGetUseByteLen(sInfo.info[src].readBuff); + const HRingBufferLenType buffLen = HRingBufferGetLen(sInfo.info[src].readBuff) >> 1; + if (readLen >= buffLen) { + // 只通知一次, 读取数据后再次检查 + sInfo.info[src].notifyAlarm = 1; + sInfo.checkAlarmCall(&sInfo.info[src]); + } + } sInfo.info[src].run = 0; } @@ -331,8 +369,8 @@ void HDProtocolRun() // 有之前的数据已经占用了, 并且检查是否超时 uint8_t occupiedIndex = OCCUPIED_MAX; if (IsOccupied(i, sInfo.info[i].supportProtocol, &occupiedIndex)) { - // 异常情况 if (occupiedIndex >= OCCUPIED_MAX) { + LogE("occupiedIndex[%d] is out of range[%d]", occupiedIndex, OCCUPIED_MAX); continue; } @@ -341,7 +379,7 @@ void HDProtocolRun() continue; } - // 通知协议超时 + // 通知协议超时, 数据清空 ParseReadData(occupiedIndex, 1); // 如果还占用, 说明用户那边自己要求继续占用 diff --git a/src/HRingBuffer.c b/src/HRingBuffer.c index 32d65d3..629f7d6 100644 --- a/src/HRingBuffer.c +++ b/src/HRingBuffer.c @@ -199,37 +199,24 @@ HRingBufferLenType HRingBufferGetByteDatas(HRingBufferType* buffer, uint8_t *dat _HRingBufferBase *base = (_HRingBufferBase *)buffer; const HRingBufferLenType typeSize = GetRingBufferTypeSize(buffer); - const HRingBufferLenType dataLen = HRingBufferGetUseByteLen(buffer); - len = len / typeSize * typeSize; - len = (len > dataLen) ? dataLen : len; - HRingBufferLenType readLen = 0; - if (base->start >= base->end) { - int copySize = (base->len - base->start) * typeSize; - if (copySize > len) { - copySize = len; - } - - memcpy(data, GetRingByteData(buffer, base->start), copySize); - readLen += copySize; - data += copySize; - len -= copySize; - AdjustReadPos(buffer, copySize / typeSize); + const HRingBufferLenType startPos = base->start; + const HRingBufferLenType endPos = base->end; + int copyLen = (endPos - startPos) * typeSize; + if (startPos >= endPos) { + copyLen = (base->len - startPos) * typeSize; } - if (len == 0) { - return readLen; + if (copyLen > len) { + copyLen = len / typeSize * typeSize; } - int copySize = (base->end - base->start) * typeSize; - if (copySize > len) { - copySize = len; + if (copyLen == 0) { + return 0; } - memcpy(data, GetRingByteData(buffer, base->start), copySize); - readLen += copySize; - len -= copySize; - AdjustReadPos(buffer, copySize / typeSize); - return readLen; + memcpy(data, GetRingByteData(buffer, startPos), copyLen); + AdjustReadPos(buffer, copyLen / typeSize); + return copyLen; } // 获取环形缓冲区数据长度 diff --git a/src/HTimer.c b/src/HTimer.c index f9ce9f1..157ba50 100644 --- a/src/HTimer.c +++ b/src/HTimer.c @@ -68,11 +68,17 @@ static int16_t AddTimerData(uint8_t id, uint32_t duration, HTimerCallType call, } for (uint16_t i = 0; i < sTimeRegisters[id].len; ++i) { - if (sTimeRegisters[id].timers[i].enable == 1) { + 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;