4cf73b5a0f
1. 新增SendNoDataCnt计数器: Much=ETH时每次发送累加, 连续>10次 无任何下行数据回应(0x7A帧)则置MuchRegFlag=false并ETH_RESET复位, 解决服务器在线但不应答时网关一直沉默无感知的问题 2. ETH_WAIT_RECV和ETH_WAIT_SEND检测到物理链路断开时立即清除 MuchRegFlag, 保证重连后强制重新注册, para显示为false 3. ETH_RESET和ETH_OFF时清零SendNoDataCnt, 避免计数器残留 4. 复位后MuchRegFlag=false使ETH_REG_SVR真正等待注册响应并重试, 修复原逻辑中复位后注册流程被MuchRegFlag=true跳过的问题
349 lines
8.2 KiB
C
349 lines
8.2 KiB
C
#include "EthTask.h"
|
|
#include "Public.h"
|
|
#include "DebugCmd.h"
|
|
|
|
static rt_sem_t EthIRQ_Sem = RT_NULL;
|
|
static rt_thread_t EthRev_Thread = RT_NULL;
|
|
|
|
static EthTask_t Eth;
|
|
|
|
static char EthRxBuff[ETH_RX_LEN_MAX];
|
|
static uint16_t EthRxLen;
|
|
static uint8_t EthRevTimeOutCnt;
|
|
|
|
static uint8_t Payload[ETH_RX_LEN_MAX];
|
|
static char CommUnitSendASCII[ETH_RX_LEN_MAX * 2];
|
|
|
|
static bool EthDispEn = false;
|
|
|
|
#define ETH_DBG_LOG(...) { if(EthDispEn) Debug_Printf(__VA_ARGS__);}
|
|
|
|
void ETHOnOff(bool OnOff)
|
|
{
|
|
EthDispEn = OnOff;
|
|
if(OnOff)
|
|
Debug_Printf("\r\nEth Display Enable!\r\n\r\n");
|
|
else
|
|
Debug_Printf("\r\nEth Display Disable!\r\n\r\n");
|
|
}
|
|
|
|
void ETHStop(void)
|
|
{
|
|
Eth.Status = ETH_OFF;
|
|
}
|
|
|
|
void ETHReset(void)
|
|
{
|
|
Eth.Status = ETH_RESET;
|
|
}
|
|
|
|
void ETHTriggerRegister(void)
|
|
{
|
|
Eth.Status = ETH_REG_SVR;
|
|
}
|
|
|
|
static int GateWayRegister(uint8_t *TxBuff)
|
|
{
|
|
uint16_t UnitCommCnt = 0;
|
|
uint8_t *p = &TxBuff[0];
|
|
uint16_t len = 5;
|
|
|
|
if(Eth.GateWay->ConfigPara.Rs485Ch1.CommUnitEnable == true && Eth.GateWay->ConfigPara.Rs485Ch1.Enable == true) {
|
|
UnitCommCnt++;
|
|
memcpy(&p[len], Eth.GateWay->ConfigPara.Rs485Ch1.CUPara.Para.Mac[0], 6);
|
|
len += 6;
|
|
}
|
|
if(Eth.GateWay->ConfigPara.Rs485Ch2.CommUnitEnable == true && Eth.GateWay->ConfigPara.Rs485Ch2.Enable == true) {
|
|
UnitCommCnt++;
|
|
memcpy(&p[len], Eth.GateWay->ConfigPara.Rs485Ch2.CUPara.Para.Mac[0], 6);
|
|
len += 6;
|
|
}
|
|
for(int i = 0; i < COMMUNIT_NUM_MAX; i++) {
|
|
if(Eth.GateWay->ConfigPara.CommUnitArray[i].RegFlag == true) {
|
|
for(int j = 0; j < Eth.GateWay->ConfigPara.CommUnitArray[i].SensorN; j++)
|
|
{
|
|
memcpy(&p[len], Eth.GateWay->ConfigPara.CommUnitArray[i].Mac[j], 6);
|
|
len += 6;
|
|
UnitCommCnt++;
|
|
}
|
|
}
|
|
}
|
|
TxBuff[0] = (len - 3) & 0x00ff;
|
|
TxBuff[1] = ((len - 3) >> 8) & 0x00ff;
|
|
TxBuff[2] = NET_COMM_CMD_REG;
|
|
TxBuff[3] = UnitCommCnt & 0x00ff;
|
|
TxBuff[4] = (UnitCommCnt >> 8) & 0x00ff;
|
|
return len;
|
|
}
|
|
|
|
void EthLoopHandler(void)
|
|
{
|
|
rt_err_t result;
|
|
|
|
switch(Eth.Status) {
|
|
case ETH_IDEL:
|
|
rt_thread_delay(1);
|
|
if(Eth.ResetDelayCnt > 0) {
|
|
Eth.ResetDelayCnt--;
|
|
}
|
|
else {
|
|
Eth.Status = ETH_RESET;
|
|
}
|
|
break;
|
|
|
|
case ETH_RESET:
|
|
ETH_DBG_LOG("ETH Reset!\r\n");
|
|
Eth.SendNoDataCnt = 0;
|
|
ETH_RESET_CLR();
|
|
rt_thread_delay(10);
|
|
ETH_RESET_SET();
|
|
rt_thread_delay(2000);
|
|
Eth.Status = ETH_WAIT_LINK;
|
|
Eth.LinkWaitCnt = 0;
|
|
Eth.FirstRegFlag = true;
|
|
break;
|
|
|
|
case ETH_WAIT_LINK:
|
|
if(Eth.LinkWaitCnt == 0) {
|
|
ETH_DBG_LOG("ETH Waiting for module ready...\r\n");
|
|
rt_thread_delay(2000);
|
|
}
|
|
if(ETH_LINK_GET() == Reset) {
|
|
ETH_DBG_LOG("ETH Link OK!\r\n");
|
|
if(Eth.GateWay->ConfigPara.Much != CH_ETH) {
|
|
GateWayRegister(Payload);
|
|
Eth.TxLen = NetCommOrgData(Eth.GateWay, Payload, Eth.TxBuff);
|
|
HexToAscii(Eth.TxBuff, CommUnitSendASCII, Eth.TxLen);
|
|
CommUnitSendASCII[Eth.TxLen * 2] = 0;
|
|
EthUartSend((uint8_t *)CommUnitSendASCII, Eth.TxLen * 2);
|
|
ETH_DBG_LOG("Eth Send Reg: %s\r\n", CommUnitSendASCII);
|
|
Eth.Status = ETH_WAIT_RECV;
|
|
Eth.RecvTimeoutCnt = 0;
|
|
Eth.SendRetryCnt = 0;
|
|
}
|
|
else {
|
|
Eth.Status = ETH_REG_SVR;
|
|
}
|
|
}
|
|
else {
|
|
Eth.LinkWaitCnt++;
|
|
if(Eth.LinkWaitCnt >= ETH_LINK_WAIT_TIME_MAX) {
|
|
ETH_DBG_LOG("ETH Link Timeout, Reset!\r\n");
|
|
Eth.Status = ETH_OFF;
|
|
}
|
|
rt_thread_delay(1);
|
|
}
|
|
break;
|
|
|
|
case ETH_REG_SVR:
|
|
{
|
|
if(Eth.FirstRegFlag) {
|
|
ETH_DBG_LOG("ETH First Register, waiting for system stable...\r\n");
|
|
rt_thread_delay(ETH_FIRST_REG_DELAY);
|
|
Eth.FirstRegFlag = false;
|
|
Eth.SendRetryCnt = 0;
|
|
}
|
|
|
|
GateWayRegister(Payload);
|
|
Eth.TxLen = NetCommOrgData(Eth.GateWay, Payload, Eth.TxBuff);
|
|
HexToAscii(Eth.TxBuff, CommUnitSendASCII, Eth.TxLen);
|
|
CommUnitSendASCII[Eth.TxLen * 2] = 0;
|
|
EthUartSend((uint8_t *)CommUnitSendASCII, Eth.TxLen * 2);
|
|
ETH_DBG_LOG("Eth Send Reg: %s\r\n", CommUnitSendASCII);
|
|
Eth.Status = ETH_WAIT_RECV;
|
|
Eth.RecvTimeoutCnt = 0;
|
|
}
|
|
break;
|
|
|
|
case ETH_WAIT_SEND:
|
|
result = rt_mq_recv(ChannelMQ(*Eth.GateWay, CH_ETH), Payload, ETH_RX_LEN_MAX, 100);
|
|
if(result == RT_EOK) {
|
|
Eth.TxLen = NetCommOrgData(Eth.GateWay, Payload, Eth.TxBuff);
|
|
Eth.Status = ETH_SEND_DATA;
|
|
}
|
|
else {
|
|
if(Eth.Status == ETH_RESET || Eth.Status == ETH_OFF)
|
|
return;
|
|
if(ETH_LINK_GET() != Reset) {
|
|
ETH_DBG_LOG("ETH Link Lost!\r\n");
|
|
Eth.GateWay->MuchRegFlag = false;
|
|
Eth.Status = ETH_OFF;
|
|
}
|
|
else {
|
|
rt_thread_delay(1);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ETH_SEND_DATA:
|
|
if(Eth.GateWay->ConfigPara.Much == CH_ETH) {
|
|
Eth.SendNoDataCnt++;
|
|
if(Eth.SendNoDataCnt > ETH_SEND_NO_DATA_MAX) {
|
|
ETH_DBG_LOG("ETH has no receive data for a long time, Reset!\r\n");
|
|
Eth.SendNoDataCnt = 0;
|
|
Eth.GateWay->MuchRegFlag = false;
|
|
Eth.Status = ETH_RESET;
|
|
break;
|
|
}
|
|
}
|
|
HexToAscii(Eth.TxBuff, CommUnitSendASCII, Eth.TxLen);
|
|
EthRevTimeOutCnt = 0;
|
|
EthUartSend((uint8_t *)CommUnitSendASCII, Eth.TxLen * 2);
|
|
CommUnitSendASCII[Eth.TxLen * 2] = 0;
|
|
ETH_DBG_LOG("Eth Send: %s\r\n", CommUnitSendASCII);
|
|
|
|
Eth.Status = ETH_WAIT_RECV;
|
|
Eth.RecvTimeoutCnt = 0;
|
|
Eth.SendRetryCnt = 0;
|
|
break;
|
|
|
|
case ETH_WAIT_RECV:
|
|
if(Eth.GateWay->ConfigPara.Much != CH_ETH) {
|
|
Eth.Status = ETH_WAIT_SEND;
|
|
break;
|
|
}
|
|
rt_thread_delay(1);
|
|
Eth.RecvTimeoutCnt++;
|
|
|
|
if(Eth.RecvTimeoutCnt >= ETH_RECV_TIMEOUT_MAX) {
|
|
ETH_DBG_LOG("ETH Recv Timeout!\r\n");
|
|
Eth.SendRetryCnt++;
|
|
if(Eth.SendRetryCnt >= ETH_SEND_RETRY_MAX) {
|
|
ETH_DBG_LOG("ETH Send Retry Max, Reset!\r\n");
|
|
Eth.Status = ETH_OFF;
|
|
}
|
|
else {
|
|
if(Eth.GateWay->MuchRegFlag == false) {
|
|
Eth.Status = ETH_REG_SVR;
|
|
}
|
|
else {
|
|
Eth.Status = ETH_WAIT_SEND;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(ETH_LINK_GET() != Reset) {
|
|
ETH_DBG_LOG("ETH Link Lost During Wait!\r\n");
|
|
Eth.GateWay->MuchRegFlag = false;
|
|
Eth.Status = ETH_OFF;
|
|
}
|
|
|
|
if(Eth.GateWay->MuchRegFlag == true) {
|
|
ETH_DBG_LOG("ETH Register Success!\r\n");
|
|
Eth.Status = ETH_WAIT_SEND;
|
|
Eth.RecvTimeoutCnt = 0;
|
|
Eth.SendRetryCnt = 0;
|
|
}
|
|
|
|
break;
|
|
|
|
case ETH_OFF:
|
|
ETH_DBG_LOG("ETH Power Off!\r\n");
|
|
Eth.SendNoDataCnt = 0;
|
|
Eth.Status = ETH_IDEL;
|
|
Eth.ResetDelayCnt = ETH_RESET_DELAY_TIME_MAX;
|
|
break;
|
|
|
|
default:
|
|
Eth.Status = ETH_RESET;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void EthInit(GateWayPara GateWay)
|
|
{
|
|
memset(&Eth, 0x00, sizeof(EthTask_t));
|
|
Eth.Status = ETH_RESET;
|
|
Eth.GateWay = GateWay;
|
|
}
|
|
|
|
void EthIrqCallbackHandler(uint8_t rData)
|
|
{
|
|
if(EthRevTimeOutCnt == 0)
|
|
EthRxLen = 0;
|
|
|
|
if(EthRxLen < ETH_RX_LEN_MAX) {
|
|
EthRxBuff[EthRxLen++] = rData;
|
|
}
|
|
|
|
EthRevTimeOutCnt = 3;
|
|
}
|
|
|
|
void EthOverHandler(void)
|
|
{
|
|
if(EthRevTimeOutCnt > 0)
|
|
EthRevTimeOutCnt--;
|
|
|
|
if(EthRxLen > 0 && EthRevTimeOutCnt == 0) {
|
|
EthRevTimeOutCnt = 20;
|
|
rt_sem_release(EthIRQ_Sem);
|
|
}
|
|
}
|
|
|
|
static void EthRev_Thread_Entry(void *parameter)
|
|
{
|
|
rt_err_t result;
|
|
char RxBuffTemp[ETH_RX_LEN_MAX];
|
|
uint8_t HexData[ETH_RX_LEN_MAX / 2];
|
|
|
|
GateWayPara GateWay = (GateWayPara)parameter;
|
|
|
|
rt_kprintf("EthRev Thread is running!\r\n");
|
|
|
|
while(1) {
|
|
result = rt_sem_take(EthIRQ_Sem, 500);
|
|
if(result == RT_EOK || EthRxLen > 1) {
|
|
if(EthRxLen == 0) continue;
|
|
memcpy(RxBuffTemp, EthRxBuff, EthRxLen);
|
|
RxBuffTemp[EthRxLen] = 0;
|
|
memset(HexData, 0x00, EthRxLen / 2);
|
|
uint8_t ret = AsciiToHex(RxBuffTemp, HexData, EthRxLen);
|
|
if(ret > 0 && HexData[0] == 0x7A) {
|
|
Eth.SendNoDataCnt = 0;
|
|
if(GateWay->ConfigPara.Much == CH_ETH)
|
|
GateWay->MuchRevCallBack(GateWay, HexData, ret);
|
|
else
|
|
GateWay->AuchRevCallBack(GateWay, HexData, ret);
|
|
}
|
|
else if(EthRxLen > 1) {
|
|
DebugAnalyze(GateWay, (uint8_t *)RxBuffTemp, EthRxLen);
|
|
}
|
|
memset(EthRxBuff, 0x00, ETH_RX_LEN_MAX);
|
|
EthRxLen = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Eth_Thread_Entry(void *parameter)
|
|
{
|
|
GateWayPara GateWay = (GateWayPara)parameter;
|
|
|
|
EthIRQ_Sem = rt_sem_create("ethi_sem", 0, RT_IPC_FLAG_FIFO);
|
|
if(EthIRQ_Sem == RT_NULL) {
|
|
rt_kprintf("EthIRQ Sem Create Failed!\r\n");
|
|
}
|
|
|
|
EthInit(GateWay);
|
|
ETH_RESET_CLR();
|
|
rt_thread_delay(10);
|
|
ETH_RESET_SET();
|
|
|
|
EthRev_Thread = rt_thread_create("EthRev", EthRev_Thread_Entry, parameter, 3000, 3, 20);
|
|
if (EthRev_Thread != RT_NULL) {
|
|
rt_thread_startup(EthRev_Thread);
|
|
}
|
|
else {
|
|
rt_kprintf("EthRev Thread Create Failed! Exit...\r\n");
|
|
return;
|
|
}
|
|
rt_kprintf("Eth Thread is running!\r\n");
|
|
|
|
while(1) {
|
|
if(!ChannelIsActive(GateWay->ConfigPara, CH_ETH)) {
|
|
rt_thread_delay(100);
|
|
continue;
|
|
}
|
|
EthLoopHandler();
|
|
}
|
|
}
|