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_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

View File

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

View File

@ -2,6 +2,7 @@
#include "HDProtocolServer.h"
#include "HRingBuffer.h"
// #include "src/sys/inc/HDSystemTask.h"
#include "HDLog.h"
#include <stdarg.h>
#include <string.h>
@ -11,7 +12,8 @@
#define HDDelayMs(ms)
#endif
#define OCCUPIED_MAX (5)
// 占用信息监测, 需要大于协议数量
#define OCCUPIED_MAX (10)
struct __attribute__((__packed__)) OccupiedInfo {
@ -25,6 +27,7 @@ struct __attribute__((__packed__)) OccupiedInfo {
struct __attribute__((__packed__)) HScheduleRegisterInfo {
HDProtocolReadCallback readCall; ///< 读取回调
HDProtocolWriteCallback writeCall; ///< 写入回调
HDProtocolCheckAlarmCallback checkAlarmCall; ///< 检查缓冲区报警回调
HDProtocolServerInfo *info; ///< 协议信息
uint8_t infoLen; ///< 协议信息长度
uint8_t useIndex; ///< 当前使用的索引
@ -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);
// 如果还占用, 说明用户那边自己要求继续占用

View File

@ -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;
const HRingBufferLenType startPos = base->start;
const HRingBufferLenType endPos = base->end;
int copyLen = (endPos - startPos) * typeSize;
if (startPos >= endPos) {
copyLen = (base->len - startPos) * typeSize;
}
memcpy(data, GetRingByteData(buffer, base->start), copySize);
readLen += copySize;
data += copySize;
len -= copySize;
AdjustReadPos(buffer, copySize / typeSize);
if (copyLen > len) {
copyLen = len / typeSize * typeSize;
}
if (len == 0) {
return readLen;
if (copyLen == 0) {
return 0;
}
int copySize = (base->end - base->start) * typeSize;
if (copySize > len) {
copySize = len;
}
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;
}
// 获取环形缓冲区数据长度

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) {
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;