Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

xmodem.c

Go to the documentation of this file.
00001 /*! \file xmodem.c \brief XModem Transmit/Receive Implementation with CRC and 1K support. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'xmodem.c'
00005 // Title        : XModem Transmit/Receive Implementation with CRC and 1K support
00006 // Author       : Pascal Stang - Copyright (C) 2006
00007 // Created      : 4/22/2006
00008 // Revised      : 7/22/2006
00009 // Version      : 0.1
00010 // Target MCU   : AVR processors
00011 // Editor Tabs  : 4
00012 //
00013 // This code is distributed under the GNU Public License
00014 //      which can be found at http://www.gnu.org/licenses/gpl.txt
00015 //
00016 //*****************************************************************************
00017 
00018 #include <string.h>
00019 #include "rprintf.h"
00020 #include "timer.h"
00021 
00022 #include "xmodem.h"
00023 
00024 //#define XMODEM_BUFFER_SIZE        128
00025 #define XMODEM_BUFFER_SIZE      1024
00026 
00027 // pointers to stream I/O functions
00028 static void (*xmodemOut)(unsigned char c);
00029 static int (*xmodemIn)(void);
00030 
00031 void xmodemInit(void (*sendbyte_func)(unsigned char c), int (*getbyte_func)(void))
00032 {
00033     // assign function pointers
00034     xmodemOut = sendbyte_func;
00035     xmodemIn = getbyte_func;
00036 }
00037 
00038 long xmodemReceive( int (*write)(unsigned char* buffer, int size) )
00039 {
00040     // create xmodem buffer
00041     // 1024b for Xmodem 1K
00042     // 128 bytes for Xmodem std.
00043     // + 5b header/crc + NULL
00044     unsigned char xmbuf[XMODEM_BUFFER_SIZE+6];
00045     unsigned char seqnum=1;     // xmodem sequence number starts at 1
00046     unsigned short pktsize=128; // default packet size is 128 bytes
00047     unsigned char response='C'; // solicit a connection with CRC enabled
00048     char retry=XMODEM_RETRY_LIMIT;
00049     unsigned char crcflag=0;
00050     unsigned long totalbytes=0;
00051     int i,c;
00052 
00053     while(retry > 0)
00054     {
00055         // solicit a connection/packet
00056         xmodemOut(response);
00057         // wait for start of packet
00058         if( (c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) >= 0)
00059         {
00060             switch(c)
00061             {
00062             case SOH:
00063                 pktsize = 128;
00064                 break;
00065             #if(XMODEM_BUFFER_SIZE>=1024)
00066             case STX:
00067                 pktsize = 1024;
00068                 break;
00069             #endif
00070             case EOT:
00071                 xmodemInFlush();
00072                 xmodemOut(ACK);
00073                 // completed transmission normally
00074                 return totalbytes;
00075             case CAN:
00076                 if((c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) == CAN)
00077                 {
00078                     xmodemInFlush();
00079                     xmodemOut(ACK);
00080                     // transaction cancelled by remote node
00081                     return XMODEM_ERROR_REMOTECANCEL;
00082                 }
00083             default:
00084                 break;
00085             }
00086         }
00087         else
00088         {
00089             // timed out, try again
00090             // no need to flush because receive buffer is already empty
00091             retry--;
00092             //response = NAK;
00093             continue;
00094         }
00095 
00096         // check if CRC mode was accepted
00097         if(response == 'C') crcflag = 1;
00098         // got SOH/STX, add it to processing buffer
00099         xmbuf[0] = c;
00100         // try to get rest of packet
00101         for(i=0; i<(pktsize+crcflag+4-1); i++)
00102         {
00103             if((c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) >= 0)
00104             {
00105                 xmbuf[1+i] = c;
00106             }
00107             else
00108             {
00109                 // timed out, try again
00110                 retry--;
00111                 xmodemInFlush();
00112                 response = NAK;
00113                 break;
00114             }
00115         }
00116         // packet was too small, retry
00117         if(i<(pktsize+crcflag+4-1))
00118             continue;
00119 
00120         // got whole packet
00121         // check validity of packet
00122         if( (xmbuf[1] == (unsigned char)(~xmbuf[2])) &&     // sequence number was transmitted w/o error
00123             xmodemCrcCheck(crcflag, &xmbuf[3], pktsize) )   // packet is not corrupt
00124         {
00125             // is this the packet we were waiting for?
00126             if(xmbuf[1] == seqnum)
00127             {
00128                 // write/deliver data
00129                 write(&xmbuf[3], pktsize);
00130                 //spiflashWrite(flashaddr, pktsize, &xmbuf[3]);
00131                 totalbytes += pktsize;
00132                 // next sequence number
00133                 seqnum++;
00134                 // reset retries
00135                 retry = XMODEM_RETRY_LIMIT;
00136                 // reply with ACK
00137                 response = ACK;
00138                 continue;
00139             }
00140             else if(xmbuf[1] == (unsigned char)(seqnum-1))
00141             {
00142                 // this is a retransmission of the last packet
00143                 // ACK and move on
00144                 response = ACK;
00145                 continue;
00146             }
00147             else
00148             {
00149                 // we are completely out of sync
00150                 // cancel transmission
00151                 xmodemInFlush();
00152                 xmodemOut(CAN);
00153                 xmodemOut(CAN);
00154                 xmodemOut(CAN);
00155                 return XMODEM_ERROR_OUTOFSYNC;
00156             }
00157         }
00158         else
00159         {
00160             // packet was corrupt
00161             // NAK it and try again
00162             retry--;
00163             xmodemInFlush();
00164             response = NAK;
00165             continue;
00166         }
00167     }
00168 
00169     // exceeded retry count
00170     xmodemInFlush();
00171     xmodemOut(CAN);
00172     xmodemOut(CAN);
00173     xmodemOut(CAN);
00174     return XMODEM_ERROR_RETRYEXCEED;
00175 }
00176 
00177 
00178 long xmodemTransmit( int (*read)(unsigned char* buffer, int size) )
00179 {
00180     // still to be written
00181     return 0;
00182 }
00183 
00184 uint16_t crc_xmodem_update(uint16_t crc, uint8_t data)
00185 {
00186     int i;
00187 
00188     crc = crc ^ ((uint16_t)data << 8);
00189     for (i=0; i<8; i++)
00190     {
00191         if(crc & 0x8000)
00192             crc = (crc << 1) ^ 0x1021;
00193         else
00194             crc <<= 1;
00195     }
00196 
00197     return crc;
00198 }
00199 
00200 int xmodemCrcCheck(int crcflag, const unsigned char *buffer, int size)
00201 {
00202     // crcflag=0 - do regular checksum
00203     // crcflag=1 - do CRC checksum
00204 
00205     if(crcflag)
00206     {
00207         unsigned short crc=0;
00208         unsigned short pktcrc = (buffer[size]<<8)+buffer[size+1];
00209         // do CRC checksum
00210         while(size--)
00211             crc = crc_xmodem_update(crc, *buffer++);
00212         // check checksum against packet
00213         if(crc == pktcrc)
00214             return 1;
00215     }
00216     else
00217     {
00218         int i;
00219         unsigned char cksum = 0;
00220         // do regular checksum
00221         for(i=0; i<size; ++i)
00222         {
00223             cksum += buffer[i];
00224         }
00225         // check checksum against packet
00226         if(cksum == buffer[size])
00227             return 1;
00228     }
00229 
00230     return 0;
00231 }
00232 
00233 
00234 int xmodemInTime(unsigned short timeout)
00235 {
00236     int c=-1;
00237 
00238     while( (timeout--) && ((c=xmodemIn()) < 0) )
00239         timerPause(1);
00240 
00241     return c;
00242 }
00243 
00244 void xmodemInFlush(void)
00245 {
00246     while(xmodemInTime(XMODEM_TIMEOUT_DELAY) >= 0);
00247 }

Generated on Sun Oct 29 03:41:08 2006 for Procyon AVRlib by  doxygen 1.4.2