1. 修复协议服务

2. 修复环状缓冲区存在中断越位问题
This commit is contained in:
coffee 2025-09-17 23:48:08 +08:00
parent 22b508ad31
commit 697fe56098
5 changed files with 93 additions and 52 deletions

View File

@ -29,7 +29,7 @@
#define HDPROTOCOL_DELAY_TIMEOUT (100) #define HDPROTOCOL_DELAY_TIMEOUT (100)
// 数据占用时间 // 数据占用时间
#define HDPROTOCOL_OCCUPY_TIMEOUT (3000) #define HDPROTOCOL_OCCUPY_TIMEOUT (1000)
enum eHDProtocolSupport enum eHDProtocolSupport
@ -37,6 +37,7 @@ enum eHDProtocolSupport
kHDProtocolNone = 0x00, ///< 无协议, 不阻塞等待 kHDProtocolNone = 0x00, ///< 无协议, 不阻塞等待
kHDProtocolFpga = 0x01, ///< fpga协议, 独占解析端 kHDProtocolFpga = 0x01, ///< fpga协议, 独占解析端
kHDProtocolVP = 0x02, ///< vp协议, 独占解析端 kHDProtocolVP = 0x02, ///< vp协议, 独占解析端
kHDProtocolTV = 0x04, ///< tv协议
}; };
/** /**
@ -51,10 +52,13 @@ typedef struct __attribute__((__packed__)) HDProtocolServerInfo
uint8_t src; ///< 源数据口 uint8_t src; ///< 源数据口
uint8_t dst; ///< 目标数据口(如果需要始终转发可以修改该项目, 否则默认和src一样) uint8_t dst; ///< 目标数据口(如果需要始终转发可以修改该项目, 否则默认和src一样)
uint8_t tmpDst; ///< 临时回送目标数据口(用于该指令需要先请求某个数据后才能回复的情况) uint8_t tmpDst; ///< 临时回送目标数据口(用于该指令需要先请求某个数据后才能回复的情况)
uint8_t tmpReadCount : 6; ///< 临时数据最大等待回复次数 uint8_t tmpReadCount : 5; ///< 临时数据最大等待回复次数
uint8_t tmpEnable : 1; ///< 当前临时目标等待数据, 需要等待数据内部标记开启, 数据完成或者超时后自动关闭 uint8_t tmpEnable : 1; ///< 当前临时目标等待数据, 需要等待数据内部标记开启, 数据完成或者超时后自动关闭
uint8_t run : 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; } HDProtocolServerInfo;
/** /**
@ -65,7 +69,7 @@ typedef struct __attribute__((__packed__)) HDProtocolServerInfo
*/ */
typedef int (*HDProtocolReadCallback)(HDProtocolServerInfo *info, uint8_t isTimeout); typedef int (*HDProtocolReadCallback)(HDProtocolServerInfo *info, uint8_t isTimeout);
typedef void (*HDProtocolWriteCallback)(HDProtocolServerInfo *info, const uint8_t *data, int len); typedef void (*HDProtocolWriteCallback)(HDProtocolServerInfo *info, const uint8_t *data, int len);
typedef void (*HDProtocolCheckAlarmCallback)(HDProtocolServerInfo *info);
/** /**
* @brief * @brief
* @param readCall * @param readCall
@ -73,6 +77,12 @@ typedef void (*HDProtocolWriteCallback)(HDProtocolServerInfo *info, const uint8_
*/ */
void HDProtocolSetCallback(HDProtocolReadCallback readCall, HDProtocolWriteCallback writeCall); void HDProtocolSetCallback(HDProtocolReadCallback readCall, HDProtocolWriteCallback writeCall);
/**
* @brief , ,
* @param checkCall
*/
void HDProtocolCheckAlarmCall(HDProtocolCheckAlarmCallback checkCall);
/** /**
* @brief , () * @brief , ()
* @param info * @param info

View File

@ -13,7 +13,7 @@
// 定时器注册最大数量 // 定时器注册最大数量
#ifndef HTIMER_REGISTER_MAX #ifndef HTIMER_REGISTER_MAX
#define HTIMER_REGISTER_MAX (1) #define HTIMER_REGISTER_MAX (5)
#endif #endif
// 无效值 // 无效值
@ -37,12 +37,12 @@ typedef void (*HTimerCallType)();
///< 注册的定时器信息, 定义为数组, 数量由外部控制 ///< 注册的定时器信息, 定义为数组, 数量由外部控制
typedef struct HTimerInfo { typedef struct HTimerInfo {
uint32_t flags : 1; ///< 定时器标志, eTimerFlags uint32_t flags : 1; ///< 定时器标志, eTimerFlags
uint32_t enable : 1; ///< 定时器使能 volatile uint32_t enable: 2; ///< 定时器使能
uint32_t curr : 1; ///< 当前回调者 uint32_t curr : 1; ///< 当前回调者
uint32_t duration : 29; ///< 定时触发时长, 毫秒为计数单元 uint32_t duration : 28; ///< 定时触发时长, 毫秒为计数单元
uint32_t lastTime; ///< 上次触发时间 uint32_t lastTime; ///< 上次触发时间
HTimerCallType call; ///< 定时触发函数 HTimerCallType call; ///< 定时触发函数
} HTimerInfo; } HTimerInfo;

View File

@ -2,6 +2,7 @@
#include "HDProtocolServer.h" #include "HDProtocolServer.h"
#include "HRingBuffer.h" #include "HRingBuffer.h"
// #include "src/sys/inc/HDSystemTask.h"
#include "HDLog.h" #include "HDLog.h"
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
@ -11,7 +12,8 @@
#define HDDelayMs(ms) #define HDDelayMs(ms)
#endif #endif
#define OCCUPIED_MAX (5) // 占用信息监测, 需要大于协议数量
#define OCCUPIED_MAX (10)
struct __attribute__((__packed__)) OccupiedInfo { struct __attribute__((__packed__)) OccupiedInfo {
@ -23,11 +25,12 @@ struct __attribute__((__packed__)) OccupiedInfo {
}; };
struct __attribute__((__packed__)) HScheduleRegisterInfo { struct __attribute__((__packed__)) HScheduleRegisterInfo {
HDProtocolReadCallback readCall; ///< 读取回调 HDProtocolReadCallback readCall; ///< 读取回调
HDProtocolWriteCallback writeCall; ///< 写入回调 HDProtocolWriteCallback writeCall; ///< 写入回调
HDProtocolServerInfo *info; ///< 协议信息 HDProtocolCheckAlarmCallback checkAlarmCall; ///< 检查缓冲区报警回调
uint8_t infoLen; ///< 协议信息长度 HDProtocolServerInfo *info; ///< 协议信息
uint8_t useIndex; ///< 当前使用的索引 uint8_t infoLen; ///< 协议信息长度
uint8_t useIndex; ///< 当前使用的索引
}; };
static struct HScheduleRegisterInfo sInfo; 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) { if (currIndex >= OCCUPIED_MAX) {
LogE("index[%d] out of range[%d]", 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) { 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; return 0;
} }
// 被其他协议占用
sOccupiedInfo[i].waitOccupy = 1; sOccupiedInfo[i].waitOccupy = 1;
return 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].protocol = 0;
sOccupiedInfo[i].occupyTime = 0; sOccupiedInfo[i].occupyTime = 0;
sOccupiedInfo[i].waitOccupy = 0; sOccupiedInfo[i].waitOccupy = 0;
sInfo.info[currIndex].occupy = 0;
return ; return ;
} }
@ -111,6 +117,8 @@ static void SetOccupied(uint8_t currIndex, uint8_t protocol, uint8_t enable)
sOccupiedInfo[index].index = currIndex; sOccupiedInfo[index].index = currIndex;
sOccupiedInfo[index].protocol = protocol; sOccupiedInfo[index].protocol = protocol;
sOccupiedInfo[index].occupyTime = HDLogGetTime(); sOccupiedInfo[index].occupyTime = HDLogGetTime();
sInfo.info[currIndex].occupy = 1;
} }
static void WaitRead(HDProtocolServerInfo *info) static void WaitRead(HDProtocolServerInfo *info)
@ -120,6 +128,7 @@ static void WaitRead(HDProtocolServerInfo *info)
} }
for (int i = 0; i < info->delayCount; ++i) { for (int i = 0; i < info->delayCount; ++i) {
uint32_t curr = HDLogGetTime();
for (int j = 0; j < HDPROTOCOL_DELAY_TIMEOUT; ++j) { for (int j = 0; j < HDPROTOCOL_DELAY_TIMEOUT; ++j) {
HDProtocolRun(); HDProtocolRun();
if (info->tmpEnable == 0) { if (info->tmpEnable == 0) {
@ -130,6 +139,10 @@ static void WaitRead(HDProtocolServerInfo *info)
if (info->run == 0) { if (info->run == 0) {
HDDelayMs(1); HDDelayMs(1);
} }
if (HDLogGetTime() - curr >= HDPROTOCOL_DELAY_TIMEOUT) {
break;
}
} }
if (info->tmpEnable == 0) { 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; info->tmpEnable = 0;
} }
@ -145,6 +162,12 @@ static void ParseReadData(int index, int isTimeout)
sInfo.useIndex = index; sInfo.useIndex = index;
const int len = sInfo.readCall(&sInfo.info[index], isTimeout); const int len = sInfo.readCall(&sInfo.info[index], isTimeout);
sInfo.useIndex = sInfo.infoLen; 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 (len == 0 && sInfo.info[index].tmpEnable) {
// 临时路由转发数据 // 临时路由转发数据
if (sInfo.info[index].tmpReadCount > 0) { if (sInfo.info[index].tmpReadCount > 0) {
@ -169,6 +192,11 @@ void HDProtocolSetCallback(HDProtocolReadCallback readCall, HDProtocolWriteCallb
sInfo.writeCall = writeCall; sInfo.writeCall = writeCall;
} }
void HDProtocolCheckAlarmCall(HDProtocolCheckAlarmCallback checkCall)
{
sInfo.checkAlarmCall = checkCall;
}
void HDProtocolInitInfo(HDProtocolServerInfo *info, uint8_t src, void *data, int dataLen) void HDProtocolInitInfo(HDProtocolServerInfo *info, uint8_t src, void *data, int dataLen)
{ {
if (info == NULL) { if (info == NULL) {
@ -192,7 +220,7 @@ void _HDProtocolSetSupportProtocol(HDProtocolServerInfo *info, int len, ...)
va_list args; va_list args;
va_start(args, len); va_start(args, len);
for (int i = 0; i < len; ++i) { for (int i = 0; i < len; ++i) {
info->supportProtocol |= (1 << va_arg(args, int)); info->supportProtocol |= va_arg(args, int);
} }
va_end(args); va_end(args);
@ -258,7 +286,7 @@ uint8_t HDProtocolGetDest(HDProtocolServerInfo *info)
return 0; return 0;
} }
if (info->tmpEnable) { if (info->tmpEnable && info == HDProtocolGetCurrInfo()) {
return info->tmpDst; return info->tmpDst;
} }
@ -295,13 +323,13 @@ void HDProtocolRead(uint8_t src, const void *data, int len)
sInfo.info[src].run = 1; sInfo.info[src].run = 1;
for (int i = 0; i < len; ++i) { for (int i = 0; i < len; ++i) {
if (HRingBufferFull(sInfo.info[src].readBuff)) { if (HRingBufferFull(sInfo.info[src].readBuff)) {
// 需要检查一次 // 当自身处于未占用时, 需要检查一次
if (occupy == 0xff) { if (sInfo.info[src].occupy == 0) {
occupy = IsOccupied(src, sInfo.info[src].supportProtocol, NULL); occupy = IsOccupied(src, sInfo.info[src].supportProtocol, NULL);
} }
// 检查是否占用 // 自身处于占用状态或者当前可占用时执行读取
if (occupy == 0) { if (sInfo.info[src].occupy || occupy == 0) {
ParseReadData(src, 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]); 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; sInfo.info[src].run = 0;
} }
@ -331,8 +369,8 @@ void HDProtocolRun()
// 有之前的数据已经占用了, 并且检查是否超时 // 有之前的数据已经占用了, 并且检查是否超时
uint8_t occupiedIndex = OCCUPIED_MAX; uint8_t occupiedIndex = OCCUPIED_MAX;
if (IsOccupied(i, sInfo.info[i].supportProtocol, &occupiedIndex)) { if (IsOccupied(i, sInfo.info[i].supportProtocol, &occupiedIndex)) {
// 异常情况
if (occupiedIndex >= OCCUPIED_MAX) { if (occupiedIndex >= OCCUPIED_MAX) {
LogE("occupiedIndex[%d] is out of range[%d]", occupiedIndex, OCCUPIED_MAX);
continue; continue;
} }
@ -341,7 +379,7 @@ void HDProtocolRun()
continue; continue;
} }
// 通知协议超时 // 通知协议超时, 数据清空
ParseReadData(occupiedIndex, 1); ParseReadData(occupiedIndex, 1);
// 如果还占用, 说明用户那边自己要求继续占用 // 如果还占用, 说明用户那边自己要求继续占用

View File

@ -199,37 +199,24 @@ HRingBufferLenType HRingBufferGetByteDatas(HRingBufferType* buffer, uint8_t *dat
_HRingBufferBase *base = (_HRingBufferBase *)buffer; _HRingBufferBase *base = (_HRingBufferBase *)buffer;
const HRingBufferLenType typeSize = GetRingBufferTypeSize(buffer); const HRingBufferLenType typeSize = GetRingBufferTypeSize(buffer);
const HRingBufferLenType dataLen = HRingBufferGetUseByteLen(buffer); const HRingBufferLenType startPos = base->start;
len = len / typeSize * typeSize; const HRingBufferLenType endPos = base->end;
len = (len > dataLen) ? dataLen : len; int copyLen = (endPos - startPos) * typeSize;
HRingBufferLenType readLen = 0; if (startPos >= endPos) {
if (base->start >= base->end) { copyLen = (base->len - startPos) * typeSize;
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);
} }
if (len == 0) { if (copyLen > len) {
return readLen; copyLen = len / typeSize * typeSize;
} }
int copySize = (base->end - base->start) * typeSize; if (copyLen == 0) {
if (copySize > len) { return 0;
copySize = len;
} }
memcpy(data, GetRingByteData(buffer, base->start), copySize); memcpy(data, GetRingByteData(buffer, startPos), copyLen);
readLen += copySize; AdjustReadPos(buffer, copyLen / typeSize);
len -= copySize; return copyLen;
AdjustReadPos(buffer, copySize / typeSize);
return readLen;
} }
// 获取环形缓冲区数据长度 // 获取环形缓冲区数据长度

View File

@ -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) { for (uint16_t i = 0; i < sTimeRegisters[id].len; ++i) {
if (sTimeRegisters[id].timers[i].enable == 1) { if (sTimeRegisters[id].timers[i].enable) {
continue; continue;
} }
// 防中断导致数据重叠
sTimeRegisters[id].timers[i].enable = 1; 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].duration = duration;
sTimeRegisters[id].timers[i].lastTime = GetCurrentMs(); sTimeRegisters[id].timers[i].lastTime = GetCurrentMs();
sTimeRegisters[id].timers[i].call = call; sTimeRegisters[id].timers[i].call = call;