#include "at91rm9200.h"
//
#define XMODEM_SOH 0x01
#define XMODEM_STX 0x02
#define XMODEM_EOT 0x04
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_ESC 0x1b
#define XMODEM_CAN 0x18
#define XMODEM_CRC 'C'
//
unsigned char filebuf[ 4 * 8 * 128 ]; //Max size of file, 4KB
unsigned char *fileEnd = filebuf;
static const unsigned short CRC16TAB[ 256 ] =
{
0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
};
//
void init_DMA_DBGU( void )
{
/*Using peripheral DBGU*/
AT91C_BASE_SYS -> PIOA_PDR = 0xc0000000;
AT91C_BASE_SYS -> PIOA_ASR = 0xc0000000;
AT91C_BASE_SYS -> DBGU_BRGR = 0x78; //9600 at 32.768KHz
AT91C_BASE_SYS -> DBGU_MR = 0x800; //No parity
AT91C_BASE_SYS -> DBGU_CR = 0x10c; //RSTSTA | RSTTX | RSTRX
AT91C_BASE_SYS -> DBGU_CR = 0x050; //TXEN | RXEN
AT91C_BASE_SYS -> DBGU_PTCR = 0x101; //TXTEN | RXTEN
}
void sentByte( unsigned char byte )
{
while( ( AT91C_BASE_SYS -> DBGU_CSR & 0x02 ) == 0 );
AT91C_BASE_SYS -> DBGU_THR = byte;
}
unsigned short get_CRC16( unsigned char *xbuff, int len )
{
register int i;
register unsigned short CRC = 0x00;
for( i = 0; i < len; i++ )
{
CRC = ( CRC << 8 ) ^ CRC16TAB[( ( CRC >> 8 ) ^ *xbuff++ ) & 0xff ];
}
return CRC;
}
int xmodem_recv( void )
{
int i;
int error;
int timeCounter;
unsigned short tCRC;
unsigned char recv;
unsigned char expectnum;
unsigned char XMODEM_FRAME[ 132 ];
fileEnd = filebuf;
timeCounter = 0;
while( ( AT91C_BASE_SYS -> DBGU_CSR & 0x01 ) == 0 )
{
timeCounter++;
if( timeCounter > 500000 )
{
timeCounter = 0;
sentByte( XMODEM_CRC );
}
}
for( expectnum = 1; ; expectnum++ )
{
while( ( AT91C_BASE_SYS -> DBGU_CSR & 0x01 ) == 0 );
recv = AT91C_BASE_SYS -> DBGU_RHR;
if( recv == XMODEM_EOT )
{
sentByte( XMODEM_ACK );
return 0;
}
AT91C_BASE_SYS -> DBGU_RPR = (unsigned int)XMODEM_FRAME;
AT91C_BASE_SYS -> DBGU_RCR = 132;
timeCounter = 0;
while( ( AT91C_BASE_SYS -> DBGU_CSR & 0x08 ) == 0 )
{
timeCounter++;
if( timeCounter > 500000 )
{
sentByte( XMODEM_CAN );
return 1;
}
}
if( (XMODEM_FRAME[ 0 ] ^ XMODEM_FRAME[ 1 ]) != 0xff )
{
expectnum--;
sentByte( XMODEM_NAK );
}
else
{
if( XMODEM_FRAME[ 0 ] != expectnum )
{
sentByte( XMODEM_CAN );
return 1;
}
//check the CRC
tCRC = ( XMODEM_FRAME[ 130 ] << 8 ) + XMODEM_FRAME[ 131 ];
error = ( tCRC != get_CRC16( &XMODEM_FRAME[ 2 ], 128 ) );
if( error )
{
expectnum--;
sentByte( XMODEM_NAK );
}
else
{
for( i = 2; i < 130; i++ )
{
*fileEnd++ = XMODEM_FRAME[ i ];
}
}
sentByte( XMODEM_ACK );
}
}
return 0;
}
int xmodem_sent( void )
{
int i;
int valid;
unsigned char packetnum;
unsigned char recv;
unsigned char XMODEM_FRAME[ 133 ];
unsigned char *fp = filebuf;
unsigned short CRC;
while( 1 )
{
do
{
valid = 1;
while( ( AT91C_BASE_SYS -> DBGU_CSR & 0x01 ) == 0 );
recv = AT91C_BASE_SYS -> DBGU_RHR;
switch( recv )
{
case XMODEM_ACK: packetnum++; break;
case XMODEM_NAK: fp = fp - 128; break;
case XMODEM_CAN: return 1;
case XMODEM_CRC: packetnum = 1; break;
default: valid = 0;
}
}while( !valid );
if( fp == fileEnd )
{
sentByte( XMODEM_EOT );
return 0;
}
else
{
XMODEM_FRAME[ 0 ] = XMODEM_SOH;
XMODEM_FRAME[ 1 ] = packetnum;
XMODEM_FRAME[ 2 ] = 0xff - packetnum;
for( i = 3; i < 131; i++ )
{
if( fp != fileEnd ) XMODEM_FRAME[ i ] = *fp++;
else
{
XMODEM_FRAME[ i ] = '\0';
}
}
CRC = get_CRC16( &XMODEM_FRAME[ 3 ], 128 );
XMODEM_FRAME[ 131 ] = CRC >> 8;
XMODEM_FRAME[ 132 ] = CRC & 0xff;
AT91C_BASE_SYS -> DBGU_TPR = (unsigned int)XMODEM_FRAME;
AT91C_BASE_SYS -> DBGU_TCR = 133;
while( ( AT91C_BASE_SYS -> DBGU_CSR & 0x10 ) == 0 );
}
}
return 0;
}
int main( void )
{
int error;
init_DMA_DBGU( );
error = xmodem_recv( );
error = xmodem_sent( );
while( 1 ){}
return 0;
}