u-boot原理分析第二课-------UBOOT第二阶段

原博客:https://blog.csdn.net/xiaokangdream/article/details/79588088

版权声明: https://blog.csdn.net/xiaokangdream/article/details/79588088

    我们之前讲到的UBOOT的第一阶段初始化,都是一些硬件的操作,之后的操作便在比较复杂的函数中去实现了,也是我们上节课讲到的:

    这里把_start_armboot的地址赋值给pc,而_start_armboot的地址为:

    也就是跳到start_armboot这个地址里。这应该是一个函数,我们看看这个函数的定义:


   
   
  1. void start_armboot (void)
  2. {
  3. init_fnc_t **init_fnc_ptr;
  4. char *s;
  5. #ifndef CFG_NO_FLASH
  6. ulong size;
  7. #endif
  8. #if defined(CONFIG_VFD) || defined(CONFIG_LCD)
  9. unsigned long addr;
  10. #endif
  11. /* Pointer is writable since we allocated a register for it */
  12. gd = ( gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof( gd_t));
  13. /* compiler optimization barrier needed for GCC >= 3.4 */
  14. __asm__ __volatile__( "": : : "memory");
  15. memset (( void*)gd, 0, sizeof ( gd_t));
  16. gd->bd = ( bd_t*)(( char*)gd - sizeof( bd_t));
  17. memset (gd->bd, 0, sizeof ( bd_t));
  18. monitor_flash_len = _bss_start - _armboot_start;
  19. for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
  20. if ((*init_fnc_ptr)() != 0) {
  21. hang ();
  22. }
  23. }
  24. #ifndef CFG_NO_FLASH
  25. /* configure available FLASH banks */
  26. size = flash_init ();
  27. display_flash_config (size);
  28. #endif /* CFG_NO_FLASH */
  29. #ifdef CONFIG_VFD
  30. # ifndef PAGE_SIZE
  31. # define PAGE_SIZE 4096
  32. # endif
  33. /*
  34. * reserve memory for VFD display (always full pages)
  35. */
  36. /* bss_end is defined in the board-specific linker script */
  37. addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
  38. size = vfd_setmem (addr);
  39. gd->fb_base = addr;
  40. #endif /* CONFIG_VFD */
  41. #ifdef CONFIG_LCD
  42. # ifndef PAGE_SIZE
  43. # define PAGE_SIZE 4096
  44. # endif
  45. /*
  46. * reserve memory for LCD display (always full pages)
  47. */
  48. /* bss_end is defined in the board-specific linker script */
  49. addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
  50. size = lcd_setmem (addr);
  51. gd->fb_base = addr;
  52. #endif /* CONFIG_LCD */
  53. /* armboot_start is defined in the board-specific linker script */
  54. mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
  55. #if (CONFIG_COMMANDS & CFG_CMD_NAND)
  56. puts ( "NAND: ");
  57. nand_init(); /* go init the NAND */
  58. #endif
  59. #ifdef CONFIG_HAS_DATAFLASH
  60. AT91F_DataflashInit();
  61. dataflash_print_info();
  62. #endif
  63. /* initialize environment */
  64. env_relocate ();
  65. #ifdef CONFIG_VFD
  66. /* must do this after the framebuffer is allocated */
  67. drv_vfd_init();
  68. #endif /* CONFIG_VFD */
  69. /* IP Address */
  70. gd->bd->bi_ip_addr = getenv_IPaddr ( "ipaddr");
  71. /* MAC Address */
  72. {
  73. int i;
  74. ulong reg;
  75. char *s, *e;
  76. char tmp[ 64];
  77. i = getenv_r ( "ethaddr", tmp, sizeof (tmp));
  78. s = (i > 0) ? tmp : NULL;
  79. for (reg = 0; reg < 6; ++reg) {
  80. gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
  81. if (s)
  82. s = (*e) ? e + 1 : e;
  83. }
  84. #ifdef CONFIG_HAS_ETH1
  85. i = getenv_r ( "eth1addr", tmp, sizeof (tmp));
  86. s = (i > 0) ? tmp : NULL;
  87. for (reg = 0; reg < 6; ++reg) {
  88. gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
  89. if (s)
  90. s = (*e) ? e + 1 : e;
  91. }
  92. #endif
  93. }
  94. devices_init (); /* get the devices list going. */
  95. #ifdef CONFIG_CMC_PU2
  96. load_sernum_ethaddr ();
  97. #endif /* CONFIG_CMC_PU2 */
  98. jumptable_init ();
  99. console_init_r (); /* fully init console as a device */
  100. #if defined(CONFIG_MISC_INIT_R)
  101. /* miscellaneous platform dependent initialisations */
  102. misc_init_r ();
  103. #endif
  104. Port_Init();
  105. if (!PreLoadedONRAM) {
  106. /* enable exceptions */
  107. enable_interrupts ();
  108. /* add by www.100ask.net */
  109. usb_init();
  110. }
  111. /* Perform network card initialisation if necessary */
  112. #ifdef CONFIG_DRIVER_CS8900
  113. cs8900_get_enetaddr (gd->bd->bi_enetaddr);
  114. #endif
  115. #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
  116. if (getenv ( "ethaddr")) {
  117. smc_set_mac_addr(gd->bd->bi_enetaddr);
  118. }
  119. #endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
  120. /* Initialize from environment */
  121. if ((s = getenv ( "loadaddr")) != NULL) {
  122. load_addr = simple_strtoul (s, NULL, 16);
  123. }
  124. #if (CONFIG_COMMANDS & CFG_CMD_NET)
  125. if ((s = getenv ( "bootfile")) != NULL) {
  126. copy_filename (BootFile, s, sizeof (BootFile));
  127. }
  128. #endif /* CFG_CMD_NET */
  129. #ifdef BOARD_LATE_INIT
  130. board_late_init ();
  131. #endif
  132. #if (CONFIG_COMMANDS & CFG_CMD_NET)
  133. #if defined(CONFIG_NET_MULTI)
  134. puts ( "Net: ");
  135. #endif
  136. eth_initialize(gd->bd);
  137. #endif
  138. /* main_loop() can return to retry autoboot, if so just run it again. */
  139. for (;;) {
  140. main_loop ();
  141. }
  142. /* NOTREACHED - no way out of command loop except booting */
  143. }

首先看到这里:

这里的话给gd_t这个结构体分配了空间,其实这就是给我们分配一些全局数据的内存。我们继续往下看:

这个init_sequence是什么?我们搜索一下,发现在本文件中有相关的定义:


   
   
  1. init_fnc_t *init_sequence[] = {
  2. cpu_init, /* basic cpu dependent setup */
  3. board_init, /* basic board dependent setup */
  4. interrupt_init, /* set up exceptions */
  5. env_init, /* initialize environment */
  6. init_baudrate, /* initialze baudrate settings */
  7. serial_init, /* serial communications setup */
  8. console_init_f, /* stage 1 init of console */
  9. display_banner, /* say that we are here */
  10. # if defined(CONFIG_DISPLAY_CPUINFO)
  11. print_cpuinfo, /* display cpu info (and speed) */
  12. #endif
  13. # if defined(CONFIG_DISPLAY_BOARDINFO)
  14. checkboard, /* display board info */
  15. #endif
  16. dram_init, /* configure available RAM banks */
  17. display_dram_config,
  18. NULL,
  19. };

我们发现,其里面都是一些函数指针,装有各种初始化函数:cpu的,开发版的,中断的,环境变量的,串口的等等。而这个init_sequence便是一个指针数组来的。所以,这个循环的意思就是分别执行各个初始化函数,如果返回值不为零的话,就会卡死在那里。这里我们研究一下其中的部分初始化函数,首先看到board_init:


   
   
  1. int board_init (void)
  2. {
  3. S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
  4. S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
  5. /* set up the I/O ports */
  6. gpio->GPACON = 0x007FFFFF;
  7. gpio->GPBCON = 0x00044555;
  8. gpio->GPBUP = 0x000007FF;
  9. gpio->GPCCON = 0xAAAAAAAA;
  10. gpio->GPCUP = 0x0000FFFF;
  11. gpio->GPDCON = 0xAAAAAAAA;
  12. gpio->GPDUP = 0x0000FFFF;
  13. gpio->GPECON = 0xAAAAAAAA;
  14. gpio->GPEUP = 0x0000FFFF;
  15. gpio->GPFCON = 0x000055AA;
  16. gpio->GPFUP = 0x000000FF;
  17. gpio->GPGCON = 0xFF95FFBA;
  18. gpio->GPGUP = 0x0000FFFF;
  19. gpio->GPHCON = 0x002AFAAA;
  20. gpio->GPHUP = 0x000007FF;
  21. /* support both of S3C2410 and S3C2440, by www.100ask.net */
  22. if (isS3C2410)
  23. {
  24. /* arch number of SMDK2410-Board */
  25. gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
  26. }
  27. else
  28. {
  29. /* arch number of SMDK2440-Board */
  30. gd->bd->bi_arch_number = MACH_TYPE_S3C2440;
  31. }
  32. /* adress of boot parameters */
  33. gd->bd->bi_boot_params = 0x30000100;
  34. #if 0
  35. icache_enable();
  36. dcache_enable();
  37. #endif
  38. return 0;
  39. }
我们看到,函数的前面都是做一些初始化管脚的工作,初始化完管脚后,就开始设置机器ID:

   
   
  1. /* support both of S3C2410 and S3C2440, by www.100ask.net */
  2. if (isS3C2410)
  3. {
  4. /* arch number of SMDK2410-Board */
  5. gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
  6. }
  7. else
  8. {
  9. /* arch number of SMDK2440-Board */
  10. gd->bd->bi_arch_number = MACH_TYPE_S3C2440;
  11. }

检查开发板式2410还是2440,然后分别相应的值。最后则是设置内核需要的参数的地址:


   
   
  1. /* adress of boot parameters */
  2. gd->bd->bi_boot_params = 0x30000100;

这个值后面再讲,后面会用得到的。接下来,我们回到之前的start_armboot。我们知道,u-boot最终的目的是启动内核,所以我们现在更希望找到与启动内核比较有关的代码。我们看到接下来的代码:

这一步是初始化flash,它会识别出你当前所使用的norflash。我们继续往下看:

这一步是初始化nandflash,它会扫出单板。以上步骤,都是对flash初始化,执行了上面的步骤后,才有能力对flash进行读写,是我们从flash中读出内核并执行的基础。我们继续看:

这一步是初始化环境变量。我们继续往下看:

我们看到,到这里, 就是一个死循环了,那么这个函数是什么呢?我们进去看一下:


   
   
  1. void main_loop (void)
  2. {
  3. #ifndef CFG_HUSH_PARSER
  4. static char lastcommand[CFG_CBSIZE] = { 0, };
  5. int len;
  6. int rc = 1;
  7. int flag;
  8. #endif
  9. #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
  10. char *s;
  11. int bootdelay;
  12. #endif
  13. #ifdef CONFIG_PREBOOT
  14. char *p;
  15. #endif
  16. #ifdef CONFIG_BOOTCOUNT_LIMIT
  17. unsigned long bootcount = 0;
  18. unsigned long bootlimit = 0;
  19. char *bcs;
  20. char bcs_set[ 16];
  21. #endif /* CONFIG_BOOTCOUNT_LIMIT */
  22. #if defined(CONFIG_VFD) && defined(VFD_TEST_LOGO)
  23. ulong bmp = 0; /* default bitmap */
  24. extern int trab_vfd (ulong bitmap);
  25. #ifdef CONFIG_MODEM_SUPPORT
  26. if (do_mdm_init)
  27. bmp = 1; /* alternate bitmap */
  28. #endif
  29. trab_vfd (bmp);
  30. #endif /* CONFIG_VFD && VFD_TEST_LOGO */
  31. #ifdef CONFIG_BOOTCOUNT_LIMIT
  32. bootcount = bootcount_load();
  33. bootcount++;
  34. bootcount_store (bootcount);
  35. sprintf (bcs_set, "%lu", bootcount);
  36. setenv ( "bootcount", bcs_set);
  37. bcs = getenv ( "bootlimit");
  38. bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0;
  39. #endif /* CONFIG_BOOTCOUNT_LIMIT */
  40. #ifdef CONFIG_MODEM_SUPPORT
  41. debug ( "DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init);
  42. if (do_mdm_init) {
  43. char *str = strdup(getenv( "mdm_cmd"));
  44. setenv ( "preboot", str); /* set or delete definition */
  45. if (str != NULL)
  46. free (str);
  47. mdm_init(); /* wait for modem connection */
  48. }
  49. #endif /* CONFIG_MODEM_SUPPORT */
  50. #ifdef CONFIG_VERSION_VARIABLE
  51. {
  52. extern char version_string[];
  53. setenv ( "ver", version_string); /* set version variable */
  54. }
  55. #endif /* CONFIG_VERSION_VARIABLE */
  56. #ifdef CFG_HUSH_PARSER
  57. u_boot_hush_start ();
  58. #endif
  59. #ifdef CONFIG_AUTO_COMPLETE
  60. install_auto_complete();
  61. #endif
  62. #ifdef CONFIG_JFFS2_CMDLINE
  63. extern int mtdparts_init(void);
  64. if (!getenv( "mtdparts"))
  65. {
  66. run_command( "mtdparts default", 0);
  67. }
  68. else
  69. {
  70. mtdparts_init();
  71. }
  72. #endif
  73. #ifdef CONFIG_PREBOOT
  74. if ((p = getenv ( "preboot")) != NULL) {
  75. # ifdef CONFIG_AUTOBOOT_KEYED
  76. int prev = disable_ctrlc( 1); /* disable Control C checking */
  77. # endif
  78. # ifndef CFG_HUSH_PARSER
  79. run_command (p, 0);
  80. # else
  81. parse_string_outer(p, FLAG_PARSE_SEMICOLON |
  82. FLAG_EXIT_FROM_LOOP);
  83. # endif
  84. # ifdef CONFIG_AUTOBOOT_KEYED
  85. disable_ctrlc(prev); /* restore Control C checking */
  86. # endif
  87. }
  88. #endif /* CONFIG_PREBOOT */
  89. #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
  90. s = getenv ( "bootdelay");
  91. bootdelay = s ? ( int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
  92. debug ( "### main_loop entered: bootdelay=%d\n\n", bootdelay);
  93. # ifdef CONFIG_BOOT_RETRY_TIME
  94. init_cmd_timeout ();
  95. # endif /* CONFIG_BOOT_RETRY_TIME */
  96. if (PreLoadedONRAM) {
  97. printf( "Use these steps to program the image to flash:\n");
  98. printf( "1. In OpenOCD\n");
  99. printf( " Run the 'halt' command to halt u-boot\n");
  100. printf( " Run the 'load_image <file> <address>' command to load file to SDRAM\n");
  101. printf( " Run the 'resume' command to resume u-boot\n");
  102. printf( "2. In u-boot, use the flash commands to program the image to flash\n");
  103. printf( "Or, use the tftp or nfs command to download file, and then program the flash.\n");
  104. goto PROMPT;
  105. }
  106. #ifdef CONFIG_BOOTCOUNT_LIMIT
  107. if (bootlimit && (bootcount > bootlimit)) {
  108. printf ( "Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
  109. ( unsigned)bootlimit);
  110. s = getenv ( "altbootcmd");
  111. }
  112. else
  113. #endif /* CONFIG_BOOTCOUNT_LIMIT */
  114. s = getenv ( "bootcmd");
  115. debug ( "### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
  116. if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
  117. # ifdef CONFIG_AUTOBOOT_KEYED
  118. int prev = disable_ctrlc( 1); /* disable Control C checking */
  119. # endif
  120. # ifndef CFG_HUSH_PARSER
  121. {
  122. printf( "Booting Linux ...\n");
  123. run_command (s, 0);
  124. }
  125. # else
  126. parse_string_outer(s, FLAG_PARSE_SEMICOLON |
  127. FLAG_EXIT_FROM_LOOP);
  128. # endif
  129. # ifdef CONFIG_AUTOBOOT_KEYED
  130. disable_ctrlc(prev); /* restore Control C checking */
  131. # endif
  132. }
  133. # ifdef CONFIG_MENUKEY
  134. if (menukey == CONFIG_MENUKEY) {
  135. s = getenv( "menucmd");
  136. if (s) {
  137. # ifndef CFG_HUSH_PARSER
  138. run_command (s, 0);
  139. # else
  140. parse_string_outer(s, FLAG_PARSE_SEMICOLON |
  141. FLAG_EXIT_FROM_LOOP);
  142. # endif
  143. }
  144. }
  145. #endif /* CONFIG_MENUKEY */
  146. #endif /* CONFIG_BOOTDELAY */
  147. #ifdef CONFIG_AMIGAONEG3SE
  148. {
  149. extern void video_banner(void);
  150. video_banner();
  151. }
  152. #endif
  153. eth_init(gd->bd);
  154. run_command( "menu", 0);
  155. /*
  156. * Main Loop for Monitor Command Processing
  157. */
  158. PROMPT:
  159. #ifdef CFG_HUSH_PARSER
  160. parse_file_outer();
  161. /* This point is never reached */
  162. for (;;);
  163. #else
  164. for (;;) {
  165. #ifdef CONFIG_BOOT_RETRY_TIME
  166. if (rc >= 0) {
  167. /* Saw enough of a valid command to
  168. * restart the timeout.
  169. */
  170. reset_cmd_timeout();
  171. }
  172. #endif
  173. len = readline (CFG_PROMPT);
  174. flag = 0; /* assume no special flags for now */
  175. if (len > 0)
  176. strcpy (lastcommand, console_buffer);
  177. else if (len == 0)
  178. flag |= CMD_FLAG_REPEAT;
  179. #ifdef CONFIG_BOOT_RETRY_TIME
  180. else if (len == -2) {
  181. /* -2 means timed out, retry autoboot
  182. */
  183. puts ( "\nTimed out waiting for command\n");
  184. # ifdef CONFIG_RESET_TO_RETRY
  185. /* Reinit board to run initialization code again */
  186. do_reset ( NULL, 0, 0, NULL);
  187. # else
  188. return; /* retry autoboot */
  189. # endif
  190. }
  191. #endif
  192. if (len == -1)
  193. puts ( "<INTERRUPT>\n");
  194. else
  195. rc = run_command (lastcommand, flag);
  196. if (rc <= 0) {
  197. /* invalid command or not repeatable, forget it */
  198. lastcommand[ 0] = 0;
  199. }
  200. }
  201. #endif /*CFG_HUSH_PARSER*/
  202. }

我们看到这里:

这里首先获得bootcmd的环境变量值,然后打印出相关的信息:我们看一下bootcmd的环境变量值是多少:

我们大概可以推测,这是一条启动内核的两条指令。我们再看下面的代码:

这里是倒计时,。如果在这个倒数计时没到达到0 之前,没有输入空格键,就会打印下面的信息:

也就执行run_command(s,0),这个命令的具体内容下节课讲。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值