#include "HDProtocolServer.h" #include "HRingBuffer.h" #include "HDLog.h" #include #include #ifndef HDDelayMs #define HDDelayMs(ms) #endif #define OCCUPIED_MAX (5) struct __attribute__((__packed__)) OccupiedInfo { uint32_t occupyTime; ///< 当前数据占用时间(ms), 用于超时 uint8_t protocol; ///< 占用的协议 uint8_t index; ///< 占用的索引 uint8_t enbale : 1; ///< 是否占用 uint8_t waitOccupy : 1; ///< 是否等待占用 }; struct __attribute__((__packed__)) HScheduleRegisterInfo { HDProtocolReadCallback readCall; ///< 读取回调 HDProtocolWriteCallback writeCall; ///< 写入回调 HDProtocolServerInfo *info; ///< 协议信息 uint8_t infoLen; ///< 协议信息长度 uint8_t useIndex; ///< 当前使用的索引 }; static struct HScheduleRegisterInfo sInfo; static struct OccupiedInfo sOccupiedInfo[OCCUPIED_MAX]; // 判断当前协议是否占用 static uint8_t IsOccupied(uint8_t currIndex, uint8_t protocol, uint8_t *occupiedIndex) { if (currIndex >= OCCUPIED_MAX) { LogE("index[%d] out of range[%d]", currIndex, OCCUPIED_MAX); return 0; } for (int i = 0; i < OCCUPIED_MAX; ++i) { if (sOccupiedInfo[i].enbale == 0) { continue; } if ((sOccupiedInfo[i].protocol & protocol) == 0) { continue; } // 占用索引 if (occupiedIndex != NULL) { *occupiedIndex = i; } if (sOccupiedInfo[i].index == currIndex) { return 0; } sOccupiedInfo[i].waitOccupy = 1; return 1; } return 0; } static void SetOccupied(uint8_t currIndex, uint8_t protocol, uint8_t enable) { if (currIndex >= OCCUPIED_MAX) { LogE("index[%d] out of range[%d]", currIndex, OCCUPIED_MAX); return ; } uint8_t index = OCCUPIED_MAX; for (int i = 0; i < OCCUPIED_MAX; ++i) { if (sOccupiedInfo[i].enbale == 0) { if (index == OCCUPIED_MAX) { index = i; } continue; } // 检查当前索引是否已经使用占用 if (sOccupiedInfo[i].index != currIndex) { continue; } // 如果是关闭的直接关闭掉 if (enable == 0) { sOccupiedInfo[i].enbale = 0; sOccupiedInfo[i].index = 0; sOccupiedInfo[i].protocol = 0; sOccupiedInfo[i].occupyTime = 0; sOccupiedInfo[i].waitOccupy = 0; return ; } sOccupiedInfo[i].protocol = protocol; sOccupiedInfo[i].occupyTime = HDLogGetTime(); return ; } if (enable == 0 || index == OCCUPIED_MAX) { return ; } sOccupiedInfo[index].enbale = 1; sOccupiedInfo[index].index = currIndex; sOccupiedInfo[index].protocol = protocol; sOccupiedInfo[index].occupyTime = HDLogGetTime(); } static void WaitRead(HDProtocolServerInfo *info) { if (info->tmpEnable == 0) { return ; } for (int i = 0; i < info->delayCount; ++i) { for (int j = 0; j < HDPROTOCOL_DELAY_TIMEOUT; ++j) { HDProtocolRun(); if (info->tmpEnable == 0) { break; } // 读取数据的时候触发的紧急读取不要去睡眠 if (info->run == 0) { HDDelayMs(1); } } if (info->tmpEnable == 0) { break; } } info->tmpEnable = 0; } static void ParseReadData(int index, int isTimeout) { sInfo.useIndex = index; const int len = sInfo.readCall(&sInfo.info[index], isTimeout); sInfo.useIndex = sInfo.infoLen; if (len == 0 && sInfo.info[index].tmpEnable) { // 临时路由转发数据 if (sInfo.info[index].tmpReadCount > 0) { --sInfo.info[index].tmpReadCount; } if (sInfo.info[index].tmpReadCount == 0) { sInfo.info[index].tmpEnable = 0; } } if (isTimeout) { sInfo.info[index].tmpEnable = 0; } SetOccupied(index, sInfo.info[index].supportProtocol, len == 0 ? 0 : 1); } void HDProtocolSetCallback(HDProtocolReadCallback readCall, HDProtocolWriteCallback writeCall) { sInfo.readCall = readCall; sInfo.writeCall = writeCall; } void HDProtocolInitInfo(HDProtocolServerInfo *info, uint8_t src, void *data, int dataLen) { if (info == NULL) { return ; } memset(info, 0, sizeof(HDProtocolServerInfo)); info->readBuff = data; HRingbufferInit8(info->readBuff, dataLen); info->delayCount = 1; info->src = src; info->dst = src; } void _HDProtocolSetSupportProtocol(HDProtocolServerInfo *info, int len, ...) { if (info == NULL) { return; } va_list args; va_start(args, len); for (int i = 0; i < len; ++i) { info->supportProtocol |= (1 << va_arg(args, int)); } va_end(args); } void HDProtocolRegisterInit(HDProtocolServerInfo *info, int len) { sInfo.info = info; sInfo.infoLen = len; } uint8_t HDProtocolCurrSend(const void *data, int len) { HDProtocolServerInfo *info = HDProtocolGetCurrInfo(); if (info == NULL) { LogD("curr not read call"); return 0; } WaitRead(info); sInfo.writeCall(info, (const uint8_t *)data, len); return 1; } void HDProtocolSendPort(uint8_t dst, const void *data, int len) { if (sInfo.writeCall == NULL || sInfo.info == NULL) { return; } if (dst >= sInfo.infoLen) { LogE("index[%d] is out of range[%d]", dst, sInfo.infoLen); return; } WaitRead(&sInfo.info[dst]); sInfo.writeCall(&sInfo.info[dst], (const uint8_t *)data, len); } void HDProtocolTmpSend(uint8_t src, uint8_t dst, const void *data, int len, uint8_t needReadCount, uint8_t waitCount) { if (sInfo.writeCall == NULL || sInfo.info == NULL) { return; } if (src >= sInfo.infoLen) { LogE("index[%d] is out of range[%d]", src, sInfo.infoLen); return; } WaitRead(&sInfo.info[src]); sInfo.info[src].tmpEnable = 1; sInfo.info[src].tmpDst = dst; sInfo.info[src].delayCount = waitCount; sInfo.info[src].tmpReadCount = needReadCount; sInfo.writeCall(&sInfo.info[src], (const uint8_t *)data, len); } uint8_t HDProtocolGetDest(HDProtocolServerInfo *info) { if (info == NULL) { return 0; } if (info->tmpEnable) { return info->tmpDst; } return info->dst; } HDProtocolServerInfo *HDProtocolGetCurrInfo() { if (sInfo.useIndex >= sInfo.infoLen) { return NULL; } return &sInfo.info[sInfo.useIndex]; } void HDProtocolRead(uint8_t src, const void *data, int len) { if (sInfo.readCall == NULL || sInfo.info == NULL) { return; } if (src >= sInfo.infoLen) { LogE("index[%d] is out of range[%d]", src, sInfo.infoLen); return; } if (sInfo.info[src].readBuff == NULL) { LogE("readBuff is NULL"); return; } const uint8_t *srcData = (const uint8_t *)data; uint8_t occupy = 0xff; sInfo.info[src].run = 1; for (int i = 0; i < len; ++i) { if (HRingBufferFull(sInfo.info[src].readBuff)) { // 只需要检查一次 if (occupy == 0xff) { occupy = IsOccupied(src, sInfo.info[src].supportProtocol, NULL); } // 检查是否占用 if (occupy == 0) { ParseReadData(src, 0); } } HRingBufferAddDataOver(sInfo.info[src].readBuff, srcData[i]); } sInfo.info[src].run = 0; } void HDProtocolRun() { if (sInfo.readCall == NULL || sInfo.info == NULL) { return; } for (int i = 0; i < sInfo.infoLen; ++i) { if (HRingBufferEmpty(sInfo.info[i].readBuff)) { continue; } if (i >= OCCUPIED_MAX) { LogE("index[%d] is out of range[%d]", i, OCCUPIED_MAX); break; } // 有之前的数据已经占用了, 并且检查是否超时 uint8_t occupiedIndex = OCCUPIED_MAX; if (IsOccupied(i, sInfo.info[i].supportProtocol, &occupiedIndex)) { // 解析被占用, 检查超时 if (HDLogGetTime() - sOccupiedInfo[occupiedIndex].occupyTime <= HDPROTOCOL_OCCUPY_TIMEOUT) { continue; } // 通知协议超时 ParseReadData(occupiedIndex, 1); // 如果还占用, 说明用户那边自己要求继续占用 if (IsOccupied(i, sInfo.info[i].supportProtocol, &occupiedIndex)) { continue; } } uint8_t waitTime = 0; if (occupiedIndex < OCCUPIED_MAX && sOccupiedInfo[occupiedIndex].waitOccupy) { // 还有其他协议等待抢占, 检查时间 if (HDLogGetTime() - sOccupiedInfo[occupiedIndex].occupyTime > HDPROTOCOL_OCCUPY_TIMEOUT) { waitTime = 1; } } ParseReadData(i, waitTime); } }