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
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;
|
|
}
|
|
|
|
|
|
|