?lang_form?
?lang_select?
?lang_submit?
?lang_endform?
{HEADER END}
{FILE START}
library
?curdirlinks? - Rev 6
?prevdifflink? - Blame - ?getfile?
/*! \file xmodem.c \brief XModem Transmit/Receive Implementation with CRC and 1K support. */
//*****************************************************************************
//
// File Name : 'xmodem.c'
// Title : XModem Transmit/Receive Implementation with CRC and 1K support
// Author : Pascal Stang - Copyright (C) 2006
// Created : 4/22/2006
// Revised : 7/22/2006
// Version : 0.1
// Target MCU : AVR processors
// Editor Tabs : 4
//
// This code is distributed under the GNU Public License
// which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************
#include <string.h>
#include "rprintf.h"
#include "timer.h"
#include "xmodem.h"
//#define XMODEM_BUFFER_SIZE 128
#define XMODEM_BUFFER_SIZE 1024
// pointers to stream I/O functions
static void (*xmodemOut)(unsigned char c);
static int (*xmodemIn)(void);
void xmodemInit(void (*sendbyte_func)(unsigned char c), int (*getbyte_func)(void))
{
// assign function pointers
xmodemOut = sendbyte_func;
xmodemIn = getbyte_func;
}
long xmodemReceive( int (*write)(unsigned char* buffer, int size) )
{
// create xmodem buffer
// 1024b for Xmodem 1K
// 128 bytes for Xmodem std.
// + 5b header/crc + NULL
unsigned char xmbuf[XMODEM_BUFFER_SIZE+6];
unsigned char seqnum=1; // xmodem sequence number starts at 1
unsigned short pktsize=128; // default packet size is 128 bytes
unsigned char response='C'; // solicit a connection with CRC enabled
char retry=XMODEM_RETRY_LIMIT;
unsigned char crcflag=0;
unsigned long totalbytes=0;
int i,c;
while(retry > 0)
{
// solicit a connection/packet
xmodemOut(response);
// wait for start of packet
if( (c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) >= 0)
{
switch(c)
{
case SOH:
pktsize = 128;
break;
#if(XMODEM_BUFFER_SIZE>=1024)
case STX:
pktsize = 1024;
break;
#endif
case EOT:
xmodemInFlush();
xmodemOut(ACK);
// completed transmission normally
return totalbytes;
case CAN:
if((c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) == CAN)
{
xmodemInFlush();
xmodemOut(ACK);
// transaction cancelled by remote node
return XMODEM_ERROR_REMOTECANCEL;
}
default:
break;
}
}
else
{
// timed out, try again
// no need to flush because receive buffer is already empty
retry--;
//response = NAK;
continue;
}
// check if CRC mode was accepted
if(response == 'C') crcflag = 1;
// got SOH/STX, add it to processing buffer
xmbuf[0] = c;
// try to get rest of packet
for(i=0; i<(pktsize+crcflag+4-1); i++)
{
if((c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) >= 0)
{
xmbuf[1+i] = c;
}
else
{
// timed out, try again
retry--;
xmodemInFlush();
response = NAK;
break;
}
}
// packet was too small, retry
if(i<(pktsize+crcflag+4-1))
continue;
// got whole packet
// check validity of packet
if( (xmbuf[1] == (unsigned char)(~xmbuf[2])) && // sequence number was transmitted w/o error
xmodemCrcCheck(crcflag, &xmbuf[3], pktsize) ) // packet is not corrupt
{
// is this the packet we were waiting for?
if(xmbuf[1] == seqnum)
{
// write/deliver data
write(&xmbuf[3], pktsize);
//spiflashWrite(flashaddr, pktsize, &xmbuf[3]);
totalbytes += pktsize;
// next sequence number
seqnum++;
// reset retries
retry = XMODEM_RETRY_LIMIT;
// reply with ACK
response = ACK;
continue;
}
else if(xmbuf[1] == (unsigned char)(seqnum-1))
{
// this is a retransmission of the last packet
// ACK and move on
response = ACK;
continue;
}
else
{
// we are completely out of sync
// cancel transmission
xmodemInFlush();
xmodemOut(CAN);
xmodemOut(CAN);
xmodemOut(CAN);
return XMODEM_ERROR_OUTOFSYNC;
}
}
else
{
// packet was corrupt
// NAK it and try again
retry--;
xmodemInFlush();
response = NAK;
continue;
}
}
// exceeded retry count
xmodemInFlush();
xmodemOut(CAN);
xmodemOut(CAN);
xmodemOut(CAN);
return XMODEM_ERROR_RETRYEXCEED;
}
long xmodemTransmit( int (*read)(unsigned char* buffer, int size) )
{
// still to be written
return 0;
}
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data)
{
int i;
crc = crc ^ ((uint16_t)data << 8);
for (i=0; i<8; i++)
{
if(crc & 0x8000)
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
return crc;
}
int xmodemCrcCheck(int crcflag, const unsigned char *buffer, int size)
{
// crcflag=0 - do regular checksum
// crcflag=1 - do CRC checksum
if(crcflag)
{
unsigned short crc=0;
unsigned short pktcrc = (buffer[size]<<8)+buffer[size+1];
// do CRC checksum
while(size--)
crc = crc_xmodem_update(crc, *buffer++);
// check checksum against packet
if(crc == pktcrc)
return 1;
}
else
{
int i;
unsigned char cksum = 0;
// do regular checksum
for(i=0; i<size; ++i)
{
cksum += buffer[i];
}
// check checksum against packet
if(cksum == buffer[size])
return 1;
}
return 0;
}
int xmodemInTime(unsigned short timeout)
{
int c=-1;
while( (timeout--) && ((c=xmodemIn()) < 0) )
timerPause(1);
return c;
}
void xmodemInFlush(void)
{
while(xmodemInTime(XMODEM_TIMEOUT_DELAY) >= 0);
}
|
{FILE END}
{FOOTER START}
Powered by WebSVN v2.8.3