飞帆blog https://bbs.21ic.com/?179849 [收藏] [复制] [RSS]

日志

xmodem源代码

已有 2045 次阅读2009-6-12 02:53 |系统分类:嵌入式系统| xmodem

#include "crc16.h"



#define SOH  0x01

#define STX  0x02

#define EOT  0x04

#define ACK  0x06

#define NAK  0x15

#define CAN  0x18

#define CTRLZ 0x1A



#define DLY_1S 1000

#define MAXRETRANS 25

static int last_error = 0;



#include "string.h"



void port_outbyte(unsigned char trychar)

{

    unsigned char buf[2];

    buf[0] = trychar;

    lowLevel_write(buf,1);

}



unsigned char port_inbyte(unsigned int time_out)

{

    unsigned char ch;

    int i;

    last_error = 0;



    if(lowLevel_read(&ch,1) == 1)

        return ch;



    last_error = 1;

    return ch;

}



static int check(int crc, const unsigned char *buf, int sz)

{

    if (crc)

    {

        unsigned short crc = crc16_ccitt(buf, sz);

        unsigned short tcrc = (buf[sz]<<8)+buf[sz+1];

        if (crc == tcrc)

            return 1;

    }

    else

    {

        int i;

        unsigned char cks = 0;

        for (i = 0; i < sz; ++i)

        {

            cks += buf;

        }

        if (cks == buf[sz])

            return 1;

    }

    return 0;

}



static void flushinput(void)

{

 //while (port_inbyte(((DLY_1S)*3)>>1) >= 0)

    ;

}



int xmodemReceive(unsigned char *dest, int destsz)

{

    unsigned char xbuff[1030];

    unsigned char *p;

    int bufsz, crc = 0;

    unsigned char trychar = 'C';

    unsigned char packetno = 1;

    int i, c, len = 0;

    int retry, retrans = MAXRETRANS;



    for(;;)

    {

        for( retry = 0; retry < 16; ++retry)

        {

            if (trychar)

                port_outbyte(trychar);

            c = port_inbyte((DLY_1S)<<1);

            if (last_error == 0)

            {

                switch (c)

                {

                case SOH:

                    bufsz = 128;

                    goto start_recv;

                case STX:

                    bufsz = 1024;

                    goto start_recv;

                case EOT:

                    flushinput();

                    port_outbyte(ACK);

                    return len;

                case CAN:

                    c = port_inbyte(DLY_1S);



                    if (c == CAN)

                    {

                        flushinput();

                        port_outbyte(ACK);

                        return -1;

                    }

                    break;

                default:

                    break;

                }

            }

        }

        if (trychar == 'C')

        {

            trychar = NAK;

            continue;

        }

        flushinput();

        port_outbyte(CAN);

        port_outbyte(CAN);

        port_outbyte(CAN);

        return -2;

start_recv:

        if (trychar == 'C') crc = 1;

            trychar = 0;

        p = xbuff;

        *p++ = c;

        for (i = 0;  i < (bufsz+(crc?1:0)+3); ++i)

        {

            c = port_inbyte(DLY_1S);



            if (last_error != 0)

                goto reject;

            *p++ = c;

        }



        if (xbuff[1] == (unsigned char)(~xbuff[2]) &&

            (xbuff[1] == packetno || xbuff[1] == (unsigned char)packetno-1) &&

            check(crc, &xbuff[3], bufsz))

        {

            if (xbuff[1] == packetno)

            {

                int count = destsz - len;

                if (count > bufsz)

                    count = bufsz;

                if (count > 0)

                {

                    memcpy (&dest[len], &xbuff[3], count);

                    len += count;

                }

                ++packetno;

                retrans = MAXRETRANS+1;

            }

            if (--retrans <= 0)

            {

                flushinput();

                port_outbyte(CAN);

                port_outbyte(CAN);

                port_outbyte(CAN);

                return -3;

            }

            port_outbyte(ACK);

            continue;

        }

reject:

        flushinput();

        port_outbyte(NAK);

    }

}



int xmodemTransmit(unsigned char *src, int srcsz)

{

    unsigned char xbuff[1030];

    int bufsz, crc = -1;

    unsigned char packetno = 1;

    int i, c, len = 0;

    int retry;



    for(;;)

    {

        for( retry = 0; retry < 16; ++retry)

        {

            c = port_inbyte((DLY_1S)<<1);

            if (last_error == 0)

            {

                switch (c)

                {

                case 'C':

                    crc = 1;

                    goto start_trans;

                case NAK:

                    crc = 0;

                    goto start_trans;

                case CAN:

                    c = port_inbyte(DLY_1S);

                    if (c == CAN)

                    {

                        port_outbyte(ACK);

                        flushinput();

                        return -1;

                    }

                    break;

                default:

                    break;

                }

            }

        }

        port_outbyte(CAN);

        port_outbyte(CAN);

        port_outbyte(CAN);

        flushinput();

        return -2;



        for(;;)

        {

start_trans:

            xbuff[0] = SOH; bufsz = 128;

            xbuff[1] = packetno;

            xbuff[2] = ~packetno;

            c = srcsz - len;

            if (c > bufsz)

                c = bufsz;

            if (c >= 0)

            {

                memset (&xbuff[3], 0, bufsz);

                if (c == 0)

                {

                    xbuff[3] = CTRLZ;

                }

                else

                {

                    memcpy (&xbuff[3], &src[len], c);

                    if (c < bufsz)

                        xbuff[3+c] = CTRLZ;

                }

                if (crc)

                {

                    unsigned short ccrc = crc16_ccitt(&xbuff[3], bufsz);

                    xbuff[bufsz+3] = (ccrc>>8) & 0xFF;

                    xbuff[bufsz+4] = ccrc & 0xFF;

                }

                else

                {

                    unsigned char ccks = 0;

                    for (i = 3; i < bufsz+3; ++i)

                    {

                        ccks += xbuff;

                    }

                    xbuff[bufsz+3] = ccks;

                }

                for (retry = 0; retry < MAXRETRANS; ++retry)

                {

                    for (i = 0; i < bufsz+4+(crc?1:0); ++i)

                    {

                        port_outbyte(xbuff);

                    }

                    c = port_inbyte(DLY_1S);

                    if (last_error == 0 )

                    {

                        switch (c)

                        {

                        case ACK:

                            ++packetno;

                            len += bufsz;

                            goto start_trans;

                        case CAN:

                            c = port_inbyte(DLY_1S);

                            if ( c == CAN)

                            {

                                port_outbyte(ACK);

                                flushinput();

                                return -1;

                            }

                            break;

                        case NAK:

                        default:

                            break;

                        }

                    }

                }

                port_outbyte(CAN);

                port_outbyte(CAN);

                port_outbyte(CAN);

                flushinput();

                return -4;

            }

            else

            {

                for (retry = 0; retry < 10; ++retry)

                {

                    port_outbyte(EOT);

                    c = port_inbyte((DLY_1S)<<1);

                    if (c == ACK)

                        break;

                }

                flushinput();

                return (c == ACK)?len:-5;

            }

        }

    }

}

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)