optical/NxFuncs/comm/xmodem.c

368 lines
6.3 KiB
C
Raw Permalink Normal View History

2025-09-04 01:45:08 +00:00
#include "xmodem.h"
#include "serial.h"
#include "trigger.h"
#include "shell.h"
#include "delay.h"
//---------------------------------------------------------
#define DEBUG_OK 0
#if (DEBUG_OK == 1)
#define DEBUG_OUT(...) do \
{\
printf(__VA_ARGS__); \
}while(0)
void OutDebugBufInfo(void){};
#elif (DEBUG_OK == 2)
char g_debugbuf[200][50];
int g_debugidx = 0;
#define DEBUG_OUT(...) do \
{\
if (g_debugidx < 200) \
{ \
sprintf((char*)&(g_debugbuf[g_debugidx][0]), __VA_ARGS__); \
g_debugidx++; \
} \
}while(0)
#if (DEBUG_OK == 2)
void OutDebugBufInfo(void)
{
printf("\r\nDebug buff info (%d):\r\n", g_debugidx);
for (int i = 0; i < g_debugidx; i++)
{
printf("%s", (char*)(&g_debugbuf[i][0]));
DelayMs(10);
}
printf("\r\nDebug buff info end\r\n");
g_debugidx = 0;
}
#endif
#else
#define DEBUG_OUT(...) do {}while(0)
void OutDebugBufInfo(void){};
#endif
//---------------------------------------------------------
// <20><><EFBFBD><EFBFBD>xmodem<65><6D>crcֵ
u16 CalcXModemCrc(u8 * pDat, int count)
{
u16 crc;
int i;
crc = 0;
while (--count >= 0)
{
crc = crc ^ (u16) (*pDat++ << 8);
i = 8;
do
{
if (crc & 0x8000)
{
crc = crc << 1 ^ 0x1021; // X16+X12+X5+X0
}
else
{
crc = crc << 1;
}
} while (--i);
}
return (crc);
}
// <20><><EFBFBD><EFBFBD>xmodem<65><6D><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>
int CheckXModemDat(int crcflag, u8 * pBuf, int size)
{
if(crcflag != 0)
{
u16 crc = CalcXModemCrc(pBuf, size);
u16 tcrc = ((u16)(pBuf[size])<<8) + pBuf[size+1];
if (crc == tcrc)
{
return 1;
}
}
else
{
int i = 0;
u8 cks = 0;
for(i = 0; i < size; i++)
{
cks += pBuf[i];
}
if (cks == pBuf[size])
{
return 1;
}
}
return 0;
}
// <20><><EFBFBD><EFBFBD>xmodem<65><6D><EFBFBD><EFBFBD>
int XmodemReceive(XmodemCtrl * pCtrl)
{
int rslt, err, retry, recvsize, exsize;
int timer;
u8 packid, tmpid, temp;
u8 trychar, svchar;
u8 xbuff[XMODEM1K_FRAME_C];
u8 ch;
int crcflag;
int datidx;
trychar = 'C'; // <20><><EFBFBD><EFBFBD>crcУ<63>ʽ
svchar = trychar;
recvsize = 0;
packid = 1;
err = 0;
datidx = 0;
pCtrl->InitSave();
DEBUG_OUT("Start XmodemReceive\r\n");
#define MAX_RETRY 32
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (retry = 0; retry < MAX_RETRY; retry++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
// 1. <20><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD>ֽ<EFBFBD>
if(trychar != 0)
{
xbuff[0] = trychar;
pCtrl->XmodemOutBuff(xbuff, 1);
}
// 2. <20>ȴ<EFBFBD><C8B4>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD>ݰ<EFBFBD>
timer = GetMsSoftTimer(); // <20><>¼ʱ<C2BC><CAB1>
recvsize = 0;
do
{
rslt = pCtrl->XmodemInBuff(xbuff, 1);
if (rslt != 1) // <20>ȵ<EFBFBD><C8B5>ַ<EFBFBD>
{
if (GetMsSoftTimer() - timer > 1000) // <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD><C7B7><EFBFBD>ʱ
{
break;
}
continue;
}
ch = xbuff[0];
switch(ch)
{
case XMODEM_SOH: // Xmodem<65><6D><EFBFBD>ݰ<EFBFBD>ͷ
{
DEBUG_OUT("get soh\r\n");
recvsize = XMODEM_F_SIZE;
break;
}
case XMODEM_STX: // 1K-Xmodem<65><6D><EFBFBD>ݰ<EFBFBD>ͷ
{
DEBUG_OUT("get stx\r\n");
recvsize = XMODEM1K_F_SIZE;
break;
}
case XMODEM_EOT: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
DEBUG_OUT("get eot\r\n");
pCtrl->XmodemCleanBuff(); // <20><><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
xbuff[0] = XMODEM_ACK; // ȷ<>ϻظ<CFBB>
pCtrl->XmodemOutBuff(xbuff, 1);
err = 1;
break;
}
case XMODEM_CAN: // ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
DEBUG_OUT("get can\r\n");
pCtrl->XmodemCleanBuff(); // <20><><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
xbuff[0] = XMODEM_ACK; // ȷ<>ϻظ<CFBB>
pCtrl->XmodemOutBuff(xbuff, 1);
err = -2;
break;
}
default:
{
DEBUG_OUT("get others\r\n");
break;
}
}
break;
}while(1);
if (err == 0)
{
// 3. <20>жϻظ<CFBB><D8B8>Ƿ<EFBFBD><C7B7><EFBFBD>ȷ
if (recvsize == 0) // ͬ<><CDAC><EFBFBD>ֳ<EFBFBD>ʱ
{
if (trychar == 'C')
{
if (retry >= MAX_RETRY-1)
{
trychar = XMODEM_NAK; // <20><>Ϊʹ<CEAA>ú<EFBFBD>У<EFBFBD>ʽ
retry = 0;
}
continue; // <20><><EFBFBD>¿<EFBFBD>ʼ
}
else
{
if (retry >= MAX_RETRY-1)
{
err = -1; // <20>泬ʱ<E6B3AC><CAB1><EFBFBD>˳<EFBFBD>
}
else
{
continue;
}
}
}
if (trychar != 0)
{
DEBUG_OUT("save trychar\r\n");
svchar = trychar;
}
trychar = 0; // <20>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˴<EFBFBD><CBB4><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
if (err == 0 && recvsize != 0)
{
if (svchar == 'C')
{
DEBUG_OUT("exsize = 4\r\n");
exsize = XMODEM_HEAD_SIZE+XMODEM_CRC_SIZE-1;
crcflag = 1;
}
else
{
DEBUG_OUT("exsize = 3\r\n");
exsize = XMODEM_HEAD_SIZE+XMODEM_CHECK_SIZE-1;
crcflag = 0;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD>
timer = GetMsSoftTimer(); // <20><>¼ʱ<C2BC><CAB1>
DEBUG_OUT("timer=%d\r\n", timer);
do
{
rslt = pCtrl->XmodemInBuff(&(xbuff[1]), recvsize+exsize);
if (rslt == recvsize+exsize) // <20>ȵ<EFBFBD><C8B5>ַ<EFBFBD>
{
DEBUG_OUT("get exsize+recvsize=%d+%d\r\n", exsize, recvsize);
tmpid = xbuff[1];
temp = ~(xbuff[2]);
if ((tmpid == temp) &&
(CheckXModemDat(crcflag, &(xbuff[3]), recvsize) != 0))
{
xbuff[0] = XMODEM_ACK; // <20>ظ<EFBFBD>ACK<43><4B>ȷ<EFBFBD>Ͻ<EFBFBD><CFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD>
pCtrl->XmodemOutBuff(xbuff, 1);
DEBUG_OUT("check ok, send ack\r\n");
if (tmpid == packid) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
int svlen;
int svflag = (datidx == 0 ? 0:1);
svlen = pCtrl->SaveData(svflag, &(xbuff[3]), recvsize, pCtrl->savedsize); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (svlen > 0)
{
pCtrl->savedsize += svlen;
}
datidx++;
packid++;
}
retry = 0;
}
else
{
xbuff[0] = XMODEM_NAK; // <20>ظ<EFBFBD> NAK<41><4B><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD>
pCtrl->XmodemOutBuff(xbuff, 1);
DEBUG_OUT("crc err, send NAK\r\n");
}
break;
}
else
{
int tptimer;
// <20><><EFBFBD><EFBFBD>
tptimer = GetMsSoftTimer();
if (tptimer - timer > recvsize*1) // <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD><C7B7><EFBFBD>ʱ
{
DEBUG_OUT("tptimer=%d, timer=%d, gap=%d\r\n", tptimer, timer, tptimer - timer);
rslt = pCtrl->XmodemGetInBuffLen();
if (rslt > 0)
{
pCtrl->XmodemCleanBuff(); // <20><><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
xbuff[0] = XMODEM_NAK; // <20>ظ<EFBFBD> NAK<41><4B><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD>
pCtrl->XmodemOutBuff(xbuff, 1);
DEBUG_OUT("resvlen = %d, send NAK\r\n", rslt);
}
else
{
DEBUG_OUT("not data, error\r\n");
err = -1; // <20><><EFBFBD>ճ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>˳<EFBFBD>
}
DEBUG_OUT("wait timeout\r\n");
break;
}
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD>
}
}
}while(1);
}
else
{
DEBUG_OUT("err != 0 || recvsize == 0\r\n");
break;
}
if (err < 0)
{
DEBUG_OUT("err < 0 sanc cancel\r\n");
xbuff[0] = XMODEM_CAN; // ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pCtrl->XmodemOutBuff(xbuff, 1);
pCtrl->XmodemOutBuff(xbuff, 1);
pCtrl->XmodemOutBuff(xbuff, 1);
break;
}
} // end of for
return err;
}