feat(ota): ETH口升级兼容方案与升级链路收尾, 软件版本V1.4
- ETH口参考Cat1接入0x7D升级: 下行IsHexText校验/NetUpgradeFeed第一优先/明文直通DebugAnalyze, 升级应答帧主循环最顶部直发 - 升级TX应答队列按通道绑定(TxChan/CurCh): Cat1/ETH各自取回本通道ACK, 双链路互不抢占 - ETH接收改为8KB单生产单消费环形缓冲: 修复IRQ与Rev线程单缓冲竞态丢包 - 升级会话期间ETH状态机旁路: 防RESET/OFF复位模组断链; 会话内纯hex流模式(奇数尾字符跨块拼接) - Public: IsHexText公共化(Cat1/Eth共用), AsciiToHex内部计数器uint16修复(512字符块溢出丢帧) - Cat1: 升级帧带CH_CAT1通道标签, 空闲5分钟保活重连只建链不上传 - 移除全部[ETHDBG]调试打印, 新增MAC不匹配提示日志
This commit is contained in:
@@ -432,18 +432,18 @@
|
|||||||
<Bp>
|
<Bp>
|
||||||
<Number>0</Number>
|
<Number>0</Number>
|
||||||
<Type>0</Type>
|
<Type>0</Type>
|
||||||
<LineNumber>569</LineNumber>
|
<LineNumber>503</LineNumber>
|
||||||
<EnabledFlag>1</EnabledFlag>
|
<EnabledFlag>1</EnabledFlag>
|
||||||
<Address>0</Address>
|
<Address>54178</Address>
|
||||||
<ByteObject>0</ByteObject>
|
<ByteObject>0</ByteObject>
|
||||||
<HtxType>0</HtxType>
|
<HtxType>0</HtxType>
|
||||||
<ManyObjects>0</ManyObjects>
|
<ManyObjects>0</ManyObjects>
|
||||||
<SizeOfObject>0</SizeOfObject>
|
<SizeOfObject>0</SizeOfObject>
|
||||||
<BreakByAccess>0</BreakByAccess>
|
<BreakByAccess>0</BreakByAccess>
|
||||||
<BreakIfRCount>0</BreakIfRCount>
|
<BreakIfRCount>1</BreakIfRCount>
|
||||||
<Filename>..\source\User\Src\CatOneTask.c</Filename>
|
<Filename>..\source\User\Src\CatOneTask.c</Filename>
|
||||||
<ExecCommand></ExecCommand>
|
<ExecCommand></ExecCommand>
|
||||||
<Expression></Expression>
|
<Expression>\\GateWay\../source/User/Src/CatOneTask.c\503</Expression>
|
||||||
</Bp>
|
</Bp>
|
||||||
</Breakpoint>
|
</Breakpoint>
|
||||||
<WatchWindow1>
|
<WatchWindow1>
|
||||||
|
|||||||
@@ -358,6 +358,7 @@ struct GateWay_t{
|
|||||||
int MuchRevCallBack(GateWayPara GateWay, uint8_t *rData, uint16_t rLen);
|
int MuchRevCallBack(GateWayPara GateWay, uint8_t *rData, uint16_t rLen);
|
||||||
int AuchRevCallBack(GateWayPara GateWay, uint8_t *rData, uint16_t rLen);
|
int AuchRevCallBack(GateWayPara GateWay, uint8_t *rData, uint16_t rLen);
|
||||||
uint16_t CRC_Modbus(uint16_t wBase, __IO uint8_t *para, uint16_t length);
|
uint16_t CRC_Modbus(uint16_t wBase, __IO uint8_t *para, uint16_t length);
|
||||||
|
bool IsHexText(char *s, uint16_t len);
|
||||||
uint16_t AsciiToHex(char *ASCData, uint8_t *HexData, uint16_t sLen);
|
uint16_t AsciiToHex(char *ASCData, uint8_t *HexData, uint16_t sLen);
|
||||||
void HexToAscii(uint8_t *HexData, char *ASCData, uint8_t sLen);
|
void HexToAscii(uint8_t *HexData, char *ASCData, uint8_t sLen);
|
||||||
int NetCommOrgData(GateWayPara GateWay, uint8_t *MegData, uint8_t *OutData);
|
int NetCommOrgData(GateWayPara GateWay, uint8_t *MegData, uint8_t *OutData);
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ void Update(uint8_t *PayLoad);
|
|||||||
void UpdateInit(void);
|
void UpdateInit(void);
|
||||||
|
|
||||||
/*Cat1远程升级(0x7D帧)接口 - CatOneTask调用: 固件分包写外部SPI Flash暂存区, 收完置APP_UPDATE_SPI_FLAG复位*/
|
/*Cat1远程升级(0x7D帧)接口 - CatOneTask调用: 固件分包写外部SPI Flash暂存区, 收完置APP_UPDATE_SPI_FLAG复位*/
|
||||||
bool NetUpgradeFeed(uint8_t *data, uint16_t len); //喂入Cat1下行数据片段, 返回true=已被升级模块消费
|
bool NetUpgradeFeed(uint8_t *data, uint16_t len, uint8_t ch); //喂入下行数据片段(带来源通道), 返回true=已被升级模块消费
|
||||||
bool NetUpgradePopTx(uint8_t *Out, uint16_t *OutLen); //取待发应答帧(0x01/0x02, 0x7D原始帧)
|
bool NetUpgradePopTx(uint8_t *Out, uint16_t *OutLen, uint8_t ch); //取本通道待发应答帧(0x01/0x02, 0x7D原始帧)
|
||||||
bool NetUpgradeActive(void); //升级会话进行中
|
bool NetUpgradeActive(void); //升级会话进行中
|
||||||
void NetUpgradeTick(void); //1ms轮询: 超时催发与会话放弃
|
void NetUpgradeTick(void); //1ms轮询: 超时催发与会话放弃
|
||||||
void UpdateFromStash(uint32_t AppSize, uint32_t Crc32); //暂存区校验通过后置标志复位进Boot
|
void UpdateFromStash(uint32_t AppSize, uint32_t Crc32); //暂存区校验通过后置标志复位进Boot
|
||||||
|
|||||||
@@ -488,7 +488,7 @@ void CatOneLoopHandler(void)
|
|||||||
|
|
||||||
case CAT_ONE_WAIT_SEND:
|
case CAT_ONE_WAIT_SEND:
|
||||||
/*Cat1远程升级应答帧优先(0x7D原始帧直发, 绕过0x7A打包)*/
|
/*Cat1远程升级应答帧优先(0x7D原始帧直发, 绕过0x7A打包)*/
|
||||||
if(NetUpgradePopTx(CatOneTxBuff, &CatOneTxLen)) {
|
if(NetUpgradePopTx(CatOneTxBuff, &CatOneTxLen, CH_CAT1)) {
|
||||||
CatSendErrCnt = 0;
|
CatSendErrCnt = 0;
|
||||||
Cat1UpgTxFlag = 1; /*升级应答帧标记*/
|
Cat1UpgTxFlag = 1; /*升级应答帧标记*/
|
||||||
CatOne.Cat1Status = CAT_ONE_SEND_DATA;
|
CatOne.Cat1Status = CAT_ONE_SEND_DATA;
|
||||||
@@ -651,18 +651,6 @@ static void CatOneInit(GateWayPara GateWay)
|
|||||||
GateWay->MuchRevCallBack : GateWay->AuchRevCallBack;
|
GateWay->MuchRevCallBack : GateWay->AuchRevCallBack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*hex文本合法性: 全部字符∈[0-9a-fA-F]且偶数长度(AsciiToHex不校验字符合法性, 非hex明文须先识别直通)*/
|
|
||||||
static bool Cat1IsHexText(char *s, int len)
|
|
||||||
{
|
|
||||||
if(len <= 0 || len % 2 != 0)
|
|
||||||
return false;
|
|
||||||
for(int i = 0; i < len; i++) {
|
|
||||||
char c = s[i];
|
|
||||||
if(!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/*+LIPURC异步事件统一分发: 与AT状态机无关, 任何状态下都能处理升级帧/业务数据*/
|
/*+LIPURC异步事件统一分发: 与AT状态机无关, 任何状态下都能处理升级帧/业务数据*/
|
||||||
/*一批数据包的URC会连发, 多条可能挤进同一缓冲块: 必须循环解析每一条*/
|
/*一批数据包的URC会连发, 多条可能挤进同一缓冲块: 必须循环解析每一条*/
|
||||||
static void CatOneUrcHandle(GateWayPara GateWay, char *RxBuff)
|
static void CatOneUrcHandle(GateWayPara GateWay, char *RxBuff)
|
||||||
@@ -686,7 +674,7 @@ static void CatOneUrcHandle(GateWayPara GateWay, char *RxBuff)
|
|||||||
|
|
||||||
if(sLen > 0) {
|
if(sLen > 0) {
|
||||||
memset(hData, 0x00, sizeof(hData)); /*ASCII hex转二进制(服务器下发为hex文本)*/
|
memset(hData, 0x00, sizeof(hData)); /*ASCII hex转二进制(服务器下发为hex文本)*/
|
||||||
hLen = Cat1IsHexText(rData, sLen) ? AsciiToHex(rData, hData, sLen) : 0;
|
hLen = IsHexText(rData, sLen) ? AsciiToHex(rData, hData, sLen) : 0;
|
||||||
if(hLen == 0) {
|
if(hLen == 0) {
|
||||||
/*非hex明文(如网络调试助手直发命令): 原样直通调试解析, 与ETH口明文直通一致*/
|
/*非hex明文(如网络调试助手直发命令): 原样直通调试解析, 与ETH口明文直通一致*/
|
||||||
hLen = (sLen < (int)sizeof(hData)) ? sLen : (int)sizeof(hData) - 1;
|
hLen = (sLen < (int)sizeof(hData)) ? sLen : (int)sizeof(hData) - 1;
|
||||||
@@ -695,7 +683,7 @@ static void CatOneUrcHandle(GateWayPara GateWay, char *RxBuff)
|
|||||||
}
|
}
|
||||||
CatSendErrCnt = 0;
|
CatSendErrCnt = 0;
|
||||||
Cat1RevErrCnt = 0; /*server data arrived: reload watchdog*/
|
Cat1RevErrCnt = 0; /*server data arrived: reload watchdog*/
|
||||||
if(hLen > 0 && NetUpgradeFeed(hData, hLen)) {
|
if(hLen > 0 && NetUpgradeFeed(hData, hLen, CH_CAT1)) {
|
||||||
/*0x7D frame consumed by NetUpgrade*/
|
/*0x7D frame consumed by NetUpgrade*/
|
||||||
}
|
}
|
||||||
else if(hLen > 0 && hData[0] == 0x7A) { /*0x7A业务帧: 按Much/Auch配置分流*/
|
else if(hLen > 0 && hData[0] == 0x7A) { /*0x7A业务帧: 按Much/Auch配置分流*/
|
||||||
|
|||||||
@@ -1,14 +1,30 @@
|
|||||||
#include "EthTask.h"
|
#include "EthTask.h"
|
||||||
#include "Public.h"
|
#include "Public.h"
|
||||||
#include "DebugCmd.h"
|
#include "DebugCmd.h"
|
||||||
|
#include "Update.h"
|
||||||
|
|
||||||
static rt_sem_t EthIRQ_Sem = RT_NULL;
|
static rt_sem_t EthIRQ_Sem = RT_NULL;
|
||||||
static rt_thread_t EthRev_Thread = RT_NULL;
|
static rt_thread_t EthRev_Thread = RT_NULL;
|
||||||
|
|
||||||
static EthTask_t Eth;
|
static EthTask_t Eth;
|
||||||
|
|
||||||
static char EthRxBuff[ETH_RX_LEN_MAX];
|
/*单生产(IRQ)单消费(Rev)环形缓冲: 无锁, 读写指针独立安全; 防Rev处理期间IRQ覆盖丢包*/
|
||||||
static uint16_t EthRxLen;
|
#define ETH_RING_SIZE 8192
|
||||||
|
static uint8_t EthRingBuf[ETH_RING_SIZE];
|
||||||
|
static volatile uint16_t EthRingW = 0, EthRingR = 0;
|
||||||
|
static uint16_t EthRingLen(void)
|
||||||
|
{
|
||||||
|
return (uint16_t)((EthRingW - EthRingR + ETH_RING_SIZE) % ETH_RING_SIZE);
|
||||||
|
}
|
||||||
|
static uint16_t EthRingGet(uint8_t *dst, uint16_t max)
|
||||||
|
{
|
||||||
|
uint16_t n = 0;
|
||||||
|
while(n < max && EthRingR != EthRingW) {
|
||||||
|
dst[n++] = EthRingBuf[EthRingR];
|
||||||
|
EthRingR = (uint16_t)((EthRingR + 1) % ETH_RING_SIZE);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
static uint8_t EthRevTimeOutCnt;
|
static uint8_t EthRevTimeOutCnt;
|
||||||
|
|
||||||
static uint8_t Payload[ETH_RX_LEN_MAX];
|
static uint8_t Payload[ETH_RX_LEN_MAX];
|
||||||
@@ -79,7 +95,6 @@ static int GateWayRegister(uint8_t *TxBuff)
|
|||||||
void EthLoopHandler(void)
|
void EthLoopHandler(void)
|
||||||
{
|
{
|
||||||
rt_err_t result;
|
rt_err_t result;
|
||||||
|
|
||||||
switch(Eth.Status) {
|
switch(Eth.Status) {
|
||||||
case ETH_IDEL:
|
case ETH_IDEL:
|
||||||
rt_thread_delay(1);
|
rt_thread_delay(1);
|
||||||
@@ -156,6 +171,11 @@ void EthLoopHandler(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ETH_WAIT_SEND:
|
case ETH_WAIT_SEND:
|
||||||
|
if(NetUpgradePopTx(Eth.TxBuff, &Eth.TxLen, CH_ETH)) { /*升级应答帧第一优先(仅取本通道帧)*/
|
||||||
|
|
||||||
|
Eth.Status = ETH_SEND_DATA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
result = rt_mq_recv(ChannelMQ(*Eth.GateWay, CH_ETH), Payload, ETH_RX_LEN_MAX, 100);
|
result = rt_mq_recv(ChannelMQ(*Eth.GateWay, CH_ETH), Payload, ETH_RX_LEN_MAX, 100);
|
||||||
if(result == RT_EOK) {
|
if(result == RT_EOK) {
|
||||||
Eth.TxLen = NetCommOrgData(Eth.GateWay, Payload, Eth.TxBuff);
|
Eth.TxLen = NetCommOrgData(Eth.GateWay, Payload, Eth.TxBuff);
|
||||||
@@ -188,6 +208,7 @@ void EthLoopHandler(void)
|
|||||||
}
|
}
|
||||||
HexToAscii(Eth.TxBuff, CommUnitSendASCII, Eth.TxLen);
|
HexToAscii(Eth.TxBuff, CommUnitSendASCII, Eth.TxLen);
|
||||||
EthRevTimeOutCnt = 0;
|
EthRevTimeOutCnt = 0;
|
||||||
|
|
||||||
EthUartSend((uint8_t *)CommUnitSendASCII, Eth.TxLen * 2);
|
EthUartSend((uint8_t *)CommUnitSendASCII, Eth.TxLen * 2);
|
||||||
CommUnitSendASCII[Eth.TxLen * 2] = 0;
|
CommUnitSendASCII[Eth.TxLen * 2] = 0;
|
||||||
ETH_DBG_LOG("Eth Send: %s\r\n", CommUnitSendASCII);
|
ETH_DBG_LOG("Eth Send: %s\r\n", CommUnitSendASCII);
|
||||||
@@ -259,13 +280,11 @@ static void EthInit(GateWayPara GateWay)
|
|||||||
|
|
||||||
void EthIrqCallbackHandler(uint8_t rData)
|
void EthIrqCallbackHandler(uint8_t rData)
|
||||||
{
|
{
|
||||||
if(EthRevTimeOutCnt == 0)
|
if((uint16_t)((EthRingW + 1) % ETH_RING_SIZE) != EthRingR) { /*未满才入, IRQ不阻塞*/
|
||||||
EthRxLen = 0;
|
EthRingBuf[EthRingW] = rData;
|
||||||
|
EthRingW = (uint16_t)((EthRingW + 1) % ETH_RING_SIZE);
|
||||||
if(EthRxLen < ETH_RX_LEN_MAX) {
|
|
||||||
EthRxBuff[EthRxLen++] = rData;
|
|
||||||
}
|
}
|
||||||
|
/*强制入环: 满时覆盖旧数据, IRQ永不阻塞*/
|
||||||
EthRevTimeOutCnt = 3;
|
EthRevTimeOutCnt = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +293,7 @@ void EthOverHandler(void)
|
|||||||
if(EthRevTimeOutCnt > 0)
|
if(EthRevTimeOutCnt > 0)
|
||||||
EthRevTimeOutCnt--;
|
EthRevTimeOutCnt--;
|
||||||
|
|
||||||
if(EthRxLen > 0 && EthRevTimeOutCnt == 0) {
|
if(EthRingLen() > 0 && EthRevTimeOutCnt == 0) {
|
||||||
EthRevTimeOutCnt = 20;
|
EthRevTimeOutCnt = 20;
|
||||||
rt_sem_release(EthIRQ_Sem);
|
rt_sem_release(EthIRQ_Sem);
|
||||||
}
|
}
|
||||||
@@ -292,24 +311,59 @@ static void EthRev_Thread_Entry(void *parameter)
|
|||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
result = rt_sem_take(EthIRQ_Sem, 500);
|
result = rt_sem_take(EthIRQ_Sem, 500);
|
||||||
if(result == RT_EOK || EthRxLen > 1) {
|
uint16_t n = EthRingLen();
|
||||||
if(EthRxLen == 0) continue;
|
if(result == RT_EOK || n > 1) {
|
||||||
memcpy(RxBuffTemp, EthRxBuff, EthRxLen);
|
if(n == 0) continue;
|
||||||
RxBuffTemp[EthRxLen] = 0;
|
n = EthRingGet((uint8_t *)RxBuffTemp, ETH_RX_LEN_MAX - 1);
|
||||||
memset(HexData, 0x00, EthRxLen / 2);
|
RxBuffTemp[n] = 0;
|
||||||
uint16_t ret = AsciiToHex(RxBuffTemp, HexData, EthRxLen);
|
uint16_t ret = 0;
|
||||||
if(ret > 0 && HexData[0] == 0x7A) {
|
if(NetUpgradeActive()) {
|
||||||
|
/*升级会话: 纯hex流模式, 奇数尾字符跨块拼接(模组512字节透传块会切在帧任意位置)*/
|
||||||
|
static char hexTail = 0;
|
||||||
|
static bool tailV = false;
|
||||||
|
if(tailV && n < ETH_RX_LEN_MAX) {
|
||||||
|
memmove(&RxBuffTemp[1], RxBuffTemp, n);
|
||||||
|
RxBuffTemp[0] = hexTail;
|
||||||
|
n++; tailV = false;
|
||||||
|
} else { tailV = false; }
|
||||||
|
if(n % 2 == 1) { hexTail = RxBuffTemp[n - 1]; tailV = true; n--; }
|
||||||
|
RxBuffTemp[n] = 0;
|
||||||
|
if(n > 0 && IsHexText(RxBuffTemp, n)) {
|
||||||
|
memset(HexData, 0x00, ETH_RX_LEN_MAX / 2);
|
||||||
|
ret = AsciiToHex(RxBuffTemp, HexData, n);
|
||||||
|
bool fed = (ret > 0) ? NetUpgradeFeed(HexData, ret, CH_ETH) : false;
|
||||||
|
/*注意: 会话内禁止全量hex打印, 串口打印阻塞EthRev线程导致USART RX缓冲溢出丢包*/
|
||||||
|
|
||||||
|
if(fed) Eth.SendNoDataCnt = 0; /*清看门狗防升级会话被复位*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*非会话: hex业务帧/明文命令分流(0x81握手在此分支进入升级模块)*/
|
||||||
|
memset(HexData, 0x00, n / 2);
|
||||||
|
bool hexv = IsHexText(RxBuffTemp, n);
|
||||||
|
if(hexv) {
|
||||||
|
ret = AsciiToHex(RxBuffTemp, HexData, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool fed = (ret > 0) ? NetUpgradeFeed(HexData, ret, CH_ETH) : false;
|
||||||
|
|
||||||
|
if(fed) {
|
||||||
|
Eth.SendNoDataCnt = 0;
|
||||||
|
}
|
||||||
|
else if(ret > 0 && HexData[0] == 0x7A) {
|
||||||
Eth.SendNoDataCnt = 0;
|
Eth.SendNoDataCnt = 0;
|
||||||
if(GateWay->ConfigPara.Much == CH_ETH)
|
if(GateWay->ConfigPara.Much == CH_ETH)
|
||||||
GateWay->MuchRevCallBack(GateWay, HexData, ret);
|
GateWay->MuchRevCallBack(GateWay, HexData, ret);
|
||||||
else
|
else
|
||||||
GateWay->AuchRevCallBack(GateWay, HexData, ret);
|
GateWay->AuchRevCallBack(GateWay, HexData, ret);
|
||||||
}
|
}
|
||||||
else if(EthRxLen > 1) {
|
else if(n > 1) {
|
||||||
DebugAnalyze(GateWay, (uint8_t *)RxBuffTemp, EthRxLen);
|
DebugAnalyze(GateWay, (uint8_t *)RxBuffTemp, n);
|
||||||
}
|
}
|
||||||
memset(EthRxBuff, 0x00, ETH_RX_LEN_MAX);
|
}
|
||||||
EthRxLen = 0;
|
if(EthRingLen() > 0)
|
||||||
|
rt_sem_release(EthIRQ_Sem); /*缓冲仍有数据: 自释放信号量连续泵空*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,8 +393,20 @@ void Eth_Thread_Entry(void *parameter)
|
|||||||
rt_kprintf("Eth Thread is running!\r\n");
|
rt_kprintf("Eth Thread is running!\r\n");
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
|
/*升级会话应答帧: 最高优先直发, 不依赖通道配置/LINK状态/状态机(ACK原路CH_ETH返回)*/
|
||||||
|
if(NetUpgradeActive() && NetUpgradePopTx(Eth.TxBuff, &Eth.TxLen, CH_ETH)) {
|
||||||
|
HexToAscii(Eth.TxBuff, CommUnitSendASCII, Eth.TxLen);
|
||||||
|
CommUnitSendASCII[Eth.TxLen * 2] = 0;
|
||||||
|
|
||||||
|
EthUartSend((uint8_t *)CommUnitSendASCII, Eth.TxLen * 2);
|
||||||
|
}
|
||||||
if(!ChannelIsActive(GateWay->ConfigPara, CH_ETH)) {
|
if(!ChannelIsActive(GateWay->ConfigPara, CH_ETH)) {
|
||||||
rt_thread_delay(100);
|
rt_thread_delay(20);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(NetUpgradeActive()) {
|
||||||
|
/*升级会话: 状态机旁路(防RESET/OFF复位模组断链), 应答走主循环直发+接收线程收包*/
|
||||||
|
rt_thread_delay(5);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
EthLoopHandler();
|
EthLoopHandler();
|
||||||
|
|||||||
@@ -126,10 +126,28 @@ void HexToAscii(uint8_t *HexData, char *ASCData, uint8_t sLen)
|
|||||||
sLen, 需要转的字符串长度
|
sLen, 需要转的字符串长度
|
||||||
* 返 回 值: 无
|
* 返 回 值: 无
|
||||||
*****************************************************************************************/
|
*****************************************************************************************/
|
||||||
|
/*****************************************************************************************
|
||||||
|
* 函数名称: IsHexText
|
||||||
|
* 功能描述: 判断缓冲区内容是否为合法hex文本(AsciiToHex不校验字符合法性, 非hex明文须先识别)
|
||||||
|
* 参 数: s, 待判断字符串; len, 字符长度
|
||||||
|
* 返 回 值: true=合法hex文本(全字符∈[0-9a-fA-F]且偶数长度)
|
||||||
|
*****************************************************************************************/
|
||||||
|
bool IsHexText(char *s, uint16_t len)
|
||||||
|
{
|
||||||
|
if(len == 0 || len % 2 != 0)
|
||||||
|
return false;
|
||||||
|
for(uint16_t i = 0; i < len; i++) {
|
||||||
|
char c = s[i];
|
||||||
|
if(!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t AsciiToHex(char *ASCData, uint8_t *HexData, uint16_t sLen)
|
uint16_t AsciiToHex(char *ASCData, uint8_t *HexData, uint16_t sLen)
|
||||||
{
|
{
|
||||||
char chr;
|
char chr;
|
||||||
uint8_t HexLen = 0;
|
uint16_t HexLen = 0; /*uint16: 大块(512字符=256字节)时uint8溢出归0导致ret=0丢帧*/
|
||||||
|
|
||||||
if(sLen % 2 == 1)
|
if(sLen % 2 == 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -103,7 +103,9 @@ static struct {
|
|||||||
uint32_t ErrCnt; //连续超时次数
|
uint32_t ErrCnt; //连续超时次数
|
||||||
uint8_t TxQ[4][40]; //应答帧队列(0x01/0x02连发互不挤占)
|
uint8_t TxQ[4][40]; //应答帧队列(0x01/0x02连发互不挤占)
|
||||||
uint8_t TxQLen[4];
|
uint8_t TxQLen[4];
|
||||||
uint8_t TxHead; //队首索引(出队)
|
uint8_t TxHead;
|
||||||
|
uint8_t TxChan[4]; /*每帧来源通道: ACK从收到0x81的通道原路返回*/
|
||||||
|
uint8_t CurCh; /*当前会话通道: Feed进入时记录*/ //队首索引(出队)
|
||||||
uint8_t TxCnt; //队列帧数
|
uint8_t TxCnt; //队列帧数
|
||||||
}Nup;
|
}Nup;
|
||||||
|
|
||||||
@@ -162,6 +164,7 @@ static void NetUpgradePushTx(uint8_t Cmd, uint8_t *Payload, uint8_t Len)
|
|||||||
Nup.TxQ[Tail][9 + Len] = crc & 0xFF;
|
Nup.TxQ[Tail][9 + Len] = crc & 0xFF;
|
||||||
Nup.TxQ[Tail][10 + Len] = (crc >> 8) & 0xFF;
|
Nup.TxQ[Tail][10 + Len] = (crc >> 8) & 0xFF;
|
||||||
Nup.TxQLen[Tail] = 11 + Len;
|
Nup.TxQLen[Tail] = 11 + Len;
|
||||||
|
Nup.TxChan[Tail] = Nup.CurCh; /*绑定来源通道*/
|
||||||
Nup.TxCnt++;
|
Nup.TxCnt++;
|
||||||
}
|
}
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
@@ -305,8 +308,9 @@ static void NetUpgradeFrameHandler(uint8_t Cmd, uint8_t *Payload, uint8_t Len)
|
|||||||
* 参 数: data/len, 二进制数据片段(TCP分片有序)
|
* 参 数: data/len, 二进制数据片段(TCP分片有序)
|
||||||
* 返 回 值: true=数据已被升级模块消费(帧头0x7D); false=非0x7D流, 调用方交还原0x7A路径
|
* 返 回 值: true=数据已被升级模块消费(帧头0x7D); false=非0x7D流, 调用方交还原0x7A路径
|
||||||
*****************************************************************************************/
|
*****************************************************************************************/
|
||||||
bool NetUpgradeFeed(uint8_t *data, uint16_t len)
|
bool NetUpgradeFeed(uint8_t *data, uint16_t len, uint8_t ch)
|
||||||
{
|
{
|
||||||
|
|
||||||
Nup.CurCh = ch; /*记录会话通道*/
|
Nup.CurCh = ch; /*记录会话通道*/
|
||||||
if(NupFrameLen == 0) {
|
if(NupFrameLen == 0) {
|
||||||
uint16_t skip = 0;
|
uint16_t skip = 0;
|
||||||
@@ -350,6 +354,9 @@ bool NetUpgradeFeed(uint8_t *data, uint16_t len)
|
|||||||
broadcast 0x81 is answered by the target device only, other devices drop it silently*/
|
broadcast 0x81 is answered by the target device only, other devices drop it silently*/
|
||||||
if(memcmp(&NupFrameBuf[1], GateWay.ConfigPara.GwMac, 6) == 0) {
|
if(memcmp(&NupFrameBuf[1], GateWay.ConfigPara.GwMac, 6) == 0) {
|
||||||
NetUpgradeFrameHandler(NupFrameBuf[7], &NupFrameBuf[9], NupFrameBuf[8]);
|
NetUpgradeFrameHandler(NupFrameBuf[7], &NupFrameBuf[9], NupFrameBuf[8]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
U_DBG_LOG("NetUpgrade MAC mismatch, check upgrade dialog MAC\r\n");
|
||||||
}
|
}
|
||||||
memmove(NupFrameBuf, &NupFrameBuf[total], NupFrameLen - total);
|
memmove(NupFrameBuf, &NupFrameBuf[total], NupFrameLen - total);
|
||||||
NupFrameLen -= total;
|
NupFrameLen -= total;
|
||||||
@@ -362,29 +369,36 @@ bool NetUpgradeFeed(uint8_t *data, uint16_t len)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
* 函数名称: NetUpgradePopTx
|
/*****************************************************************************************
|
||||||
* 功能描述: 取待发应答帧(0x01 ACK/0x02请求), 由CatOne主循环经AT+LIPSEND直发
|
* 函 数 名: NetUpgradePopTx
|
||||||
* 功 能: 取出本通道应答帧(0x01 ACK/0x02请求), 供CatOne主循环/EthTask经AT+LIPSEND直发
|
* 功 能: 取出本通道应答帧(0x01 ACK/0x02请求), 供CatOne主循环/EthTask经AT+LIPSEND直发
|
||||||
bool NetUpgradePopTx(uint8_t *Out, uint16_t *OutLen)
|
*****************************************************************************************/
|
||||||
bool NetUpgradePopTx(uint8_t *Out, uint16_t *OutLen, uint8_t ch)
|
bool NetUpgradePopTx(uint8_t *Out, uint16_t *OutLen, uint8_t ch)
|
||||||
{
|
{
|
||||||
uint8_t cmdLog = 0;
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if(Nup.TxCnt > 0) {
|
rt_base_t level = rt_hw_interrupt_disable();
|
||||||
cmdLog = Nup.TxQ[Nup.TxHead][7];
|
for(uint8_t idx = 0; idx < Nup.TxCnt; idx++) {
|
||||||
memcpy(Out, Nup.TxQ[Nup.TxHead], Nup.TxQLen[Nup.TxHead]);
|
uint8_t slot = (Nup.TxHead + idx) % 4;
|
||||||
*OutLen = Nup.TxQLen[Nup.TxHead];
|
if(Nup.TxChan[slot] != ch) continue; /*跳过其他通道的帧(Cat1/ETH各自取自己的ACK)*/
|
||||||
Nup.TxHead = (Nup.TxHead + 1) % 4;
|
memcpy(Out, Nup.TxQ[slot], Nup.TxQLen[slot]);
|
||||||
|
*OutLen = Nup.TxQLen[slot];
|
||||||
|
uint8_t keep = Nup.TxCnt - idx - 1; /*slot之后的帧数: 依次前移紧凑*/
|
||||||
|
for(uint8_t m2 = 0; m2 < keep; m2++) {
|
||||||
|
uint8_t curSlot = (slot + m2) % 4;
|
||||||
|
uint8_t nxt = (slot + m2 + 1) % 4;
|
||||||
|
memcpy(Nup.TxQ[curSlot], Nup.TxQ[nxt], 40);
|
||||||
|
Nup.TxChan[curSlot] = Nup.TxChan[nxt];
|
||||||
|
Nup.TxQLen[curSlot] = Nup.TxQLen[nxt];
|
||||||
}
|
}
|
||||||
Nup.TxCnt--;
|
Nup.TxCnt--;
|
||||||
|
ret = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(ret) {
|
|
||||||
U_DBG_LOG("NetUpgrade pop: cmd=0x%02x\r\n", cmdLog);
|
|
||||||
}
|
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
}
|
return ret;
|
||||||
|
}/*****************************************************************************************
|
||||||
|
* 函 数 名: NetUpgradeActive
|
||||||
|
* 功 能: 升级会话状态查询
|
||||||
*****************************************************************************************/
|
*****************************************************************************************/
|
||||||
bool NetUpgradeActive(void)
|
bool NetUpgradeActive(void)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user