参考韦东山串口烧写binary和uboot命令,自制bootloader在QT210实现这些功能,方便调试:
串口烧写的速度大概8K左右,烧写几十k的bootloader还可以,不用总是插拔usb了,
log:
Printf enter to enter shell mode
SMDKV210 #uart load 0x20000000
uartmem:uart
uart load 0x20000000 Download will start!press enter to start the timer
10
9
8
7
6
开始 xmodem 传输。 按 Ctrl+C 取消。
Transferring BL2.log...
100% 275 KB 7 KB/s 00:00:35 0 Errors
complted:len:282368
SMDKV210 #
uartmem:uart
uart
SMDKV210 #
SMDKV210 #
SMDKV210 #flashbl2Download will start!press enter to start the timer
10
9
8
7
6
开始 xmodem 传输。 按 Ctrl+C 取消。
Transferring BL2.bin...
100% 29 KB 7 KB/s 00:00:04 0 Errors
complted:len:30592
SMDKV210 #
BL2.lds
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x30000000;
.text :
{
out/start.o (.text)
out/*(.text)
}
. = ALIGN(4);
.rodata : { out/*(.rodata) }
. = ALIGN(4);
.data : {out/*(.data)}
. = ALIGN(4);
.got : { out/*(.got) }
__u_boot_cmd_start = .;
.u_boot_cmd : { out/*(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
bss_start = .;
.bss : {out/*(.bss) out/*(COMMON) }
bss_end = .;
}
//main.c
#include "stdio.h"
#include "includes.h"
void run_shell()
{
char rx_buf[100]={'\0'};
delay(1000);
while(1)
{
printf("SMDKV210 #");
gets(rx_buf);
if((strlen(rx_buf) == 1 && strcmp(rx_buf, "q") == 0) || strcmp(rx_buf, "quit")==0)
break;
run_command(rx_buf,0);
printf("\n");
}
}
void main(void)
{
int i = 5;
char c;
int timeout=0;
led_init();
lcd_init();
uart_init();
GUI_ClearScreen(0x00ffff00);
GUI_Printf(100,100,0x00,0xffffffff,"BL2 BOOT...");
while(1)
{
getc_nowait(&c);
if(c=='\r')
{
timeout = 0;
run_shell();
c='\0';//resolve reset the c is s
}
delay(1000);
printf("time out:%d\r",timeout);
timeout++;
if(timeout> 5)
break;
}
printf("the system will be boot\n");
while (1)
{
i=i%4;
led(i);
delay(1000);
i++;
}
}
//commond.c
#include "command.h"
#include "stdio.h"
#include "string.h"
#include "includes.h"
/*
* Use puts() instead of printf() to avoid printf buffer overflow
* for long help messages
*/
int do_help (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
int i;
int rcode = 0;
if (argc == 1) { /*show list of commands */
int cmd_items = &__u_boot_cmd_end -
&__u_boot_cmd_start; /* pointer arith! */
cmd_tbl_t *cmd_array[cmd_items];
int i, j, swaps;
/* Make array of commands from .uboot_cmd section */
cmdtp = &__u_boot_cmd_start;
for (i = 0; i < cmd_items; i++) {
cmd_array[i] = cmdtp++;
}
/* Sort command list (trivial bubble sort) */
for (i = cmd_items - 1; i > 0; --i) {
swaps = 0;
for (j = 0; j < i; ++j) {
if (strcmp (cmd_array[j]->name,
cmd_array[j + 1]->name) > 0) {
cmd_tbl_t *tmp;
tmp = cmd_array[j];
cmd_array[j] = cmd_array[j + 1];
cmd_array[j + 1] = tmp;
++swaps;
}
}
if (!swaps)
break;
}
/* print short help (usage) */
for (i = 0; i < cmd_items; i++) {
const char *usage = cmd_array[i]->usage;
/* allow user abort */
if (ctrlc ())
return 1;
if (usage == NULL)
continue;
puts (usage);
}
return 0;
}
/*
* command help (long version)
*/
for (i = 1; i < argc; ++i) {
if ((cmdtp = find_cmd (argv[i])) != NULL) {
#ifdef CFG_LONGHELP
/* found - print (long) help info */
puts (cmdtp->name);
putc (' ');
if (cmdtp->help) {
puts (cmdtp->help);
} else {
puts ("- No help available.\n");
rcode = 1;
}
putc ('\n');
#else /* no long help available */
if (cmdtp->usage)
puts (cmdtp->usage);
#endif /* CFG_LONGHELP */
} else {
printf ("Unknown command '%s' - try 'help'"
" without arguments for list of all"
" known commands\n\n", argv[i]
);
rcode = 1;
return 0;
}
}
return rcode;
}
U_BOOT_CMD(
help, CFG_MAXARGS, 1, do_help,
"help - print online help\n",
"[command ...]\n"
" - show help information (for 'command')\n"
"'help' prints online help for the monitor commands.\n\n"
"Without arguments, it prints a short usage message for all commands.\n\n"
"To get detailed help information for specific commands you can type\n"
"'help' with one or more command names as arguments.\n"
);
/* This do not ust the U_BOOT_CMD macro as ? can't be used in symbol names */
cmd_tbl_t __u_boot_cmd_question_mark Struct_Section = {
"?", CFG_MAXARGS, 1, do_help,
"? - alias for 'help'\n",
NULL
};
/***************************************************************************
* find command table entry for a command
*/
cmd_tbl_t *find_cmd (const char *cmd)
{
cmd_tbl_t *cmdtp;
cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start; /*Init value */
const char *p;
int len;
int n_found = 0;
/*
* Some commands allow length modifiers (like "cp.b");
* compare command name only until first dot.
*/
len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);
for (cmdtp = &__u_boot_cmd_start;
cmdtp != &__u_boot_cmd_end;
cmdtp++) {
if (strncmp (cmd, cmdtp->name, len) == 0) {
if (len == strlen (cmdtp->name))
return cmdtp; /* full match */
cmdtp_temp = cmdtp; /* abbreviated command ? */
n_found++;
}
}
if (n_found == 1) { /* exactly one match */
return cmdtp_temp;
}
return NULL; /* not found or ambiguous command */
}
int parse_line (char *line, char *argv[])
{
int nargs = 0;
while (nargs < CFG_MAXARGS )
{
/* skip any white space */
while ((*line == ' ') || (*line == '\t'))
{
++line;
}
if (*line == '\0')
{ /* end of line, no more args */
argv[nargs] = NULL;
return (nargs);
}
argv[nargs++] = line; /* begin of argument string */
/* find end of string */
while (*line && (*line != ' ') && (*line != '\t'))
{
++line;
}
if (*line == '\0')
{ /* end of line, no more args */
argv[nargs] = NULL;
return (nargs);
}
*line++ = '\0'; /* terminate current arg */
}
printf ("** Too many args (max. %d) **\n", CFG_MAXARGS);
return (nargs);
}
int run_command (char *cmd, int flag)
{
cmd_tbl_t *cmdtp;
//char cmdbuf[CFG_CBSIZE]; /* working copy of cmd */
//char *str = cmdbuf;
char *argv[CFG_MAXARGS + 1]; /* NULL terminated */
int argc;
int repeatable = 1;
int rc = 0;
clear_ctrlc(); /* forget any previous Control C */
if (!cmd || !*cmd) {
return -1; /* empty command */
}
if (strlen(cmd) >= CFG_CBSIZE) {
puts ("## Command too long!\n");
return -1;
}
//strcpy (cmdbuf, cmd);
/* Process separators and check for invalid
* repeatable commands
*/
// while (*str)
// {
/* Extract arguments */
if ((argc = parse_line (cmd, argv)) == 0)
{
rc = -1; /* no command at all */
//continue;
return 0;
}
//printf("argc:%d,%s,%s\r\n",argc,argv[0],argv[1]);
/* Look up command in command table */
if ((cmdtp = find_cmd(argv[0])) == NULL)
{
printf ("Unknown command '%s' - try 'help'\n", argv[0]);
rc = -1; /* give up after bad command */
return 0;
//continue;
}
if(strcmp(argv[1],"help")==0)
{
printf ("\nhelp:\n%s\n", cmdtp->help);
return 0;
}
/* found - check max args */
if (argc > cmdtp->maxargs)
{
printf ("Usage:\n%s\n", cmdtp->usage);
rc = -1;
return 0;
//continue;
}
/* OK - call function to do the command */
if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0)
{
rc = -1;
return 0;
}
repeatable &= cmdtp->repeatable;
/* Did the user stop this? */
if (had_ctrlc ())
return -1; /* if stopped then not repeatable */
// }
return 0;
// return rc ? rc : repeatable;
}
cmd_load.c
#include "stdio.h"
#include "command.h"
#include "string.h"
#include "def.h"
extern U8 SDHC_WriteBlocks(U32 uStBlock, U16 uBlocks, U32* uBufAddr);
extern int getc_nowait(unsigned char *pChar);
#define SOH 0x01
#define STX 0x02
#define EOT 0x04//正常结束,通知接收方
#define ACK 0x06//接收正确
#define NAK 0x15//开始发第一个包、重发
#define CAN 0x18//无条件停止发送
#define CTRLZ 0x1A//不足部分填充
extern void delay(int ms);
int xmodem_recv(unsigned long addr)
{
int i = 0;
int cnt=addr;
char buf[128 + 4];
char c;
puts("Download will start!press enter to start the timer\n");
getc();
for(i =10; i>0;i--)
{
printf("%d\n",i);
delay(1500);
}
putc(NAK);
while((buf[0] = getc()) != EOT)
{
for(i = 1; i < 128 + 4; i++)
{
if(i >= 3 && i <= 130)
*(char *)(addr + i-3) = getc();
}
addr += 128;
putc(ACK);
}
putc(ACK);
printf("\ncomplted:len:%d\n",addr-cnt);
return (addr-cnt);
}
int uart_load_mem(unsigned long addr)
{
unsigned char *buf = (unsigned char *)addr;
unsigned long len = 0;
int have_begin = 0;
int nodata_time = 0;
int i=0;
/* 读串口获得数据 */
printf("\nuse terminal to send file:0x%08x\n", (unsigned long)addr);
while (1)
{
if (getc_nowait(&buf[len]) == 0)
{
have_begin = 1;
nodata_time = 0;
len++;
}
else
{
if (have_begin)
{
nodata_time++;
}
}
if (nodata_time == 1000000)
{
break;
}
}
printf("\ncomplted:len:%d,timeout:%d\n",len,nodata_time);
return len;
}
int do_uartmem (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
unsigned long load_addr=0;
int len = 0;
int i = 0;
int isload = 0;
int memsize = 0;
int start_blk = 0;
char ap[20]={'\0'};
printf("\n uartmem:%s\n",argv[0]);
for( i=0;i<5;i++)
{
if(argv[i])
printf("%s ",argv[i]);
else break;
}
//(strcmp(ap[1], "-eq") == 0)
strcpy(ap,argv[1]);
if(strcmp(ap,"load") == 0)
{
isload = 1;//load mem
load_addr = simple_strtoul(argv[2], NULL, 16);
}
if(strcmp(ap,"sd") == 0)
{
isload = 2; //write to sd
load_addr = simple_strtoul(argv[2], NULL, 16);
start_blk = simple_strtoul(argv[3], NULL, 10);
memsize = simple_strtoul(argv[4], NULL, 10);
}
switch(isload)
{
case 1:
len = uart_load_mem(load_addr);
//len = xmodem_recv(load_addr);
break;
case 2:
printf("\n sd:start_blk:%d,memsize:%d,load_addr:0x%08x\n",start_blk,(memsize+511)/512,load_addr);
SDHC_WriteBlocks(start_blk,(memsize+511)/512,(U32 *)load_addr);
break;
default:
break;
}
return 0;
}
U_BOOT_CMD(
uart, 5, 0, do_uartmem,
"uart - load into memory from uart\n",
"uart load address\nuart sd addr(0xXXXXXXXX) blk size(bytes)\n"
);
int do_goaddr(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
unsigned long addr;
addr = simple_strtoul(argv[1],NULL,16);
printf("\nwill run to adress::%s,%s,0x%08x\n",argv[0],argv[1],addr);
void (*theProgram)(void);
theProgram = (void (*)(void))addr;
theProgram();
return 0;
}
U_BOOT_CMD(
go, 2, 0, do_goaddr,
"go - go address\r\n",
NULL
);
/* * reset the cpu by setting up the watchdog timer and let him time out */
int reset_cpu(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
printf("reset... \n\n\n");
//SW_RST_REG = 0x1;
*(volatile long *)0xe0102000 = 0x01;
while (1)
{
if(getc())
break;
}
return 0;
/*NOTREACHED*/
}
U_BOOT_CMD(
reset, 1, 0, reset_cpu,
"reset - reset cpu\n",
NULL
);
int flash_bl2(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int len=0;
//len = xmodem_recv(0x20000000);
len = uart_load_mem(0x20000000);
SDHC_WriteBlocks(49,(len+511)/512,(U32 *)0x20000000);
return 0;
}
U_BOOT_CMD(
flashbl2, 1, 0, flash_bl2,
"flashbl2- down load bl2 to sd\n",
NULL
);