⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmodem.c

📁 XMODEM串口下载代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -