📄 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 + -