www.pudn.com > xModem_vxWorks.rar > Drv_Xmodem.c


 
#ifndef __XMODEM_C__ 
#define __XMODEM_C__ 
 
#include "vxWorks.h" 
#include "config.h"                 /* board support configuration header */ 
#include "Typedef.h" 
#include "../Bsp.h" 
#include "Drv_Crc.h" 
#include "Drv_Xmodem.h" 
 
 
//在主机中加载跑不起来可能是因为命令行把字符收过去了。可以测试一下 
_U32 Load_xModemDownLoad ( _U32 startaddr,_U32 *pdwLength) 
{ 
    _U32 iReturn; 
 
    /*====================================================================*/ 
    /*    Initialize the related variables                                */ 
    /*====================================================================*/ 
    g_DecTimer = 0 ; 
    iRepeatTime = 0 ; 
    ucLastSeqNo = 0 ; 
    iDownLoadState = START_OF_HEADER ; 
    szDram = (_U8 *)startaddr; 
    ulLength = 0 ; 
    gucSOHReceived = 0 ; 
    iReturn = 0 ; 
 
    InitCrcTable(); 
    Drv_Print ( "\n\r Please run command \"send file\" of HyperTerminal..." ) ; 
 
 
    /*====================================================================*/ 
    /*    FSM execute looply until the state is END                       */ 
    /*====================================================================*/ 
    while ( (iDownLoadState != END) && (!iReturn) ) 
    { 
        iReturn = DownLoadFSM[ iDownLoadState ] (  ) ; 
        if ( iDownLoadState == END ) 
        { 
            g_DecTimer = 0 ; 
            iRepeatTime = 0 ; 
            ucLastSeqNo = 0 ; 
        } 
    } 
 
    if (ulLength == 0) 
    { 
		return FAILURE; 
	} 
    *pdwLength = ulLength; 
 
    return iReturn; 
} 
 
 
/*========================================================================*/ 
/*                                                                        */ 
/*    Function Name    : StartOfHeader                                    */ 
/*    Function Func.   : The Function for the state START_OF_HEADER       */ 
/*    Input Parameter  : none                                             */ 
/*    Output Parameter : none                                             */ 
/*    Return           : int                                              */ 
/*                       0 : success else failure                         */ 
/*    Call Functions   :                                                  */ 
/*                       1. InChar  (  )                                  */ 
/*                       2. OutChar (  )                                  */ 
/*    Called By        :                                                  */ 
/*                       1. xModemDownLoad (  )                           */ 
/*                                                                        */ 
/*========================================================================*/ 
_U32 Load_xModemStartOfHeader ( void ) 
{ 
    _U8 data ; 
    _U32 ret ; 
    int i; 
    if ( !iRepeatTime ) 
    { 
        /*================================================================*/ 
        /*    if firstly go the state START_OF_HEADER,                    */ 
        /*    then send NAK to tell the sender that the receiver have     */ 
        /*    been ready, and set the timeout timer                       */ 
        /*================================================================*/ 
        data = OUTCC ; 
        ret  = Drv_DbgSerialOutChar(data); 
        g_DecTimer = WAITFORSOH ; 
        iRepeatTime ++ ; 
 
        return SUCCESS ; 
    } 
 
    /*====================================================================*/ 
    /* receive the data, if the data is :                                 */ 
    /*    SOH   ---- indicate the start of Xmodem packet                  */ 
    /*    EOT   ---- indicate the end of transfer                         */ 
    /*    CAN   ---- transmiter end the transmition                       */ 
    /*    other ---- discard                                              */ 
    /*====================================================================*/ 
    ret = Drv_DbgSerialInChar(&data); 
    if ( !ret ) 
    { 
        switch ( data ) 
        { 
            case SOH : 
                gucSOHReceived = 1 ; 
                g_DecTimer = 0 ; 
                iRepeatTime = 0 ; 
                iDownLoadState = SEQUENCE_NO ; 
                return SUCCESS ; 
 
            case EOT : 
                data = ACK ; 
                ret = Drv_DbgSerialOutChar(data); 
                g_DecTimer = 0 ; 
                iRepeatTime = 0 ; 
                iDownLoadState = END ; 
                return SUCCESS ; 
 
            case CAN : 
                g_DecTimer = 0 ; 
                iRepeatTime = 0 ; 
                iDownLoadState = END ; 
                return FAILURE; 
 
            case 0x03 :    /* 'Ctrl+c' exit to reboot TA */ 
                g_DecTimer = 0 ; 
                iRepeatTime = 0 ; 
                iDownLoadState = END ; 
                Drv_Print ( "\n\r Download stoped! now rebooting system..."); 
                for(i=0;i<5000;i++) 
                { 
                } 
 
                return FAILURE; 
 
            default : 
                break ; 
        } 
    } 
 
    /*====================================================================*/ 
    /*    If timeout , then retry , if retry time is 10, then error       */ 
    /*====================================================================*/ 
    if ( !g_DecTimer ) 
    { 
        if ( (iRepeatTime < MAXREPEATTIME_FOR_FIRST_FRAME)&&(gucSOHReceived == 0) ) 
        { 
            data = OUTCC ; 
            ret  = Drv_DbgSerialOutChar(data); 
 
            iRepeatTime ++ ; 
            g_DecTimer = WAITFORSOH ; 
 
            return SUCCESS ; 
        } 
        else 
        if( (iRepeatTime < MAXREPEATTIME_FOR_FIRST_FRAME)&&(gucSOHReceived == 1) ) 
        { 
            if( !(iRepeatTime%5) ) 
            { 
	            data = NAK ; 
                ret  = Drv_DbgSerialOutChar(data); 
	            g_DecTimer = WAITFORSOH ; 
            } 
            iRepeatTime ++ ; 
            return SUCCESS ; 
        } 
        else 
        { 
            g_DecTimer = 0 ; 
            iRepeatTime = 0 ; 
 
            iDownLoadState = END ; 
 
            return FAILURE; 
        } 
    } 
 
    return SUCCESS ; 
} 
 
/*========================================================================*/ 
/*                                                                        */ 
/*    Function Name    : SequenceNo                                       */ 
/*    Function Func.   : The Function for the state SEQUNCE_NO            */ 
/*    Created By       : YanJunQing                                       */ 
/*    Creation Date    : 1997, 1                                          */ 
/*    Input Parameter  : none                                             */ 
/*    Output Parameter : none                                             */ 
/*    Return           : int                                              */ 
/*                       0 : success else failure                         */ 
/*    Call Functions   :                                                  */ 
/*                       1. InChar  (  )                                  */ 
/*    Called By        :                                                  */ 
/*                       1. xModemDownLoad (  )                           */ 
/*                                                                        */ 
/*========================================================================*/ 
_U32 Load_xModemSequenceNo ( void ) 
{ 
    _U8 data ; 
    _U32 ret ; 
 
    /*====================================================================*/ 
    /*   if firstly go to the state SEQUNCE_NO, then set the timout timer */ 
    /*====================================================================*/ 
    if ( !iRepeatTime ) 
    { 
        g_DecTimer = WAITFORDATA ; 
        iRepeatTime ++ ; 
 
        return SUCCESS ; 
    } 
 
    /*====================================================================*/ 
    /*    if can receive the data , then go to the state COMP_OF_SEQ_NO   */ 
    /*====================================================================*/ 
    ret  = Drv_DbgSerialInChar(&data); 
    if ( !ret ) 
    { 
        XModemPacket.ucSeqNo = data ; 
 
        g_DecTimer = 0 ; 
        iRepeatTime = 0 ; 
 
        iDownLoadState = COMP_OF_SEQ_NO ; 
 
        return SUCCESS ; 
    } 
 
    /*====================================================================*/ 
    /*    if timeout, then retry,                                         */ 
    /*    if retry time is 10, then search the SOH again                  */ 
    /*====================================================================*/ 
    if ( !g_DecTimer ) 
    { 
        if ( iRepeatTime < MAXREPEATTIME ) 
        { 
            g_DecTimer = WAITFORDATA ; 
            iRepeatTime ++ ; 
 
            return SUCCESS ; 
        } 
        else 
        { 
            data = NAK ; 
            ret  = Drv_DbgSerialOutChar(data); 
 
            g_DecTimer = 0 ; 
            iRepeatTime = 0 ; 
 
            iDownLoadState = START_OF_HEADER ; 
 
            return FAILURE; 
        } 
    } 
 
    return SUCCESS; 
} 
 
/*========================================================================*/ 
/*                                                                        */ 
/*    Function Name    : CompOfSeqNo                                      */ 
/*    Function Func.   : The Function for the state COMP_OF_SEQ_NO        */ 
/*    Input Parameter  : none                                             */ 
/*    Output Parameter : none                                             */ 
/*    Return           : int                                              */ 
/*                       0 : success else failure                         */ 
/*    Call Functions   :                                                  */ 
/*                       1. InChar  (  )                                  */ 
/*                       2. OutChar (  )                                  */ 
/*                       3. Purge    (  )                                 */ 
/*    Called By        :                                                  */ 
/*                       1. xModemDownLoad (  )                           */ 
/*                                                                        */ 
/*========================================================================*/ 
_U32 Load_xModemCompOfSeqNo ( void ) 
{ 
    _U8 data ; 
    _U32 ret ; 
 
    /*====================================================================*/ 
    /*    if firstly go to the state COMP_OF_SEQ_NO ,                     */ 
    /*    then set the timeout timer                                      */ 
    /*====================================================================*/ 
    if ( !iRepeatTime ) 
    { 
        g_DecTimer = WAITFORDATA ; 
        iRepeatTime ++ ; 
 
        return SUCCESS ; 
    } 
 
    /*====================================================================*/ 
    /*    if receive the correct compensate of sequence no ,              */ 
    /*    then if the sequence no is :                                    */ 
    /*         the last sequence no : send ACK , search the SOH again     */ 
    /*         the expexted sequence no : begin to receive data           */ 
    /*         other case : send CAN, end the transfer                    */ 
    /*    else clear the COM ports, search the SOH again                  */ 
    /*====================================================================*/ 
    ret = Drv_DbgSerialInChar(&data); 
    if ( !ret ) 
    { 
        if ( CompensateTo255( data ) == XModemPacket.ucSeqNo ) 
        { 
            if ( XModemPacket.ucSeqNo == ucLastSeqNo ) 
            { 
                Load_xModemPurge (  ) ; 
 
                data = ACK ; 
                ret  = Drv_DbgSerialOutChar(data); 
 
                g_DecTimer = 0 ; 
                iRepeatTime = 0 ; 
 
                iDownLoadState = START_OF_HEADER ; 
 
                return SUCCESS ; 
            } 
            else if ( ( XModemPacket.ucSeqNo == 0 && ucLastSeqNo == MAXSEQNO ) 
                              || XModemPacket.ucSeqNo == ( ucLastSeqNo + 1 ) ) 
            { 
                g_DecTimer = 0 ; 
                iRepeatTime = 0 ; 
                iCurrentData = 0 ; 
                iDownLoadState = DATA ; 
 
                return SUCCESS; 
            } 
            else 
            { 
                Load_xModemPurge (  ) ; 
 
                data = CAN ; 
                ret  = Drv_DbgSerialOutChar(data); 
 
                data = CAN ; 
                ret  = Drv_DbgSerialOutChar(data); 
 
                iDownLoadState = END ; 
 
                return FAILURE; 
            } 
        } 
        else 
        { 
            Load_xModemPurge (  ) ; 
 
            data = NAK ; 
            ret  = Drv_DbgSerialOutChar(data); 
 
            g_DecTimer = 0 ; 
            iRepeatTime = 0 ; 
 
            iDownLoadState = START_OF_HEADER ; 
 
            return FAILURE ; 
        } 
    } 
 
    /*====================================================================*/ 
    /*    if timout, then retry,                                          */ 
    /*    if retry time is 10, then search the SOH again                  */ 
    /*====================================================================*/ 
    if ( !g_DecTimer ) 
    { 
        if ( iRepeatTime < MAXREPEATTIME ) 
        { 
            g_DecTimer = WAITFORDATA ; 
            iRepeatTime ++ ; 
 
            return SUCCESS ; 
        } 
        else 
        { 
            data = NAK ; 
            ret  = Drv_DbgSerialOutChar(data); 
 
            g_DecTimer = 0 ; 
            iRepeatTime = 0 ; 
 
            iDownLoadState = START_OF_HEADER ; 
 
            return FAILURE ; 
        } 
    } 
 
    return SUCCESS ; 
} 
 
/*========================================================================*/ 
/*                                                                        */ 
/*    Function Name    : Data                                             */ 
/*    Function Func.   : The Function for the state DATA                  */ 
/*    Input Parameter  : none                                             */ 
/*    Output Parameter : none                                             */ 
/*    Return           : int                                              */ 
/*                       0 : success else failure                         */ 
/*    Call Functions   :                                                  */ 
/*                       1. InChar  (  )                                  */ 
/*                       2. OutChar (  )                                  */ 
/*    Called By        :                                                  */ 
/*                       1. xModemDownLoad (  )                           */ 
/*                                                                        */ 
/*========================================================================*/ 
_U32 Load_xModemData ( void ) 
{ 
    _U8 data ; 
    _U32 ret ; 
 
    /*====================================================================*/ 
    /*    if firstly go to the state DATA, then set the timeout timer     */ 
    /*====================================================================*/ 
    if ( !iRepeatTime ) 
    { 
        g_DecTimer = WAITFORDATA ; 
        iRepeatTime ++ ; 
 
        return SUCCESS ; 
    } 
 
    /*====================================================================*/ 
    /*    if can receive data, then record the data                       */ 
    /*    if received data's no is MAXDATANO, then receive the CRC        */ 
    /*    else continue receive data                                      */ 
    /*====================================================================*/ 
    ret = Drv_DbgSerialInChar(&data); 
    if ( !ret ) 
    { 
        XModemPacket.ucData[ iCurrentData ++ ] = data ; 
 
        g_DecTimer = 0 ; 
        iRepeatTime = 0 ; 
 
        if ( iCurrentData == MAXDATANO ) 
        { 
            iCurrentCRC = 0; 
            iDownLoadState = C_R_C ; 
        } 
 
        return SUCCESS ; 
    } 
 
    /*====================================================================*/ 
    /*    if timeout, then retry,                                         */ 
    /*    if retry time is 10, then send C , search the SOH again         */ 
    /*====================================================================*/ 
    if ( !g_DecTimer ) 
    { 
        if ( iRepeatTime < MAXREPEATTIME ) 
        { 
            g_DecTimer = WAITFORDATA ; 
            iRepeatTime ++ ; 
 
            return SUCCESS ; 
        } 
        else 
        { 
            g_DecTimer = 0 ; 
            iRepeatTime = 0 ; 
 
            data = NAK ; 
            ret  = Drv_DbgSerialOutChar(data); 
 
            iDownLoadState = START_OF_HEADER ; 
 
            return FAILURE; 
        } 
    } 
 
    return SUCCESS ; 
} 
 
/*========================================================================*/ 
/*                                                                        */ 
/*    Function Name    : CRC                                              */ 
/*    Function Func.   : The Function for the state C_R_C                 */ 
/*    Input Parameter  : none                                             */ 
/*    Output Parameter : none                                             */ 
/*    Return           : int                                              */ 
/*                       0 : success else failure                         */ 
/*    Call Functions   :                                                  */ 
/*                       1. InChar  (  )                                  */ 
/*                       2. OutChar (  )                                  */ 
/*                       3. CalCRC   (  )                                 */ 
/*    Called By        :                                                  */ 
/*                       1. xModemDownLoad (  )                           */ 
/*                                                                        */ 
/*========================================================================*/ 
_U32 Load_xModemCRC ( void ) 
{ 
    _U8  data ; 
    _U16 uCRC ; 
    _U32  ret ; 
 
    /*====================================================================*/ 
    /*    if firstly go to the state C_R_C, then set the timeout timer    */ 
    /*====================================================================*/ 
    if ( !iRepeatTime ) 
    { 
        g_DecTimer = WAITFORDATA ; 
        iRepeatTime ++ ; 
 
        return SUCCESS ; 
    } 
 
    /*====================================================================*/ 
    /*    if can receive two data, then record and cmpare with CRC        */ 
    /*    calculated , if equal , then transfer ok, else have error,      */ 
    /*    send C,  search the SOH again                                   */ 
    /*====================================================================*/ 
    ret = Drv_DbgSerialInChar(&data); 
    if ( !ret ) 
    { 
        #if BIG_ENDIAN 
        XModemPacket.ucCRC[ iCurrentCRC++ ] = data ; 
        #else 
        int iCRC ; 
 
        iCRC = MAXCRCNO - iCurrentCRC - 1 ; 
        iCurrentCRC ++ ; 
        XModemPacket.ucCRC[ iCRC ] = data ; 
        #endif 
 
        g_DecTimer = 0 ; 
        iRepeatTime = 0 ; 
 
        if ( iCurrentCRC == MAXCRCNO ) 
        { 
            memcpy ( ( _U8 * )&uCRC, ( _U8 * ) XModemPacket.ucCRC, MAXCRCNO ) ; 
 
            if ( uCRC != CalcCrc ( XModemPacket.ucData, MAXDATANO ) ) 
            { 
                data = NAK ; 
                ret  = Drv_DbgSerialOutChar(data); 
            } 
            else 
            { 
                if( ulLength >= PROGRAM_MAX_LENGTH - MAXDATANO ) 
                { 
                    iDownLoadState = END ; 
                    ulLength = PROGRAM_MAX_LENGTH + 128 ; 
 
                    /*返回正确实际上是为了在外部函数对长度进行判断之后提示长度溢出*/ 
                    return OK ; 
                } 
                memcpy ( szDram, ( _U8 * ) XModemPacket.ucData, MAXDATANO ) ; 
                szDram += MAXDATANO ; 
                ulLength += MAXDATANO ; 
 
                data = ACK ; 
                ret  = Drv_DbgSerialOutChar(data); 
 
                ucLastSeqNo = XModemPacket.ucSeqNo ; 
 
            } 
 
            iDownLoadState = START_OF_HEADER ; 
        } 
 
        return SUCCESS ; 
    } 
 
    /*====================================================================*/ 
    /*    if timeout, then retry,                                         */ 
    /*    if retry time is 10, then send the C, search the SOH again      */ 
    /*====================================================================*/ 
    if ( !g_DecTimer ) 
    { 
        if ( iRepeatTime < MAXREPEATTIME ) 
        { 
            g_DecTimer = WAITFORDATA ; 
            iRepeatTime ++ ; 
 
            return SUCCESS ; 
        } 
        else 
        { 
            g_DecTimer = 0 ; 
            iRepeatTime = 0 ; 
 
            data = NAK ; 
            ret  = Drv_DbgSerialOutChar(data); 
 
            iDownLoadState = START_OF_HEADER ; 
 
            return FAILURE; 
        } 
    } 
 
    return SUCCESS ; 
} 
 
/*========================================================================*/ 
/*                                                                        */ 
/*    Function Name    : End                                              */ 
/*    Function Func.   : The Function for the state END                   */ 
/*    Input Parameter  : none                                             */ 
/*    Output Parameter : none                                             */ 
/*    Return           : int                                              */ 
/*                       0 : success else failure                         */ 
/*    Call Functions   : none                                             */ 
/*    Called By        :                                                  */ 
/*                       1. xModemDownLoad (  )                           */ 
/*                                                                        */ 
/*========================================================================*/ 
_U32 Load_xModemEnd ( void ) 
{ 
    return SUCCESS ; 
} 
 
/*========================================================================*/ 
/*                                                                        */ 
/*    Function Name    : Purge                                            */ 
/*    Function Func.   : Clear the COM port by receive data until no data */ 
/*    Input Parameter  : none                                             */ 
/*    Output Parameter : none                                             */ 
/*    Return           : void                                             */ 
/*    Call Functions   :                                                  */ 
/*                       1. InChar (  )                                   */ 
/*    Called By        :                                                  */ 
/*                       1. CompOfSeqNo (  )                              */ 
/*                                                                        */ 
/*========================================================================*/ 
void Load_xModemPurge ( void ) 
{ 
    _U8 data ; 
    _U32 ret ; 
 
    do 
    { 
        ret = Drv_DbgSerialInChar(&data); 
    } 
    while ( ret  ) ; 
 
    return ; 
} 
 
#endif