📄 xmodem.c
字号:
/*------------------------------------------------------------------------- * Filename: xmodem.c * Version: $Id: xmodem.c,v 1.2 2002/01/06 19:02:29 erikm Exp $ * Copyright: Copyright (C) 2001, Hewlett-Packard Company * Author: Christopher Hoover <ch@hpl.hp.com> * Description: xmodem functionality for uploading of kernels * and the like * Created at: Thu Dec 20 01:58:08 PST 2001 *-----------------------------------------------------------------------*//* * xmodem.c: xmodem functionality for uploading of kernels and * the like * * Copyright (C) 2001 Hewlett-Packard Laboratories * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */#ident "$Id: xmodem.c,v 1.2 2002/01/06 19:02:29 erikm Exp $"//#ifdef HAVE_CONFIG_H//# include <blob/config.h>//#endif//#include <blob/errno.h>//#include <blob/serial.h>//#include <blob/util.h>#include <../inc/board.h>#define UART_RD_TMOUT 300000#define TIMEOUT 800#define MAXERRORS 10//5#define serial_write_raw(cc) putch(cc)static int SerialInputBlock(char *buf, unsigned long count, unsigned long timeout){/* unsigned long i; do { i = 0; while(!SerialRxToBuf(buf) && (i++ < UART_RD_TMOUT)); if(i < UART_RD_TMOUT) return 1; //只读一个字符 } while(--timeout); return -1;*/ if(!WaitEventWithTimeout(kbhit, 1, timeout)) { *buf = getch(); return 1; } return 0;}//#include "ser2.c"#define SOH 0x01#define STX 0x02#define EOT 0x04#define ACK 0x06#define NAK 0x15#define CAN 0x18#define BS 0x08/*Cf: http://www.textfiles.com/apple/xmodem http://www.phys.washington.edu/~belonis/xmodem/docxmodem.txt http://www.phys.washington.edu/~belonis/xmodem/docymodem.txt http://www.phys.washington.edu/~belonis/xmodem/modmprot.col*/#undef ERROR#define ERROR(...) do { } while (0)//#define ERROR Uart_Printf//static char blockBuf[1024];static char *blockBuf; //使用指针,去掉copy过程static __inline void WriteByte(char cc) { serial_write_raw(cc); }int ReadByteWithTimeout(unsigned int timeout) { char buf[1]; int n; n = SerialInputBlock(buf, 1, timeout); if (n == 1) return buf[0] & 0xff; else return -1;}static void ReadFlush() { while(ReadByteWithTimeout(1000)>=0);} int XModemReceive(char *bufBase, int bufLen){ unsigned int errors = 0; unsigned int wantBlockNo = 1; unsigned int length = 0; int crc = 1; //use crc by send 'C', use checksum by send NAK char nak = 'C'; int crc_val; unsigned char expectedCksum; blockBuf = bufBase; //将bufBase赋与blockBuf; ERROR("start xmodem!\n"); ReadFlush(); /* Ask for CRC; if we get errors, we will go with checksum */ WriteByte(nak); ERROR("WriteByte(nak)\n"); for (;;) { int blockBegin; int blockNo, blockNoOnesCompl; int blockLength; int cksum = 0; int crcHi = 0; int crcLo = 0; blockBegin = ReadByteWithTimeout(TIMEOUT); if (blockBegin < 0){ ERROR("Read blockBegin timeout!\n"); goto timeout; } nak = NAK; switch (blockBegin) { case SOH: case STX: break; case EOT: WriteByte(ACK); ERROR("WriteByte(ACK): done\n"); goto done; default: ERROR("blockBegin error!\n"); errors--; goto error; } /* block no */ blockNo = ReadByteWithTimeout(TIMEOUT); if (blockNo < 0){ ERROR("blockNo timeout!\n"); goto timeout; } /* block no one's compliment */ blockNoOnesCompl = ReadByteWithTimeout(TIMEOUT); if (blockNoOnesCompl < 0){ ERROR("blockNoOnesCompl timeout!\n"); goto timeout; } if (blockNo != (255 - blockNoOnesCompl)) { ERROR("bad block ones compl\n"); goto error; } blockLength = (blockBegin == SOH) ? 128 : 1024; { int i, j; crc_val = 0; expectedCksum = 0; for (i = 0; i < blockLength; i++) { int cc = ReadByteWithTimeout(TIMEOUT); if (cc < 0){ ERROR(" read block byte timeout!\n"); goto timeout; } blockBuf[i] = cc; //crc 或 checksum 计算加在读数据后 if (crc) { crc_val = crc_val ^ cc << 8; for (j = 0; j < 8; j++) if (crc_val & 0x8000) crc_val = crc_val << 1 ^ 0x1021; else crc_val = crc_val << 1; } else { expectedCksum += cc; } } } if (crc) { crcHi = ReadByteWithTimeout(TIMEOUT); if (crcHi < 0) { ERROR(" read crcHi timeout!\n"); goto timeout; } crcLo = ReadByteWithTimeout(TIMEOUT); if (crcLo < 0) { ERROR(" read crcLo timeout!\n"); goto timeout; } if ((crcHi != ((crc_val>>8) & 0xff)) || (crcLo != (crc_val & 0xff))) { ERROR("crc error!\n"); goto error; } } else { cksum = ReadByteWithTimeout(TIMEOUT); if (cksum < 0){ ERROR(" read chksum timeout!\n"); goto timeout; } if (cksum != expectedCksum) { ERROR("checksum error! \n"); goto error; } } if (blockNo == ((wantBlockNo - 1) & 0xff)) { /* a repeat of the last block is ok, just ignore it. */ /* this also ignores the initial block 0 which is */ /* meta data. */ goto next; } else if (blockNo != (wantBlockNo & 0xff)) { ERROR("unexpected block no! \n"); goto error; } wantBlockNo++; length += blockLength; if (length > bufLen) { ERROR("out of space\n"); goto error; }/* { int i; for (i = 0; i < blockLength; i++) *bufBase++ = blockBuf[i]; }*/ blockBuf += blockLength; //接收成功,指针加上收到字节数next: errors = 0; WriteByte(ACK); ERROR("Receive one block OK!\n"); continue;error:timeout: ERROR("Timeout.\n"); errors++; if (errors == MAXERRORS) { /* Abort */ int i; // if using crc, try again w/o crc if (nak == 'C') { nak = NAK; errors = 0; crc = 0; //use checksum goto timeout; } for (i = 0; i < 5; i ++) WriteByte(CAN); for (i = 0; i < 5; i ++) WriteByte(BS); puts("too many errors; giving up\n"); return -1; } ReadFlush(); WriteByte(nak); ERROR("WriteByte(nak)\n"); }done: ERROR("\nxmodem done.\n"); ReadFlush(); return length;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -