#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 //--------------------------------------------------------- // 计算xmodem的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); } // 检验xmodem数据包的正确性 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; } // 接收xmodem数据 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'; // 先用crc校验方式 svchar = trychar; recvsize = 0; packid = 1; err = 0; datidx = 0; pCtrl->InitSave(); DEBUG_OUT("Start XmodemReceive\r\n"); #define MAX_RETRY 32 // 启动传输 for (retry = 0; retry < MAX_RETRY; retry++) // 尝试启动发送 { // 1. 向发送方发送同步字节 if(trychar != 0) { xbuff[0] = trychar; pCtrl->XmodemOutBuff(xbuff, 1); } // 2. 等待回复数据包 timer = GetMsSoftTimer(); // 记录时间 recvsize = 0; do { rslt = pCtrl->XmodemInBuff(xbuff, 1); if (rslt != 1) // 等到字符 { if (GetMsSoftTimer() - timer > 1000) // 判断是否超时 { break; } continue; } ch = xbuff[0]; switch(ch) { case XMODEM_SOH: // Xmodem数据包头 { DEBUG_OUT("get soh\r\n"); recvsize = XMODEM_F_SIZE; break; } case XMODEM_STX: // 1K-Xmodem数据包头 { DEBUG_OUT("get stx\r\n"); recvsize = XMODEM1K_F_SIZE; break; } case XMODEM_EOT: // 传输结束 { DEBUG_OUT("get eot\r\n"); pCtrl->XmodemCleanBuff(); // 清除已经接收数据 xbuff[0] = XMODEM_ACK; // 确认回复 pCtrl->XmodemOutBuff(xbuff, 1); err = 1; break; } case XMODEM_CAN: // 取消传输 { DEBUG_OUT("get can\r\n"); pCtrl->XmodemCleanBuff(); // 清除已经接收数据 xbuff[0] = XMODEM_ACK; // 确认回复 pCtrl->XmodemOutBuff(xbuff, 1); err = -2; break; } default: { DEBUG_OUT("get others\r\n"); break; } } break; }while(1); if (err == 0) { // 3. 判断回复是否正确 if (recvsize == 0) // 同步字超时 { if (trychar == 'C') { if (retry >= MAX_RETRY-1) { trychar = XMODEM_NAK; // 改为使用和校验方式 retry = 0; } continue; // 重新开始 } else { if (retry >= MAX_RETRY-1) { err = -1; // 真超时,退出 } else { continue; } } } if (trychar != 0) { DEBUG_OUT("save trychar\r\n"); svchar = trychar; } trychar = 0; // 已经启动了传输 } // 传输文件内容 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; } // 接收数据包 timer = GetMsSoftTimer(); // 记录时间 DEBUG_OUT("timer=%d\r\n", timer); do { rslt = pCtrl->XmodemInBuff(&(xbuff[1]), recvsize+exsize); if (rslt == recvsize+exsize) // 等到字符 { 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; // 回复ACK,确认接收到,请求发送下一个数据包 pCtrl->XmodemOutBuff(xbuff, 1); DEBUG_OUT("check ok, send ack\r\n"); if (tmpid == packid) // 保存数据 { int svlen; int svflag = (datidx == 0 ? 0:1); svlen = pCtrl->SaveData(svflag, &(xbuff[3]), recvsize, pCtrl->savedsize); // 保存数据 if (svlen > 0) { pCtrl->savedsize += svlen; } datidx++; packid++; } retry = 0; } else { xbuff[0] = XMODEM_NAK; // 回复 NAK,需要重新传输该数据包 pCtrl->XmodemOutBuff(xbuff, 1); DEBUG_OUT("crc err, send NAK\r\n"); } break; } else { int tptimer; // 接收 tptimer = GetMsSoftTimer(); if (tptimer - timer > recvsize*1) // 判断是否超时 { DEBUG_OUT("tptimer=%d, timer=%d, gap=%d\r\n", tptimer, timer, tptimer - timer); rslt = pCtrl->XmodemGetInBuffLen(); if (rslt > 0) { pCtrl->XmodemCleanBuff(); // 清除已经接收数据 xbuff[0] = XMODEM_NAK; // 回复 NAK,需要重新传输该数据包 pCtrl->XmodemOutBuff(xbuff, 1); DEBUG_OUT("resvlen = %d, send NAK\r\n", rslt); } else { DEBUG_OUT("not data, error\r\n"); err = -1; // 接收超时,退出 } DEBUG_OUT("wait timeout\r\n"); break; } else { // 继续等待 } } }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; // 取消发送 pCtrl->XmodemOutBuff(xbuff, 1); pCtrl->XmodemOutBuff(xbuff, 1); pCtrl->XmodemOutBuff(xbuff, 1); break; } } // end of for return err; }