添加XMODEM下载协议到基于u-boot-1.3.4的9G9260开发板
1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/sam9260# wget ftp://ftp.denx.de/pub/u-boot/u-boot-1.3.4.tar.bz2
root@yuanxh-desktop:/home/yuanxh/sam9260# wget ftp://www.linux4sam.org/pub/uboot/u-boot-1.3.4-exp/u-boot-1.3.4-exp.diff
root@yuanxh-desktop:/home/yuanxh/sam9260# tar xjvf u-boot-1.3.4.tar.bz2
root@yuanxh-desktop:/home/yuanxh/sam9260# mv u-boot-1.3.4 u-boot-1.3.4-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260# mv u-boot-1.3.4-exp.diff u-boot-1.3.4-9g9260/
2,打补丁:
root@yuanxh-desktop:/home/yuanxh/sam9260# cd u-boot-1.3.4-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# patch -p1 < ./u-boot-1.3.4-exp.diff
3,默认配置:
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make at91sam9260ek_dataflash_cs0_config
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make at91sam9260ek_dataflash_cs1_config
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make at91sam9260ek_nandflash_config
(选择对应的一项,区分NANDFLASH和DATAFLASH的CS0,CS1)
4,添加XMODEM下载协议
在\common\Makefile的147行添加 COBJS-y += cmd_xmodem.o xmodem.o
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# vi common/Makefile
在\common\中增加源文件 xmodem.c cmd_xmodem.c
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# rz
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# mv xmodem.c cmd_xmodem.c common/
5,编译发布:
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# mv u-boot.bin u-boot-1.3.4-9g9260.bin
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# sz u-boot-1.3.4-9g9260.bin
6, 清除配置
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make distclean
附件:xmodem.c文件
/*******************************************************************************
*
* Filename: xmodem.c
*
* change from KB9202 , yuanxihua@21cn.com
******************************************************************************/
#include <common.h>
extern int xmodem_rx(char *dest);
/* Line control codes */
#define SOH 0x01 /* start of header for Xmodem protocol */
#define STX 0x02 /* start of header for 1K xmodem protocol*/
#define ACK 0x06 /* Acknowledge */
#define NAK 0x15 /* Negative acknowledge */
#define CAN 0x18 /* Cancel */
#define EOT 0x04 /* end of text */
#define TIMEOUT 2
#define TIMEOUT_LONG 10
#define XMODEM_DATA_SIZE_SOH 128 /* for Xmodem protocol */
#define XMODEM_DATA_SIZE_STX 1024 /* for 1K xmodem protocol */
enum {
INVALID_STATE = 0,
WAITING_START,
WAIT_HEAD,
RX_PACKET,
RX_EOT,
SEND_NAK
};
static char packetNumber;
static int PACKET_SIZE;
static char HEAD;
#define TransitionState(x, y) (x = y)
void DebugPutc(char cValue)
{
putc (cValue & 0x1FF);
}
int WaitForChar(char *cPtr, int seconds)
{
unsigned long counter = 0;
seconds = seconds * 1000 ; /* delay 1000 * 50 * 20us */
while (!tstc () && (counter < seconds * 50 ))
{
udelay (20);
counter++;
}
if (tstc ())
{
*cPtr = getc ();
return 1;
}
return 0;
}
static int GetRecord(char blocknum, char *dest) {
int size;
char nextChar;
unsigned chk, j;
chk = 0;
if (!WaitForChar(&nextChar, TIMEOUT)) {
return (0);
}
if ((char)nextChar != (char)~blocknum) {
return (0);
}
for (size = 0; size < PACKET_SIZE; ++size) {
if (!WaitForChar(&nextChar, TIMEOUT)) {
return (0);
}
chk = chk ^(int)nextChar << 8;
for (j = 0; j < 8; ++j) {
if (chk & 0x8000)
chk = chk << 1 ^ 0x1021;
else
chk = chk << 1;
}
*dest++ = nextChar;
}
chk &= 0xFFFF;
if ((!WaitForChar(&nextChar, TIMEOUT)) || (nextChar != ((chk >> 8) & 0xFF))) {
return (0);
}
if ((!WaitForChar(&nextChar, TIMEOUT)) || (nextChar != (chk & 0xFF))) {
return (0);
}
DebugPutc(ACK);
return (1);
}
int xmodem_rx(char *dest) {
int state;
char nextChar, *startAddress = dest;
packetNumber = 1;
state = WAITING_START;
PACKET_SIZE = XMODEM_DATA_SIZE_SOH;
HEAD = SOH;
while (1) {
if (state == WAITING_START) {
DebugPutc('C');
if (WaitForChar(&nextChar, TIMEOUT)) {
if (nextChar == SOH)
{
PACKET_SIZE = XMODEM_DATA_SIZE_SOH;
HEAD = SOH;
TransitionState(state, RX_PACKET);
}
else
if (nextChar == STX)
{
PACKET_SIZE = XMODEM_DATA_SIZE_STX;
HEAD = STX;
TransitionState(state, RX_PACKET);
}
}
}
if (state == WAIT_HEAD) {
if (!WaitForChar(&nextChar, TIMEOUT_LONG)) {
return (-1);
}
/* if (nextChar == HEAD) {
TransitionState(state, RX_PACKET);
}
*/
if (nextChar == SOH)
{
PACKET_SIZE = XMODEM_DATA_SIZE_SOH;
HEAD = SOH;
TransitionState(state, RX_PACKET);
}
else
if (nextChar == STX)
{
PACKET_SIZE = XMODEM_DATA_SIZE_STX;
HEAD = STX;
TransitionState(state, RX_PACKET);
}
if (nextChar == EOT) {
// TransitionState(state, RX_EOT);
DebugPutc(ACK);
return (dest - startAddress);
}
}
if (state == RX_PACKET) {
if (!WaitForChar(&nextChar, TIMEOUT)) {
return (-1);
}
if (nextChar != packetNumber) {
// TransitionState(state, SEND_NAK);
DebugPutc(NAK);
return (-1);
}
if (GetRecord(packetNumber, dest)) {
dest += PACKET_SIZE;
++packetNumber;
TransitionState(state, WAIT_HEAD);
} else {
return (-1);
}
}
}
// the loop above should return in all cases
return (-1);
}
附件:cmd_xmodem.c文件
#include <common.h>
#include <command.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
static ulong load_xmodem_bin(ulong *);
static char *bin_start_address;
int do_xmodem(cmd_tbl_t *cmdtp,int flag,int argc, char *argv[])
{
DECLARE_GLOBAL_DATA_PTR;
ulong offset = 0;
ulong addr;
int load_baudrate, current_baudrate;
int rcode = 0;
char *s;
/* pre-set offset from CFG_LOAD_ADDR */
offset = CFG_LOAD_ADDR;
/* pre-set offset from $loadaddr */
if ((s = getenv("loadaddr")) != NULL) {
offset = simple_strtoul(s, NULL, 16);
}
load_baudrate = current_baudrate = gd->baudrate;
if (argc >= 2) {
offset = simple_strtoul(argv[1], NULL, 16);
}
if (argc == 3) {
load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
/* default to current baudrate */
if (load_baudrate == 0)
load_baudrate = current_baudrate;
}
if (load_baudrate != current_baudrate) {
printf ("## Switch baudrate to %d bps and press ENTER ...\n",
load_baudrate);
udelay(50000);
gd->baudrate = load_baudrate;
serial_setbrg ();
udelay(50000);
for (;;) {
if (getc() == '\r')
break;
}
}
printf ("## Ready for binary (xmodem) download "
"to 0x%08lX at %d bps...\n",
offset,
load_baudrate);
addr = load_xmodem_bin((ulong *) offset);
if (addr == ~0) {
load_addr = 0;
printf ("## Binary (xmodem) download aborted\n");
rcode = 1;
} else {
printf ("## Start Addr = 0x%08lX\n", addr);
load_addr = addr;
}
if (load_baudrate != current_baudrate) {
printf ("## Switch baudrate to %d bps and press ESC ...\n",
current_baudrate);
udelay (50000);
gd->baudrate = current_baudrate;
serial_setbrg ();
udelay (50000);
for (;;) {
if (getc() == 0x1B) /* ESC */
break;
}
}
#ifdef CONFIG_AUTOSCRIPT
if (load_addr) {
char *s;
if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
printf("Running autoscript at addr 0x%08lX ...\n", load_addr);
rcode = autoscript (load_addr);
}
}
#endif
return rcode;
}
static ulong load_xmodem_bin(unsigned long *addr)
{
int size, i;
char buf[32];
ulong offset;
// set_kerm_bin_mode ((ulong *) offset);
// size = k_recv ();
offset = addr;
bin_start_address = (char *) addr;
size = xmodem_rx(bin_start_address);
/*
* Gather any trailing characters (for instance, the ^D which
* is sent by 'cu' after sending a file), and give the
* box some time (100 * 1 ms)
*/
for (i=0; i<100; ++i) {
if (tstc()) {
(void) getc();
}
udelay(1000);
}
flush_cache (offset, size);
printf("## Total Size = 0x%08x = %d Bytes\n", size, size);
sprintf(buf, "%X", size);
setenv("filesize", buf);
return offset;
}
U_BOOT_CMD(
rx, 3, 0, do_xmodem,
"rx - load binary file over serial line (xmodem)\n",
"[ off ] [ baud ]\n"
" - load binary file over serial line"
" with offset 'off' and baudrate 'baud'\n"
);
离线