打印法:前段用puts(); 后面可以用printf();这个可以试一试。
点灯法:找到相应的GPIO寄存器,在文件头加上#include<regs.h> 这个头最好是放在所有头的后面。
int i;
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
puts ("^_^\n");
从头开始:¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
1:lib-arm/board.c
void start_armboot (void) <=====第二阶段开始
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
程序走到如上查看init_sequence恰好在此文件中
init_fnc_t *init_sequence[] = {
cpu_init,
#if defined(CONFIG_SKIP_RELOCATE_UBOOT)
reloc_init,
#endif
board_init,
interrupt_init,
env_init,
init_baudrate,
serial_init,
console_init_f,
display_banner,
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo,
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard,
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,
#endif
dram_init,
display_dram_config,
NULL,
};
经查找在display_banner这个函数中出现第一次打印 U-Boot 1.3.4 (Nov 9 2011 - 17:00:35) for SMDK2416(这个是靠上面的方法定位出来的)。
2:在print_cpuinfo(这个函数原型在cpu/s3c24xx/s3c2416/speed.c)这个函数中出现了《这里说明一下,
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo,
#endif
这个宏可以在最初的配置.h文件中或者本文件或者别的地方找到,可以配合source insight查找是否定义
》
int print_cpuinfo(void)
{
int i;
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
printf ("\n^_^");
printf("\nCPU: S3C2416@%dMHz\n", get_ARMCLK()/1000000);
printf(" Fclk = %dMHz, Hclk = %dMHz, Pclk = %dMHz\n",
get_FCLK()/1000000, get_HCLK()/1000000, get_PCLK()/1000000);
return 0;
}
3:在checkboard(board/samsung/smdk2416、smdk2416.c)这个函数中
int checkboard(void)
{
printf("^_^\n");
int i;
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
vu_long *mem_reg = (vu_long*) 0x48000000;
printf("Board: SMDK2416 ");
switch ((*mem_reg>>1) & 0x7) {
case 0:
puts("SDRAM\n");
break;
case 1:
puts("DDR2\n");
break;
case 2:
puts("Mobile SDRAM\n");
break;
case 4:
puts("DDR\n");
break;
case 6:
puts("Mobile DDR\n");
break;
default:
puts("unknown Memory Type\n");
}
return (0);
}
4:在display_dram_config(当前文件)函数中
static int display_dram_config (void)
{
int i;
#ifdef DEBUG
puts ("RAM Configuration:\n");
for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
printf ("Bank #%d: lx ", i, gd->bd->bi_dram[i].start);
print_size (gd->bd->bi_dram[i].size, "\n");
}
#else
ulong size = 0;
for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
size += gd->bd->bi_dram[i].size;
}
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
printf ("\n^_^\n");
puts("DRAM: ");
print_size(size, "\n");
#endif
return (0);
}
5:继续查看这个void start_armboot (void)
#if defined(CONFIG_NAND)
int i;
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
puts ("^_^\n");
puts("NAND: ");
nand_init();
#endif //CONFIG_NAND
#if defined(CONFIG_ONENAND)
puts("OneNAND: ");
onenand_init();
#endif //CONFIG_ONENAND
#if defined(CONFIG_BOOT_MOVINAND)
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
puts ("^_^\n");
puts("SD/MMC: ");
if ((0x24564236 == magic[0]) && (0x20764316 == magic[1])) {
printf("Boot up for burning\n");
} else {
movi_set_capacity();
movi_set_ofs(MOVI_TOTAL_BLKCNT);
movi_init();
}
#if defined(CONFIG_SMDK2416)
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
puts ("^_^\n");
printf("After SD/MMC boot\n");
#endif
6:在接下来的env_relocate ();这个函数中打印*** Warning - bad CRC or moviNAND, using default environment
void env_relocate (void)
{
//by jingyu
int i;
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
puts ("^_^\n");
DEBUGF ("%s[%d] offset = 0x%lx\n", __FUNCTION__,__LINE__,
gd->reloc_off);
#ifdef CONFIG_AMIGAONEG3SE
enable_nvram();
#endif
#ifdef ENV_IS_EMBEDDED
env_ptr = (env_t *)((ulong)env_ptr + gd->reloc_off);
DEBUGF ("%s[%d] embedded ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
#else
env_ptr = (env_t *)malloc (CFG_ENV_SIZE);
DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
#endif
if (gd->env_valid == 0) {
#if defined(CONFIG_GTH) || defined(CFG_ENV_IS_NOWHERE)
puts ("Using default environment\n\n");
#else
puts ("*** Warning - bad CRC, using default environment\n\n");
show_boot_progress (-60);
#endif
set_default_env();
}
else {
env_relocate_spec ();
}
gd->env_addr = (ulong)&(env_ptr->data);
#ifdef CONFIG_AMIGAONEG3SE
disable_nvram();
#endif
}
#ifdef CONFIG_AUTO_COMPLETE
int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
{
int i, nxt, len, vallen, found;
const char *lval, *rval;
found = 0;
cmdv[0] = NULL;
len = strlen(var);
for (i=0; env_get_char(i) != '\0'; i=nxt+1) {
for (nxt=i; env_get_char(nxt) != '\0'; ++nxt)
;
lval = (char *)env_get_addr(i);
rval = strchr(lval, '=');
if (rval != NULL) {
vallen = rval - lval;
rval++;
} else
vallen = strlen(lval);
if (len > 0 && (vallen < len || memcmp(lval, var, len) != 0))
continue;
if (found >= maxv - 2 || bufsz < vallen + 1) {
cmdv[found++] = "...";
break;
}
cmdv[found++] = buf;
memcpy(buf, lval, vallen); buf += vallen; bufsz -= vallen;
*buf++ = '\0'; bufsz--;
}
cmdv[found] = NULL;
return found;
}
7:在接下来的console_init_r (); 函数 // common/console.c
//by jingyu
int console_init_r (void)
{
device_t *inputdev = NULL, *outputdev = NULL;
int i, items = ListNumItems (devlist);
#ifdef CONFIG_SPLASH_SCREEN
if (getenv("splashimage") != NULL)
gd->flags |= GD_FLG_SILENT;
#endif
for (i = 1;
(i <= items) && ((inputdev == NULL) || (outputdev == NULL));
i++
) {
device_t *dev = ListGetPtrToItem (devlist, i);
if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
inputdev = dev;
}
if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
outputdev = dev;
}
}
if (outputdev != NULL) {
console_setfile (stdout, outputdev);
console_setfile (stderr, outputdev);
}
if (inputdev != NULL) {
console_setfile (stdin, inputdev);
}
gd->flags |= GD_FLG_DEVINIT;
#ifndef CFG_CONSOLE_INFO_QUIET
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
puts ("^_^\n");
puts ("In: ");
if (stdio_devices[stdin] == NULL) {
puts ("No input devices available!\n");
} else {
printf ("%s\n", stdio_devices[stdin]->name);
}
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
puts ("^_^\n");
puts ("Out: ");
if (stdio_devices[stdout] == NULL) {
puts ("No output devices available!\n");
} else {
printf ("%s\n", stdio_devices[stdout]->name);
}
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
puts ("^_^\n");
puts ("Err: ");
if (stdio_devices[stderr] == NULL) {
puts ("No error devices available!\n");
} else {
printf ("%s\n", stdio_devices[stderr]->name);
}
#endif
for (i = 0; i < 3; i++) {
setenv (stdio_names[i], stdio_devices[i]->name);
}
#if 0
if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
return (0);
#endif
return (0);
}
8:在接下来#ifdef CONFIG_DRIVER_SMC911X(网卡型号) smx911x_handle_mac_address(gd->bd); (driver/smc911xdxl.c)
int smx911x_handle_mac_address(bd_t *bd)
{
unsigned long addrh, addrl;
unsigned char *m = bd->bi_enetaddr;
if ((m[0] | m[1] | m[2] | m[3] | m[4] | m[5])) {
addrl = m[0] | m[1] << 8 | m[2] << 16 | m[3] << 24;
addrh = m[4] | m[5] << 8;
smc911x_set_mac_csr(ADDRH, addrh);
smc911x_set_mac_csr(ADDRL, addrl);
} else {
addrh = smc911x_get_mac_csr(ADDRH);
addrl = smc911x_get_mac_csr(ADDRL);
m[0] = (addrl ) & 0xff;
m[1] = (addrl >> 8 ) & 0xff;
m[2] = (addrl >> 16 ) & 0xff;
m[3] = (addrl >> 24 ) & 0xff;
m[4] = (addrh ) & 0xff;
m[5] = (addrh >> 8 ) & 0xff;
if ((m[0] & m[1] & m[2] & m[3] & m[4] & m[5]) == 0xff) {
printf(DRIVERNAME ": no valid mac address in environment "
"and no eeprom found\n");
return -1;
}
}
//by jingyu
int i;
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
printf ("^_^\n");
printf(DRIVERNAME ": MAC x:x:x:x:x:x\n",
m[0], m[1], m[2], m[3], m[4], m[5]);
return 0;
}
9:然后程序就走到了这里
for (;;) {
main_loop ();
}
10:进入main_loop ();在common/main.c中 这个文件大家很熟悉。
11:if (bootdelay >= 0 && s && !abortboot (bootdelay)) { //into static __inline__ int abortboot(int bootdelay)
# ifdef CONFIG_AUTOBOOT_KEYED
int prev = disable_ctrlc(1);
# endif
在上面的语句中abortboot (bootdelay)) 这个函数就是等待3秒那个
static __inline__ int abortboot(int bootdelay)
{
int abort = 0;
#ifdef CONFIG_MENUPROMPT
printf(CONFIG_MENUPROMPT);
#else
printf("Hit any key to stop autoboot: - ", bootdelay);
#endif
#if defined CONFIG_ZERO_BOOTDELAY_CHECK
if (bootdelay >= 0) {
if (tstc()) {
(void) getc();
puts ("\b\b\b 0");
abort = 1;
}
}
#endif
while ((bootdelay > 0) && (!abort)) {
int i;
--bootdelay;
for (i=0; !abort && i<100; ++i) {
if (tstc()) {
abort = 1;
bootdelay = 0;
# ifdef CONFIG_MENUKEY
menukey = getc();
# else
(void) getc();
# endif
break;
}
udelay(10000);
}
printf("\b\b\b- ", bootdelay);
}
putc('\n');
#ifdef CONFIG_SILENT_CONSOLE
if (abort)
gd->flags &= ~GD_FLG_SILENT;
#endif
//by jingyu
int i;
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
printf("^_^\n");
return abort;
}
12:找到run_command(s,0);
if (bootdelay >= 0 && s && !abortboot (bootdelay)) { //into static __inline__ int abortboot(int bootdelay)
# ifdef CONFIG_AUTOBOOT_KEYED
int prev = disable_ctrlc(1);
# endif
# ifndef CFG_HUSH_PARSER
run_command (s, 0);
# else
//<===================================
parse_string_outer(s, FLAG_PARSE_SEMICOLON |
FLAG_EXIT_FROM_LOOP);
# endif
13:在程序中 run_command(s,0);这个函数会调用输入的或者非输入的命令
通过下面的这个东西注册common/cmd_nand.c里
U_BOOT_CMD(
nboot, 4, 1, do_nandboot,
"nboot - boot from NAND device\n",
"loadAddr dev\n"
);
14在cmd_nand.c这个文件里
if (scrub) {
puts("Warning: "
"scrub option will erase all factory set "
"bad blocks!\n"
" "
"There is no reliable way to recover them.\n"
" "
"Use this command only for testing purposes "
"if you\n"
" "
"are sure of what you are doing!\n"
"\nReally scrub this NAND flash? <y/N>\n");
opts.scrub = 1;
}
ret = nand_erase_opts(nand, &opts);
printf("%s\n", ret ? "ERROR" : "OK");
//by jingyu
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
printf ("^_^\n");
15:
if (read) {
nand_read_options_t opts;
memset(&opts, 0, sizeof(opts));
opts.buffer = (u_char*) addr;
opts.length = size;
opts.offset = off;
opts.quiet = quiet;
ret = nand_read_opts(nand, &opts);
} else {
nand_write_options_t opts;
memset(&opts, 0, sizeof(opts));
opts.buffer = (u_char*) addr;
opts.length = size;
opts.offset = off;
opts.pad = 1;
opts.blockalign = 1;
opts.quiet = quiet;
ret = nand_write_opts(nand, &opts);
}
#ifdef CFG_NAND_YAFFS_WRITE
} else if (!read && s != NULL && + (!strcmp(s, ".yaffs") || !strcmp(s, ".yaffs1"))) {
nand_write_options_t opts;
memset(&opts, 0, sizeof(opts));
opts.buffer = (u_char*) addr;
opts.length = size;
opts.offset = off;
opts.pad = 0;
opts.blockalign = 1;
opts.quiet = quiet;
opts.writeoob = 1;
opts.autoplace = 1;
ret = nand_write_opts(nand, &opts);
#endif
} else {
if (read)
ret = nand_read(nand, off, &size, (u_char *)addr);
else {
ret = nand_write(nand, off, &size, (u_char *)addr);
if (ret == 0) {
uint *magic = (uint*)(PHYS_SDRAM_1);
if ((0x24564236 == magic[0]) && (0x20764316 == magic[1]))
magic[0] = 0x27051956;
}
}
}
printf(" %d bytes %s: %s\n", size,
read ? "read" : "written", ret ? "ERROR" : "OK");
//by jingyu
GPDCON_REG = 0x55555555;
GPDDAT_REG = 0x0;
for(i=0; i<1000; i++)udelay(500);
GPDDAT_REG = 0xffffffff;
for(i=0; i<1000; i++)udelay(500);
printf ("^_^\n");
return ret == 0 ? 0 : 1;
}
###############以下是SDboot启动第二阶段的整个流程其中有打印信息为调试################################
OK
^_^
U-Boot 1.3.4 (Nov 9 2011 - 17:00:35) for SMDK2416
^_^
^_^
CPU: S3C2416@400MHz
Fclk = 800MHz, Hclk = 133MHz, Pclk = 66MHz
^_^
Board: SMDK2416 DDR2
^_^
DRAM: 64 MB
^_^
Flash: 1 MB
^_^
NAND: 128 MB
^_^
SD/MMC: 1887 MB
^_^
After SD/MMC boot
^_^
*** Warning - bad CRC or moviNAND, using default environment
^_^
In: serial
^_^
Out: serial
^_^
Err: serial
^_^
smc911x: MAC 00:40:5c:26:0a:5b
Hit any key to stop autoboot: 0
^_^
NAND scrub: device 0 whole chip
Warning: scrub option will erase all factory set bad blocks!
There is no reliable way to recover them.
Use this command only for testing purposes if you
are sure of what you are doing!
Really scrub this NAND flash? <y/N>
Erasing at 0x5ea0000 -- 74% complete.
NAND 128MiB 3,3V 8-bit: MTD Erase failure: -5
Erasing at 0x7fe0000 -- 100% complete.
Scanning device for bad blocks
s3c-nand: ECC uncorrectable error detected
s3c-nand: ECC uncorrectable error detected
OK
^_^
NAND erase: device 0 whole chip
Skipping bad block at 0x05fe0000
Erasing at 0x7fe0000 -- 100% complete.
OK
^_^
Reading data from sector 3800000 (512 sectors).. completed
NAND write: device 0 offset 0x0, size 0x40000
262144 bytes written: OK
^_^
Reading kernel from sector 3853262 (8192 sectors).. completed
NAND write: device 0 offset 0x40000, size 0x200000
2097152 bytes written: OK
^_^
Reading data from sector 3600000 (114688 sectors).. completed
NAND write: device 0 offset 0x400000, size 0x35db4c0
Writing data at 0x3839000 -- 100% complete.
56472768 bytes written: OK
^_^
原文出处:
http://blog.sina.com.cn/s/blog_6d2a0a1a0100zyo1.html