You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

283 lines
7.0 KiB

//#include <asm/context.h>
//#include <asm/cacheops.h>
//#include <asm/mipsregs.h>
//#include <asm/r4kcache.h>
#define tgt_puts tgt_puts1
#undef XMODEM_DEBUG
static inline __attribute__((always_inline)) int now()
{
int count;
asm volatile("mfc0 %0,$9":"=r"(count));
return count;
}
static inline __attribute__((always_inline)) void *memcpy(char *s1, const char *s2, int n)
{
while(n--)
*s1++=*s2++;
}
static __attribute__ ((section (".data"))) void * memset(void * s,int c, int count)
{
char *xs = (char *) s;
while (count--)
*xs++ = c;
return s;
}
static __attribute__ ((section (".data"))) unsigned short _crc_xmodem_update (unsigned short crc, unsigned char data)
{
int i;
crc = crc ^ ((unsigned short)data << 8);
for (i=0; i<8; i++)
{
if (crc & 0x8000)
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
return crc;
}
static __attribute__ ((section (".data"))) int tgt_puts(char *str)
{
while(*str)
tgt_putchar1(*str++);
return 0;
}
//³£Êý¶¨Òå
#define BLOCKSIZE 128 //M16µÄÒ»¸öFlashҳΪ128×Ö½Ú(64×Ö)
#define DATA_BUFFER_SIZE BLOCKSIZE //¶¨Òå½ÓÊÕ»º³åÇø³¤¶È
//#define F_CPU 7372800 //ϵͳʱÖÓ7.3728MHz
//¶¨ÒåXmoden¿ØÖÆ×Ö·û
#define XMODEM_NUL 0x00
#define XMODEM_SOH 0x01
#define XMODEM_STX 0x02
#define XMODEM_EOT 0x04
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_CAN 0x18
#define XMODEM_EOF 0x1A
#define XMODEM_WAIT_CHAR 'C'
//¶¨ÒåÈ«¾Ö±äÁ¿
struct str_XMODEM
{
unsigned char SOH; //Æðʼ×Ö½Ú
unsigned char BlockNo; //Êý¾Ý¿é±àºÅ
unsigned char nBlockNo; //Êý¾Ý¿é±àºÅ·´Âë
unsigned char Xdata[BLOCKSIZE]; //Êý¾Ý128×Ö½Ú
unsigned char CRC16hi; //CRC16УÑéÊý¾Ý¸ßλ
unsigned char CRC16lo; //CRC16УÑéÊý¾ÝµÍλ
} strXMODEM ; //XMODEMµÄ½ÓÊÕÊý¾Ý½á¹¹
/* GCCÀïÃæµØַʹÓÃ32볤¶È£¬ÊÊÓ¦ËùÓÐAVRµÄÈÝÁ¿*/
#define ST_WAIT_START 0x00 //µÈ´ýÆô¶¯
#define ST_BLOCK_OK 0x01 //½ÓÊÕÒ»¸öÊý¾Ý¿é³É¹¦
#define ST_BLOCK_FAIL 0x02 //½ÓÊÕÒ»¸öÊý¾Ý¿éʧ°Ü
#define ST_OK 0x03 //Íê³É
#ifdef XMODEM_DEBUG
#define dbg_printf tgt_puts
#else
#define dbg_printf(...)
#endif
static __attribute__ ((section (".data"))) int testchar()
{
int count=2;
int total, start;
start = now();
while(1)
{
if(tgt_testchar1())
return 100;
if(!count)break;
if((now()-start>0x3000000 )){
start = now();
count--;
}
}
return 0;
}
static __attribute__ ((section (".data"))) int get_data(unsigned char *ptr,unsigned int len,unsigned int timeout)
{
int i=0;
volatile int count=1;
while(i<len)
{
if(testchar()>0)
ptr[i++]=tgt_getchar();
else {
if(!count)break;
count--;
}
}
return i;
}
//¼ÆËãCRC16
static __attribute__ ((section (".data"))) unsigned int calcrc(unsigned char *ptr, unsigned int count)
{
unsigned int crc = 0;
while (count--)
{
crc =_crc_xmodem_update(crc,*ptr++);
}
return crc;
}
static int __attribute__ ((section (".data"))) program1(char *p,int off, int size)
{
static int first = 1;
if(first)
{
erase();
first = 0;
}
program(p,off,size);
}
int __attribute__ ((section (".data"))) xmodem_transfer(char *base)
{
unsigned char c;
unsigned int i;
unsigned int crc;
unsigned int filesize=0;
unsigned char BlockCount=1; //Êý¾Ý¿éÀÛ¼Æ(½ö8룬ÎÞÐ뿼ÂÇÒç³ö)
unsigned char STATUS; //ÔËÐÐ״̬
spi_init();
//ÏòPC»ú·¢ËÍ¿ªÊ¼ÌáʾÐÅÏ¢
STATUS=ST_WAIT_START; //²¢ÇÒÊý¾Ý='d'»ò'D',½øÈëXMODEM
c=0;
while(1)
{
tgt_putchar1(XMODEM_WAIT_CHAR);
if(testchar()>0)break;
}
while(STATUS!=ST_OK) //Ñ­»·½ÓÊÕ£¬Ö±µ½È«²¿·¢Íê
{
i=get_data(&strXMODEM.SOH,BLOCKSIZE+5,1000); //ÏÞʱ1Ã룬½ÓÊÕ133×Ö½ÚÊý¾Ý
if(i)
{
//·ÖÎöÊý¾Ý°üµÄµÚÒ»¸öÊý¾Ý SOH/EOT/CAN
switch(strXMODEM.SOH)
{
case XMODEM_SOH: //ÊÕµ½¿ªÊ¼·ûSOH
if (i>=(BLOCKSIZE+5))
{
STATUS=ST_BLOCK_OK;
}
else
{
STATUS=ST_BLOCK_FAIL; //Èç¹ûÊý¾Ý²»×㣬ҪÇóÖØ·¢µ±Ç°Êý¾Ý¿é
tgt_putchar1(XMODEM_NAK);
}
break;
case XMODEM_EOT: //ÊÕµ½½áÊø·ûEOT
//tgt_putchar1(XMODEM_ACK); //֪ͨPC»úÈ«²¿ÊÕµ½
//STATUS=ST_OK;
tgt_putchar1(XMODEM_NAK); //ÒªÇóÖØ·¢µ±Ç°Êý¾Ý¿é
STATUS=ST_BLOCK_FAIL;
dbg_printf("transfer succeed!\r\n");
break;
case XMODEM_CAN: //ÊÕµ½È¡Ïû·ûCAN
//tgt_putchar1(XMODEM_ACK); //»ØÓ¦PC»ú
//STATUS=ST_OK;
tgt_putchar1(XMODEM_NAK); //ÒªÇóÖØ·¢µ±Ç°Êý¾Ý¿é
STATUS=ST_BLOCK_FAIL;
dbg_printf("Warning:user cancelled!\r\n");
break;
default: //Æðʼ×Ö½Ú´íÎó
tgt_putchar1(XMODEM_NAK); //ÒªÇóÖØ·¢µ±Ç°Êý¾Ý¿é
STATUS=ST_BLOCK_FAIL;
break;
}
}
else
{
dbg_printf("time out!\n");
break;
}
if (STATUS==ST_BLOCK_OK) //½ÓÊÕ133×Ö½ÚOK£¬ÇÒÆðʼ×Ö½ÚÕýÈ·
{
if (BlockCount != strXMODEM.BlockNo)//ºË¶ÔÊý¾Ý¿é±àºÅÕýÈ·
{
tgt_putchar1(XMODEM_NAK); //Êý¾Ý¿é±àºÅ´íÎó£¬ÒªÇóÖØ·¢µ±Ç°Êý¾Ý¿é
continue;
}
if (BlockCount !=(unsigned char)(~strXMODEM.nBlockNo))
{
tgt_putchar1(XMODEM_NAK); //Êý¾Ý¿é±àºÅ·´Âë´íÎó£¬ÒªÇóÖØ·¢µ±Ç°Êý¾Ý¿é
continue;
}
crc=strXMODEM.CRC16hi<<8;
crc+=strXMODEM.CRC16lo;
//AVRµÄ16λÕûÊýÊǵÍλÔÚÏÈ£¬XMODEMµÄCRC16ÊǸßλÔÚÏÈ
if(calcrc(&strXMODEM.Xdata[0],BLOCKSIZE)!=crc)
{
tgt_putchar1(XMODEM_NAK); //CRC´íÎó£¬ÒªÇóÖØ·¢µ±Ç°Êý¾Ý¿é
dbg_printf("crc error\n");
continue;
}
//ÕýÈ·½ÓÊÕ128¸ö×Ö½ÚÊý¾Ý£¬¸ÕºÃÊÇM16µÄÒ»Ò³
memcpy(base+(filesize&0xfff),strXMODEM.Xdata,128);
filesize+=128;
tgt_putchar1(XMODEM_ACK); //»ØÓ¦ÒÑÕýÈ·ÊÕµ½Ò»¸öÊý¾Ý¿é
BlockCount++; //Êý¾Ý¿éÀۼƼÓ1
if((filesize&0xfff)==0)
program1(base,filesize-0x1000,0x1000);
}
}
if((filesize&0xfff))
program1(base,(filesize&~0xfff),0x1000);
//Í˳öBootloader³ÌÐò£¬´Ó0x0000´¦Ö´ÐÐÓ¦ÓóÌÐò
tgt_puts("xmodem finished\r\n");
return filesize;
}
static char blockdata[0x1000];
int xmodem()
{
int size;
int offset;
char mode;
//clean char buf
tgt_puts("xmodem now\r\n");
while(tgt_getchar()!='x') tgt_puts("press x to tranfser\r\n");
//tgt_puts("haha\r\n");
xmodem_transfer(blockdata);
while(1);
return 0;
}