利用打印法和点灯法追踪UBOOT第二阶段启动流程

13 篇文章 0 订阅
7 篇文章 0 订阅
 

打印法:前段用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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值