📄 xmodem.c
字号:
#if !BASIC_BIOS
#include "44b0x.h"
#include "rtc.h"
#include "uart.h"
#include "xmodem.h"
#include "bios.h"
unsigned long g_dwDownLoadState; // the State of FSM
unsigned long g_dwCurrentDataNo; // have received data no.
unsigned char g_ucLastSeqNo; // the last sequence no.
unsigned char g_ucCSended; // C是否已经被对方收到
unsigned long g_dwAllowedMaxLength; // 允许加载的最大长度
unsigned long g_LoadLength; // 加载的实际长度
unsigned char *XMODEM_LoadBuffer;
struct XMODEM_PacketStruct g_SXModemPacket;
// FSM of Xmodem protocol
unsigned long (*( DownLoadFSM[ 5 ] ))( void ) =
{
XMODEM_StartOfHeader,
XMODEM_SequenceNo,
XMODEM_CompOfSeqNo,
XMODEM_Data,
XMODEM_Crc
};
unsigned short XMODEM_CalCRC ( unsigned char *ptr, signed long count )
{
unsigned short crc;
unsigned short iTmp;
unsigned char *cTmp;
crc = 0;
cTmp = ptr;
while( --count >= 0 )
{
crc = (unsigned short )(crc ^((unsigned short)(*cTmp++) << 8 ));
for( iTmp = 0; iTmp < 8; iTmp++ )
{
if ( crc & 0x8000 )
{
crc = (unsigned short )(((unsigned short)( crc << 1 )) ^ CRC16_POLY );
}
else
{
crc = (unsigned short)(crc << 1);
}
}
}
return (unsigned short )( crc & 0xFFFF ) ;
}
/*****************************************************************************/
/* 函数名称: XModemLoad( unsigned char* ucpStartAddr ) */
/* 功能 : 在本函数内实现通过xModem协议程序加载、数据加载 */
/*****************************************************************************/
unsigned long XMODEM_Load( unsigned char *start_addr, unsigned long dwAllowedMem )
{
unsigned long dwReturn = 0;
// Initialize the related variables
g_ucLastSeqNo = 0;
g_dwDownLoadState = START_OF_HEADER;
g_ucCSended = FALSE;
XMODEM_LoadBuffer = start_addr;
g_dwAllowedMaxLength = dwAllowedMem;
g_LoadLength = 0;
while( dwReturn == RETURN_NO_ERR )
{
dwReturn = DownLoadFSM[ g_dwDownLoadState ] ( );
}
if( dwReturn == 0xffffffff )
{
XMODEM_LeaveProcess();
}
return g_LoadLength;
}
/*****************************************************************************/
/* 函数名称: StartOfHeader( ) */
/* 功能 : 处理xModem协议启动标志符 */
/*****************************************************************************/
unsigned long XMODEM_StartOfHeader ( void )
{
unsigned char data;
unsigned char sec;
unsigned long i;
struct reltime time;
RTC_GetTime( &time );
sec = (unsigned char)(time.second - 1);
for( i = 0; i < (TRUE == g_ucCSended ? BIOS_CLI_TERM_TIME : BIOS_CLI_CONFIRM_TIME); )
{
if( FALSE == g_ucCSended )
{
RTC_GetTime( &time );
if( sec != time.second )
{
// 如果第一次进入,就发字符'C'告诉对方准备就绪,同时也启动定时器
UART_putchar( COM0, C );
i++;
sec = time.second;
}
}
if( UART_kbhit( COM0 ))
{
data = (unsigned char)UART_getchar( COM0 );
break;
}
}
if( g_ucCSended == FALSE )
{
if( i >= BIOS_CLI_CONFIRM_TIME )
{
XMODEM_LeaveProcess();
return 1;
}
}
else
{
if( i >= BIOS_CLI_TERM_TIME )
{
UART_putchar( COM0, NAK );
}
}
switch ( data )
{
case SOH: // xModem协议包的开始指示 128
g_ucCSended = TRUE;
g_dwDownLoadState = SEQUENCE_NO;
return RETURN_NO_ERR;
case STX: // 1024
g_ucCSended = TRUE;
g_dwDownLoadState = SEQUENCE_NO;
return RETURN_NO_ERR;
break;
case EOT: // 传送完毕,结束协议处理
UART_putchar( COM0, ACK );
XMODEM_LeaveProcess();
return 1;
case CAN: // 中止传输
XMODEM_LeaveProcess();
return 1;
default:
break;
}
return RETURN_NO_ERR;
}
/*****************************************************************************/
/* 函数名称: SequenceNo(void) */
/* 功能 : 本函数完成对序号字段的接收 */
/*****************************************************************************/
unsigned long XMODEM_SequenceNo ( void )
{
unsigned char data;
unsigned char sec;
unsigned long i;
struct reltime time;
RTC_GetTime( &time );
sec = (unsigned char)(time.second - 1);
for( i = 0 ; i < BIOS_CLI_TERM_TIME; )
{
RTC_GetTime( &time );
if( sec != time.second )
{
i++;
sec = time.second;
}
if( UART_kbhit( COM0 ))
{
data = (unsigned char)UART_getchar( COM0 );
break;
}
}
if( i >= BIOS_CLI_TERM_TIME )
{
UART_putchar( COM0, NAK );
g_dwDownLoadState = START_OF_HEADER;
return RETURN_NO_ERR;
}
g_SXModemPacket.SeqNo = data;
g_dwDownLoadState = COMP_OF_SEQ_NO;
return RETURN_NO_ERR;
}
/*****************************************************************************/
/* 函数名称: CompOfSeqNo(void) */
/* 功能 : 本函数完成对序号校验字段的接收 */
/*****************************************************************************/
unsigned long XMODEM_CompOfSeqNo ( void )
{
unsigned char data;
unsigned char sec;
unsigned long i;
struct reltime time;
RTC_GetTime( &time );
sec = (unsigned char)(time.second - 1);
for( i = 0 ; i < BIOS_CLI_TERM_TIME; )
{
RTC_GetTime( &time );
if( sec != time.second )
{
i++;
sec = time.second;
}
if( UART_kbhit( COM0 ))
{
data = (unsigned char)UART_getchar( COM0 );
break;
}
}
if( i >= BIOS_CLI_TERM_TIME )
{
UART_putchar( COM0, NAK );
g_dwDownLoadState = START_OF_HEADER;
return RETURN_NO_ERR;
}
if( MAX_SEQ_NO - data == g_SXModemPacket.SeqNo )
{
g_SXModemPacket.CmpOfSeqNo = data;
if ( g_SXModemPacket.SeqNo == g_ucLastSeqNo )
{
XMODEM_Purge();
UART_putchar( COM0, ACK );
g_dwDownLoadState = START_OF_HEADER;
return RETURN_NO_ERR;
}
else if ( ( g_SXModemPacket.SeqNo == 0 && g_ucLastSeqNo == MAX_SEQ_NO )
|| g_SXModemPacket.SeqNo == ( g_ucLastSeqNo + 1 ) )
{
g_dwCurrentDataNo = 0;
g_dwDownLoadState = DATA;
return RETURN_NO_ERR;
}
else
{
XMODEM_LeaveProcess();
XMODEM_Purge ();
return 1;
}
}
return RETURN_NO_ERR;
}
/******************************************************************************
* 函数名称: Data(void) *
* 功能 : 本函数完成对数据字段的接收 *
******************************************************************************/
unsigned long XMODEM_Data ( void )
{
unsigned char data;
unsigned char sec;
unsigned long i, k;
struct reltime time;
RTC_GetTime( &time );
sec = time.second;
for( k = 0; k < DATA_NUM_PER_PACKET; k++ )
{
for( i = 0 ; i < BIOS_CLI_TERM_TIME; )
{
RTC_GetTime( &time );
if( sec != time.second )
{
i++;
sec = time.second;
}
if( UART_kbhit( COM0 ))
{
data = (unsigned char)UART_getchar( COM0 );
g_SXModemPacket.Data[ k ] = data;
break;
}
}
if( i >= BIOS_CLI_TERM_TIME )
{
UART_putchar( COM0, NAK );
g_dwDownLoadState = START_OF_HEADER;
return 1;
}
}
g_dwDownLoadState = C_R_C;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -