您的位置:首页 > 其它

u-boot-2011.09在ST2410上启动流程分析

2014-05-29 16:49 459 查看
转载至:http://blog.csdn.net/webhack/article/details/7175344

u-boot-2011.09在ST2410上启动流程分析

作者:mutes

u-boot版本:u-boot-2011.09

分析时间:2011.10.26

源码下载地址:ftp://ftp.denx.de/pub/u-boot/u-boot-2011.09.tar.bz2

参考文献:http://www.linuxidc.com/Linux/2011-07/39310.htm (源于该文件修改)

       u-boot支持许多CPU,以及一些常见的开发板。在前面的文章中已经对u-boot1.1.6作了详细的分析,在本文以u-boot-2011.09这个最新版本为例,再来简要介绍一下u-boot在smdk2410上的启动流程。   

      首先系统是从arch/arm/cpu/arm920t目录下的start.s文件开始执行,并且实际开始执行的代码是从第117行开始:

117 start_code:

118         /*

119          * set the cpu to SVC32 mode

120          */

121         mrs     r0, cpsr

122         bic     r0, r0, #0x1f

123         orr     r0, r0, #0xd3

124         msr     cpsr, r0

上述代码的含义是设置cpu为SVC32模式,即超级保护模式,用于操作系统使用。

140 #ifdef CONFIG_S3C24X0

141         /* turn off the watchdog */

142 

143 # if defined(CONFIG_S3C2400)

144 #  define pWTCON        0x15300000

145 #  define INTMSK        0x14400008      /* Interrupt-Controller base addresses */

146 #  define CLKDIVN       0x14800014      /* clock divisor register */

147 #else

148 #  define pWTCON        0x53000000

149 #  define INTMSK        0x4A000008      /* Interrupt-Controller base addresses */

150 #  define INTSUBMSK     0x4A00001C

151 #  define CLKDIVN       0x4C000014      /* clock divisor register */

152 # endif

153 

154         ldr     r0, =pWTCON

155         mov     r1, #0x0

156         str     r1, [r0]

157 

158         /*

159          * mask all IRQs by setting all bits in the INTMR - default

160          */

161         mov     r1, #0xffffffff

162         ldr     r0, =INTMSK

163         str     r1, [r0]

164 # if defined(CONFIG_S3C2410)

165         ldr     r1, =0x3ff

166         ldr     r0, =INTSUBMSK

167         str     r1, [r0]

168 # endif

169 

170         /* FCLK:HCLK:PCLK = 1:2:4 */

171         /* default FCLK is 120 MHz ! */

172         ldr     r0, =CLKDIVN

173         mov     r1, #3

174         str     r1, [r0]

175 #endif  /* CONFIG_S3C24X0 */

该段代码的含义为,先定义几个需要的寄存器,然后关闭开门狗定时器,以及屏蔽所有中断和子中断,最后设置三个时钟频率之间的比值。

181 #ifndef CONFIG_SKIP_LOWLEVEL_INIT

182         bl      cpu_init_crit

183 #endif

在第182行中,程序跳转到cpu_init_crit中,它也是在start.s文件中,函数的位置在第328行至第356行,它的作用是设置一些重要的寄存器(如MMU和caches等)以及内存时序。其中在第353行,程序又跳转到了lowlevel_init函数,它是在board/samsung/smdk2410目录下的lowlevel_init.s文件中定义的,这个文件的目的就是为了设置内存的时序。

186 call_board_init_f:

187         ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)

188         bic     sp, sp, #7 /* 8-byte alignment for ABI compliance */

189         ldr     r0,=0x00000000

190         bl      board_init_f

从cpu_init_crit返回后,来到了调用board_init_f的函数处。首先进行堆栈的设置,然后就跳转到board_init_f函数,其中传递给该函数的参数为0。board_init_f这个函数是在arch/arm/lib目录下的board.c文件内定义的,函数的位置是在第268行至第422行,它的作用是初始化开发板。需要注意的是,此时程序是在flash中运行的。

下面我们就来分析board_init_f函数。

269         /* Pointer is writable since we allocated a register for it */

270         gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);

271         /* compiler optimization barrier needed for GCC >= 3.4 */

272         __asm__ __volatile__("": : :"memory");

273 

274         memset((void *)gd, 0, sizeof(gd_t));

275 

276         gd->mon_len = _bss_end_ofs;

277 

gd是一个保存在ARM的r8寄存器中的gd_t结构体的指针,该结构体包括了u-boot中所有重要的全局变量,它是在arch/arm/include/asm目录下的global_data.h文件内被定义的。上述代码的作用是为gd分配地址,并清零,最后得到整个u-boot的长度。

278         for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {

279                 if ((*init_fnc_ptr)() != 0) {

280                         hang ();

281                 }

282         }

上述代码的作用是循环调用init_sequence函数指针数组中的成员,该数组成员函数主要完成一些初始化的工作,如:

board_early_init_f函数(在board/samsung/smdk2410目录下的smdk2410.c文件内)完成ARM的时钟频率和IO的设置;

timer_init函数(在arch/arm/cpu/arm920t/s3c24x0目录下的timer.c文件内)完成定时器4的设置;

env_init函数(在common目录下的env_flash.c文件内,因为include/configs/smdk2410.h中定义了CONFIG_ENV_IS_IN_FLASH)完成环境变量的设置;

init_baudrate函数(在arch/arm/lib目录下的board.c文件内)完成波特率的设置;

serial_init函数(在drivers/serial目录下的serial_s3c24x0.c文件内,因为include/configs/smdk2410.h中定义了CONFIG_S3C24X0_SERIAL)完成串口通讯的设置;

console_init_f函数(在common目录下的console.c文件内)完成第一阶段的控制台初始化;

display_banner函数(在arch/arm/lib目录下的board.c文件内)用来打印输出一些信息;

dram_init函数(在board/samsung/smdk2410目录下的smdk2410.c文件内)用来配置SDRAM的大小。

 

303         addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;

得到SDRAM的末位物理地址为0x3400 0000,即SDRAM的空间分布为0x3000 0000~0x33FF FFFF。

325 #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))

326         /* reserve TLB table */

327         addr -= (4096 * 4);

328 

329         /* round down to next 64 kB limit */

330         addr &= ~(0x10000 - 1);

331 

332         gd->tlb_addr = addr;

333         debug("TLB table at: %08lx\n", addr);

334 #endif

335 

336         /* round down to next 4 kB limit */

337         addr &= ~(4096 - 1);

338         debug("Top of RAM usable for U-Boot at: %08lx\n", addr);

分配SDRAM的高64kB区域作为TLB,即0x33FF 0000~0x33FF FFFF,并且该区域也被用于U-Boot。

350         /*

351          * reserve memory for U-Boot code, data & bss

352          * round down to next 4 kB limit

353          */

354         addr -= gd->mon_len;

355         addr &= ~(4096 - 1);

356 

357         debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);

分配SDRAM的下一个单元为U-Boot代码段、数据段及BSS段。

359 #ifndef CONFIG_SPL_BUILD

360         /*

361          * reserve memory for malloc() arena

362          */

363         addr_sp = addr - TOTAL_MALLOC_LEN;

364         debug("Reserving %dk for malloc() at: %08lx\n",

365                         TOTAL_MALLOC_LEN >> 10, addr_sp);

366         /*

367          * (permanently) allocate a Board Info struct

368          * and a permanent copy of the "global" data

369          */

370         addr_sp -= sizeof (bd_t);

371         bd = (bd_t *) addr_sp;

372         gd->bd = bd;

373         debug("Reserving %zu Bytes for Board Info at: %08lx\n",

374                         sizeof (bd_t), addr_sp);

375 

376 #ifdef CONFIG_MACH_TYPE

377         gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */

378 #endif

379 

380         addr_sp -= sizeof (gd_t);

381         id = (gd_t *) addr_sp;

382         debug("Reserving %zu Bytes for Global Data at: %08lx\n",

383                         sizeof (gd_t), addr_sp);

384 

385         /* setup stackpointer for exeptions */

386         gd->irq_sp = addr_sp;

387 #ifdef CONFIG_USE_IRQ

388         addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);

389         debug("Reserving %zu Bytes for IRQ stack at: %08lx\n",

390                 CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);

391 #endif

392         /* leave 3 words for abort-stack    */

393         addr_sp -= 12;

394 

395         /* 8-byte alignment for ABI compliance */

396         addr_sp &= ~0x07;

397 #else

398         addr_sp += 128; /* leave 32 words for abort-stack   */

399         gd->irq_sp = addr_sp;

400 #endif

401 

402         debug("New Stack Pointer is: %08lx\n", addr_sp);

第363行的意思为在SDRAM中又开辟了一块malloc空间,该区域是紧挨着上面定义的U-Boot区域的下面。然后在SDRAM中又分别依次定义了bd结构体空间、gd结构体空间和3个字大小的异常中断堆空间。其中bd结构体的数据原型为bd_t数据结构,它表示的是“板级信息”结构体,这些信息包括开发板的波特率、IP地址、ID、以及DRAM等信息,它是在arch/arm/include/asm目录下的u-boot.h文件中定义的。下图详细描述了SDRAM的空间分配情况:





409         gd->bd->bi_baudrate = gd->baudrate;

410         /* Ram ist board specific, so move it to board code ... */

411         dram_init_banksize();

412         display_dram_config();  /* and display it */

413 

414         gd->relocaddr = addr;

415         gd->start_addr_sp = addr_sp;

416         gd->reloc_off = addr - _TEXT_BASE;

417         debug("relocation Offset is: %08lx\n", gd->reloc_off);

上述代码主要的作用是为gd结构体赋值,其中display_dram_config函数的作用是计算SDRAM的大小,并把它通过串口显示在控制台上。

418         memcpy(id, (void *)gd, sizeof(gd_t));

419 

420         relocate_code(addr_sp, id, addr);

在board_init_f函数的最后是跳转到relocate_code函数体内,这个函数是在arch/arm/cpu/arm920t目录下的start.s文件内,也就是说从最开始的start.s跳到board.c,又从board.c跳回到了start.s中,这是因为此时程序需要重定向,即把代码从flash中搬运到ram中,这个过程是需要汇编这个低级语言来完成的。传递给relocate_code函数的三个参数分别栈顶地址、数据ID(即全局结构gd)在SDRAM中的起始地址和在SDRAM中存储U-Boot的起始地址。需要注意的是relocate_code函数执行完后,并不会返回到relocate_code
(addr_sp, id, addr);的下一条语句继续执行。

 

下面我们再回到start.s文件:

201         .globl  relocate_code

202 relocate_code:

203         mov     r4, r0  /* save addr_sp */

204         mov     r5, r1  /* save addr of gd */

205         mov     r6, r2  /* save addr of destination */

取得三个参数,分别放入寄存器r4、r5和r6。

208 stack_setup:

209         mov     sp, r4

设置堆栈地址。

211         adr     r0, _start

212         cmp     r0, r6

213         beq     clear_bss               /* skip relocation */

214         mov     r1, r6                  /* r1 <- scratch for copy_loop */

215         ldr     r3, _bss_start_ofs

216         add     r2, r0, r3              /* r2 <- source end address         */

217 

218 copy_loop:

219         ldmia   r0!, {r9-r10}           /* copy from source address [r0]    */

220         stmia   r1!, {r9-r10}           /* copy to   target address [r1]    */

221         cmp     r0, r2                  /* until source end address [r2]    */

222         blo     copy_loop

判断U-Boot是在什么位置上,如果在SDRAM中,则直接跳到BSS段清零函数处即可;如果在FLASH中,则要把U-Boot复制到SDRAM中指定的位置处。

224 #ifndef CONFIG_SPL_BUILD

225         /*

226          * fix .rel.dyn relocations

227          */

228         ldr     r0, _TEXT_BASE          /* r0 <- Text base */

229         sub     r9, r6, r0              /* r9 <- relocation offset */

230         ldr     r10, _dynsym_start_ofs  /* r10 <- sym table ofs */

231         add     r10, r10, r0            /* r10 <- sym table in FLASH */

232         ldr     r2, _rel_dyn_start_ofs  /* r2 <- rel dyn start ofs */

233         add     r2, r2, r0              /* r2 <- rel dyn start in FLASH */

234         ldr     r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */

235         add     r3, r3, r0              /* r3 <- rel dyn end in FLASH */

236 fixloop:

237         ldr     r0, [r2]                /* r0 <- location to fix up, IN FLASH! */

238         add     r0, r0, r9              /* r0 <- location to fix up in RAM */

239         ldr     r1, [r2, #4]

240         and     r7, r1, #0xff

241         cmp     r7, #23                 /* relative fixup? */

242         beq     fixrel

243         cmp     r7, #2                  /* absolute fixup? */

244         beq     fixabs

245         /* ignore unknown type of fixup */

246         b       fixnext

247 fixabs:

248         /* absolute fix: set location to (offset) symbol value */

249         mov     r1, r1, LSR #4          /* r1 <- symbol index in .dynsym */

250         add     r1, r10, r1             /* r1 <- address of symbol in table */

251         ldr     r1, [r1, #4]            /* r1 <- symbol value */

252         add     r1, r1, r9              /* r1 <- relocated sym addr */

253         b       fixnext

254 fixrel:

255         /* relative fix: increase location by offset */

256         ldr     r1, [r0]

257         add     r1, r1, r9

258 fixnext:

259         str     r1, [r0]

260         add     r2, r2, #8              /* each rel.dyn entry is 8 bytes */

261         cmp     r2, r3

262         blo     fixloop

263 #endif

上述代码的含义是对rel.dyn进行重定向。

265 clear_bss:

266 #ifndef CONFIG_SPL_BUILD

267         ldr     r0, _bss_start_ofs

268         ldr     r1, _bss_end_ofs

269         mov     r4, r6                  /* reloc addr */

270         add     r0, r0, r4

271         add     r1, r1, r4

272         mov     r2, #0x00000000         /* clear                            */

273 

274 clbss_l:str     r2, [r0]                /* clear loop...                    */

275         add     r0, r0, #4

276         cmp     r0, r1

277         bne     clbss_l

278 

279         bl coloured_LED_init

280         bl red_led_on

281 #endif

对BSS段进行清零的函数。

287 #ifdef CONFIG_NAND_SPL

288         ldr     r0, _nand_boot_ofs

289         mov     pc, r0

290 

291 _nand_boot_ofs:

292         .word nand_boot

293 #else

294         ldr     r0, _board_init_r_ofs

295         adr     r1, _start

296         add     lr, r0, r1

297         add     lr, lr, r9

298         /* setup parameters for board_init_r */

299         mov     r0, r5          /* gd_t */

300         mov     r1, r6          /* dest_addr */

301         /* jump to it ... */

302         mov     pc, lr

303 

304 _board_init_r_ofs:

305         .word board_init_r - _start

306 #endif

由于没有定义CONFIG_NAND_SPL,所以程序是从第294行开始执行。该段代码的作用是跳转到board_init_r函数,并且给该函数传递了两个参数:全局结构gd在SDRAM中的起始地址和在SDRAM中存储U-Boot的起始地址。board_init_r函数是在arch/arm/lib目录下的board.c文件中,也就是又回到了上面执行过的board_init_f函数所在的board.c文件中。以后,程序就开始在SDRAM中运行了。

 

下面我们来分析board_init_r函数:

440 void board_init_r(gd_t *id, ulong dest_addr)

441 {

442         char *s;

443         bd_t *bd;

444         ulong malloc_start;

445 #if !defined(CONFIG_SYS_NO_FLASH)

446         ulong flash_size;

447 #endif

448 

449         gd = id;

450         bd = gd->bd;

451 

452         gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */

453 

454         monitor_flash_len = _end_ofs;

455 

456         /* Enable caches */

457         enable_caches();

458 

459         debug("monitor flash len: %08lX\n", monitor_flash_len);

460         board_init();   /* Setup chipselects */

461

上述代码的作用是对gd和bd进行赋值,其中monitor_flash_len为整个U-Boot的长度。

474 

475         /* The Malloc area is immediately below the monitor copy in DRAM */

476         malloc_start = dest_addr - TOTAL_MALLOC_LEN;

477         mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);

对SDRAM中的malloc空间进行清零初始化。

479 #if !defined(CONFIG_SYS_NO_FLASH)

480         puts("Flash: ");

481 

482         flash_size = flash_init();

483         if (flash_size > 0) {

484 # ifdef CONFIG_SYS_FLASH_CHECKSUM

485                 print_size(flash_size, "");

486                 /*

487                  * Compute and print flash CRC if flashchecksum is set to 'y'

488                  *

489                  * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX

490                  */

491                 s = getenv("flashchecksum");

492                 if (s && (*s == 'y')) {

493                         printf("  CRC: %08X", crc32(0,

494                                 (const unsigned char *) CONFIG_SYS_FLASH_BASE,

495                                 flash_size));

496                 }

497                 putc('\n');

498 # else  /* !CONFIG_SYS_FLASH_CHECKSUM */

499                 print_size(flash_size, "\n");

500 # endif /* CONFIG_SYS_FLASH_CHECKSUM */

501         } else {

502                 puts(failed);

503                 hang();

504         }

505 #endif

 上述代码的作用是计算FLASH的大小,并把它通过串口显示在控制台上。由于没有定义CONFIG_SYS_FLASH_CHECKSUM,所以没有执行CRC的校验和。其中flash_init函数是在drivers/mtd目录下的cfi_flash.c文件内(因为include/configs/smdk2410.h中定义了CONFIG_FLASH_CFI_DRIVER)。

507 #if defined(CONFIG_CMD_NAND)

508         puts("NAND:  ");

509         nand_init();            /* go init the NAND */

510 #endif

上述代码的作用是初始化NANDFLASH,并把NANDFLASH的大小通过串口显示在控制台上。其中nand_init函数是在divers/mtd/nand目录下的nand.c文件内定义的。

512 #if defined(CONFIG_CMD_ONENAND)

513         onenand_init();

514 #endif

初始化ONENAND FLASH

526         /* initialize environment */

527         env_relocate();

初始化环境变量,由于gd->env_valid等于0,所以在这里设置的是缺省环境变量。env_relocate函数是在common目录下的env_common.c文件中定义的。

529 #if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI)

530         arm_pci_init();

531 #endif

初始化PCI。

532 

533         /* IP Address */

534         gd->bd->bi_ip_addr = getenv_IPaddr("ipaddr");  设置IP地址。

535

536         stdio_init();   /* get the devices list going. */

初始化各类外设,如IIC、LCD、键盘、USB等,当然只有在定义了这些外设的前提下,才对这些外设进行初始化。该函数是在common目录下的stdio.c文件中定义的。

537 

538         jumptable_init();

初始化跳转表gd->jt,该跳转表是一个函数指针数组,它定义了U-Boot中基本的常用函数库。该函数是在common目录下的exports.c文件中定义的。

545         console_init_r();       /* fully init console as a device */

初始化控制台,即标准输入、标准输出和标准错误,在这里都是串口。该函数是在common目录下的console.c文件中定义的。

546 

547 #if defined(CONFIG_ARCH_MISC_INIT)

548         /* miscellaneous arch dependent initialisations */

549         arch_misc_init();

550 #endif

551 #if defined(CONFIG_MISC_INIT_R)

552         /* miscellaneous platform dependent initialisations */

553         misc_init_r();

554 #endif

555 

556          /* set up exceptions */

557         interrupt_init();

558         /* enable exceptions */

559         enable_interrupts();

interrupt_init函数是建立IRQ中断堆栈,enable_interrupts函数是使能IRQ中断,它们都是在arch/arm/lib目录下的interrupts.c文件中定义的。

571         /* Initialize from environment */

572         s = getenv("loadaddr");

573         if (s != NULL)

574                 load_addr = simple_strtoul(s, NULL, 16);

从环境变量中获取loadaddr参数,得到需要加载的地址。

575 #if defined(CONFIG_CMD_NET)

576         s = getenv("bootfile");

577         if (s != NULL)

578                 copy_filename(BootFile, s, sizeof(BootFile));

579 #endif

从环境变量中获取bootfile参数,得到通过TFTP加载的镜像文件名。

589 #if defined(CONFIG_NET_MULTI)

590         puts("Net:   ");

591 #endif

592         eth_initialize(gd->bd);

593 #if defined(CONFIG_RESET_PHY_R)

594         debug("Reset Ethernet PHY\n");

595         reset_phy();

596 #endif

597 #endif

上面代码主要的作用是初始化以太网,其中eth_initialize函数是在net目录下的eth.c文件的第209行至第298行定义的。

633         /* main_loop() can return to retry autoboot, if so just run it again. */

634         for (;;) {

635                 main_loop();

636         }

board_init_r函数的最后就是执行一个死循环,调用main_loop函数。该函数是在common目录下的main.c文件内定义的。

 

下面我们就来分析main_loop函数

 265 void main_loop (void)

 266 {

 267 #ifndef CONFIG_SYS_HUSH_PARSER

 268         static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };

 269         int len;

 270         int rc = 1;

 271         int flag;

 272 #endif

 声明一些hush参数。

 274 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)

 275         char *s;

 276         int bootdelay;

 277 #endif

声明启动延时需要的参数。

 315 #ifdef CONFIG_SYS_HUSH_PARSER

 316         u_boot_hush_start ();

 317 #endif

初始化hush功能。

 346 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)

 347         s = getenv ("bootdelay");

 348         bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;

 349 

 350         debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);

 351 

 352 # ifdef CONFIG_BOOT_RETRY_TIME

 353         init_cmd_timeout ();

 354 # endif /* CONFIG_BOOT_RETRY_TIME */

 355 

 356 #ifdef CONFIG_POST

 357         if (gd->flags & GD_FLG_POSTFAIL) {

 358                 s = getenv("failbootcmd");

 359         }

 360         else

 361 #endif /* CONFIG_POST */

 362 #ifdef CONFIG_BOOTCOUNT_LIMIT

 363         if (bootlimit && (bootcount > bootlimit)) {

 364                 printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",

 365                         (unsigned)bootlimit);

 366                 s = getenv ("altbootcmd");

 367         }

 368         else

 369 #endif /* CONFIG_BOOTCOUNT_LIMIT */

 370                 s = getenv ("bootcmd");

 371 

 372         debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");

 373 

 374         if (bootdelay >= 0 && s && !abortboot (bootdelay)) {

 375 # ifdef CONFIG_AUTOBOOT_KEYED

 376                 int prev = disable_ctrlc(1);    /* disable Control C checking */

 377 # endif

 378 

 379 # ifndef CONFIG_SYS_HUSH_PARSER

 380                 run_command (s, 0);

 381 # else

 382                 parse_string_outer(s, FLAG_PARSE_SEMICOLON |

 383                                     FLAG_EXIT_FROM_LOOP);

 384 # endif

 385 

 386 # ifdef CONFIG_AUTOBOOT_KEYED

 387                 disable_ctrlc(prev);    /* restore Control C checking */

 388 # endif

 389         }

第347行和第348行的含义是从环境变量中获取bootdelay参数,得到自动启动缺省镜像文件的延时(单位是秒)。第353行的含义是初始化命令行超时机制。第370行的含义是从环境变量中获取bootcmd参数,得到在启动延时过程中自动执行的命令。当我们得到了bootcmd参数,bootdelay参数也是大于等于0,并且在启动延时过程中没有按下任意键时,执行第382行的parse_string_outer函数,该函数的作用是解释bootcmd参数并执行,它是在common目录下的hush.c文件内定义的。

 409 #ifdef CONFIG_SYS_HUSH_PARSER

 410         parse_file_outer();

 411         /* This point is never reached */

 412         for (;;);

 413 #else

 414         for (;;) {

 415 #ifdef CONFIG_BOOT_RETRY_TIME

 416                 if (rc >= 0) {

 417                         /* Saw enough of a valid command to

 418                          * restart the timeout.

 419                          */

 420                         reset_cmd_timeout();

 421                 }

 422 #endif

 423                 len = readline (CONFIG_SYS_PROMPT);

 424 

 425                 flag = 0;       /* assume no special flags for now */

 426                 if (len > 0)

 427                         strcpy (lastcommand, console_buffer);

 428                 else if (len == 0)

 429                         flag |= CMD_FLAG_REPEAT;

 430 #ifdef CONFIG_BOOT_RETRY_TIME

 431                 else if (len == -2) {

 432                         /* -2 means timed out, retry autoboot

 433                          */

 434                         puts ("\nTimed out waiting for command\n");

 435 # ifdef CONFIG_RESET_TO_RETRY

 436                         /* Reinit board to run initialization code again */

 437                         do_reset (NULL, 0, 0, NULL);

 438 # else

 439                         return;         /* retry autoboot */

 440 # endif

 441                 }

 442 #endif

 443 

 444                 if (len == -1)

 445                         puts ("<INTERRUPT>\n");

 446                 else

 447                         rc = run_command (lastcommand, flag);

 448 

 449                 if (rc <= 0) {

 450                         /* invalid command or not repeatable, forget it */

 451                         lastcommand[0] = 0;

 452                 }

 453         }

 454 #endif /*CONFIG_SYS_HUSH_PARSER*/

 455 }

由于在include/configs/smdk2410.h文件中定义了CONFIG_SYS_HUSH_PARSER,所以上面的代码仅仅执行的是第410行至第412行的内容。第410行的parse_file_outer函数是在common目录下的hush.c文件中定义的,它的含义是依次读取命令序列中的命令并执行之,其中在该函数还调用了parse_stream_outer函数,这个函数体内有一个do-while循环,只有发生语法错误的时候才会跳出该循环,因此一般情况下永远也不会执行上面代码中的第412行内容,而是始终在那个do-while循环体内。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: