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

Uboot代码结构详细分析 1. Bootloader功能分析 Bootloader(如Uboot、Redboot、Blob、vivi等)直接和CPU、外围硬件设备(存储器、网卡、LCD等)打交道,负责初始化硬件设备,以及负责拉起内核:建立内存空间映射图,为内核的启动运行做好一切准备,最后将Linux内核代码加载到RAM中运行。 一般来说,bootload都会提供两种操作模式: 正常启动模式:无需开发者和用户干涉,上电后自动开始运行,完成启动内核的任务; 下载模式(开发者模式):需要用户干预,进入下载模式,使用uboot命令 阅读详情
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循环体内。

u-boot-2009.11-rc1.tar.bz2 U-Boot Source Code The current source code is available through the _git_ repository at git.denx.de. Released Versions (and some special snapshots) are available from the DENX FTP server Snapshots are available using the clever "snapshot" feature of the git server (see the "snapshot" link after all commit entries). NOTE: even though the download will be a bzip2 compressed tarball, and the file on your disk will be named "*.tar.bz2", you may find that it's actually not compressed at all. This is a "feature" of your web browser, and we cannot do anything to help it. www.denx.de also hosts the Custodian git trees CVS is no longer supported. The old project page at SourceForge is no longer used and dead. 立即下载

相关推荐

【任何电机可使用的七段式s曲线-----包括matlab代码和simulink仿真】

S形加加速(T1)→>匀加速(T2)→减加速(T3)→>匀速(T4 )>加减速(T5)>匀减速(T6)-→>减减速(T7)

weixin_44312889的博客 6309

嵌入式Linux作业二分析u-boot-1.1.6在smdk2410开发板上的启动代码

嵌入式Linux作业二分析u-boot-1.1.6在smdk2410开发板上的启动代码

enheihei的博客 965

HRnet的pytorch实现

HRnet的pytorch实现

奋土的博客 1953

smdk2410 UBoot 汇编阶段分析

首先根据链接脚本我们知道程序从u-boot-2009.03/cpu/arm920t/start.S开始,而且入口是_start,因此我们先看start.S,首先是下面的程序:    40 .globl _start  41 _start: b       start_cod

K_Linux_ManのBlog 1227

银河麒麟V10系统grub崩溃急救指南:从光盘救援到完整恢复(附常见错误排查)

本文详细介绍了银河麒麟V10系统grub崩溃的急救方法,从使用安装光盘进入救援环境到完整恢复系统的全流程。针对不同损坏程度(轻度、中度、严重)提供了分级恢复策略,包括grub2-install和grub2-mkconfig等关键命令的使用,并附有常见错误排查表,帮助用户快速解决引导问题。

weixin_30955617的博客 483

logisim计组实验八 乘法器

原理:点这里 有问题欢迎留言哦~ 文章目录五位阵列乘法器电路图时间延迟分析六位补码阵列乘法器五位无符号乘法流水线原理图电路图原码一位乘法器原理图电路图补码一位乘法器 五位阵列乘法器 电路图 此处注意:全加器FA的cout端是进位端而非输出端 使用硬件控制比循环累加的速度快得多。 但是存在串行进位链 改进版: 时间延迟分析 T是计算相加数的一级门延迟 3n–>2n 性能差别在1.5倍 ...

treblez's blog 2万+

u-boot启动代码分析

u-boot版本为u-boot-2009.08,平台smdk2410 一、第一阶段启动代码分析 在学习ARM时就知道,ARM在上电复位时将PC指针修改为0,即ARM是从0地址开始读取指令执行的。在cpu/arm920t/目录下有个u-boot.lds链接脚本,首先看代码段定义: . =0x00000000; . =ALIGN(4); .text : { cp...

weixin_30835933的博客 209

推荐系统[九]项目技术细节讲解z2:搜索Query理解[Term Weight、Query 改写、同义词扩写]和语义召回技术

在 pooling 方法上,我们也尝试过不同层 pooling,或者在多层上增加 attention 聚合 BERT 多层结果,效果和最后一层所有 token 做 average pooling 相当。损失函数方面,在排序阶段使用pairwise比 pointwise 损失函数的效果会更好。

丨汀、的博客 1109

u-boot-2011.06启动流程分析

本文以u-boot-2011.06这个最新版本为例,介绍u-boot在smdk2410上的启动流程过程。

赵春江的专栏 1万+

Altium Designer20 PCB板子绘制

版层 top layer 顶层 bottom layer 底层 设置板子大小 布局 过孔 top layer层连到bottom layer层。通过via连接。 设置线宽 在design rules里可以设置线宽。 右键new rule 可以新增线宽,电源设置成20mil 还可以设置很多其他的线宽 修改安全距离 安全距离太短容易出现毛刺,然后短路,一般设置成20mil 修改元器件旋转角度 修改rotation step,每次旋转45°。 修改光标大小 下面的cursor type是修改光标

及时总结 2581

《QGIS快速入门与应用基础》191:渐变区间设置(等间隔/分位数)

深入解析QGIS中渐变符号化的核心环节——渐变区间设置,重点对比等间隔与分位数两种主流模式的原理与应用。作者指出,90%的渐变效果问题源于区间设置不当,强调必须先分析数据分布特征(通过统计面板查看直方图、极值等)再选择匹配模式。等间隔模式适用于均匀分布数据(如海拔、温度),将数值范围均等划分;分位数模式则针对偏态数据(如GDP、人口),保证每个区间要素数量相等。文章通过界面示意图、效果对比图和操作步骤详解,指导读者根据数据类型选择合适区间模式,并提醒常见避坑要点:社会经济数据禁用等间隔、分类数不超过8类。

LuckyHanMo的博客 315

u-boot-2011.09在ST2410上的移植-在RAM中运行

u-boot-2011.09在ST2410上的移植之在RAM中运行 作者:boarmy u-boot版本:u-boot-2011.09 运行环境:Window7  Vmware workstation7.1   CentOS6.0 交叉编译环境:Arm-linux-gcc-4.3.2 with EABI 硬件环境: ST2410X开发板(CPU:S3C2410X

BoArmy的专栏 2220

YOLOv11的代数不变量解释:Syzygy模分析特征重要性,用交换代数揭示卷积核的语义相关性

本文提出了一种基于代数几何与交换代数的创新方法,特别是运用Syzygy模理论,对YOLOv11目标检测算法的卷积核语义相关性进行数学解释。研究揭示了YOLO系列算法演进背后的代数结构特征,建立了网络组件与多项式环、理想簇等代数概念的对应关系。通过构建分层的准同构代数系统,分析了YOLOv11在不同尺度下保持语义不变性的数学本质。文章系统阐述了Syzygy模在CNN特征冗余分析、跨层依赖关系建模和语义聚类中的应用,并提出了适用于动态稀疏训练的改进算法。该理论框架为深度神经网络的解释性研究提供了新的数学工具,同

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 1270

u-boot-2011.09在ST2410上的移植-启用CS8900网卡功能

u-boot-2011.09在ST2410上的移植之启用CS8900网卡功能   接上篇,启用CS8900网卡功能,实现tftp下载(红色部分为我添加的,蓝色为修改的) u-boot本身有cs8900网卡驱动程序,所以需要修改的地方不多。由于数据通过总线传送,所以要注意地址空间的配置和总线的配置。 1)、首先修改include/configs/st2410.h文件  57 #defi

BoArmy的专栏 1745

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

u-boot源码分析 --- 启动第二阶段 ,基于2410 启动代码 分析

我们先来看初始化函数表: init_sequencelib_arm/board.c:typedef int(init_fnc_t) (void);init_fnc_t*init_sequence[] = {    cpu_init,       /*basic cpu dependent setup */    board_init,     /*basic b

LYJ个人博客,记录技术、八卦、生活,分享各种心得,期待与朋友们一同进步 3254

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

2410启动代码分析

ADS下C语言的入口方式和ROM镜像文件的生成这部分介绍下ADS下如何生成可以运行的ROM镜像文件,我们知道当程序下载到flash中运行的时候,对于RW、ZI数据就存在着两个环境,一个load环境,一个是exec环境,有时候由于速度的需要RO数据也要重新加载,那么对RO数据也是有两个环境。编译器产生ROM镜像文件时候,这三块数据的存放依次为RO、RW、ZI,并且地址空间时连续的。但是到了运行的

albert的嵌入式专栏 1826

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

u-boot源码分析 - 简介,编译

1  u-boot介绍U-Boot是一种通用的Bootloader, U-Boot可以方便地移植到其他硬件平台上,其源代码也值得开发者们研究学习。最早,DENX软件工程中心的Wolfgang Denk基于8xxrom的源码创建了PPCBOOT工程,并且不断添加处理器的支持。后来,Sysgo Gmbh把ppcboot移植到ARM平台上,创建了ARMboot工程。然后以pp

aaronychen的专栏 3969

u-boot2013.01 smdk2410 启动第一阶段分析

u-boot2013.01 smdk2410  -->2440 启动分析 1.u-boot启动第一阶段  start.S (arch\arm\cpu\arm920t)     _start: b start_code     1.1 set the cpu to SVC32 mode    mrs r0, cpsr bic r0, r0,

Android 系统开发 1141

smdk2410-uboot编译

1、创建实验目录 #mkdir /home/guoqian/4-2-2 #cd /home/guoqian/4-2-2   2、将u-boot源代码拷贝至实验目录 3、解压u-boot源代码到当前目录 #tar jxvf u-boot-2008.10.tar.bz2 4、清理中间文件 # make clean 5、选择板级配置 u-boot是通用的bootloade

lifengxun20121019的专栏 1249

ARM9 2410系列开发板U-boot移植

ARM9 2410系列开发板U-boot移植 U-boot的stage1代码通常放在start.s文件中,它用汇编语言写成,其主要功能如下: 定义入口。一个可执行的Image必须有一个入口的,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址。 设置异常向量。 本地硬件设备初始化(设置CPU模式/关闭看门狗计时器/屏蔽中断等)。 初始化内存控制器。如果从固态存储介质中启动,则复制bootloader的第二阶段到RAM。 设置堆栈,跳转到stage2入口点。自此stage1执行

focus on security 969

全志A33 uboot_2011进入uboot命令行,设置延时启动参数方法

uboot可以通过修改配置文件env.cfg设置设置延时启动参数,也可以在强制进入uboot命令行后,在命令行中输入相应的命令进行配置。 1、uboot相关命令查询 1)、进入uboot后对于uboot有哪些命令可以通过 help 命令来查询 help 2)、 help + 详细的命令 如果需要知道具体的某个命令的详细用法可以通过 help + 具体的命令用法 help md help bootm 3)、查询当前开发板配置的环境参数 同时可以通过print命令查询当前uboot设置了哪些环境参数 p

u010584870的博客 1396

基于6410的u-boot移植

基于6410的u-boot移植(一)   2011-07-04 19:49:41|  分类: bsp |  标签: |字号大中小 订阅 由于Uboot2011.06对S3C6410有了很好的支持,所以采用Uboot2011.06版本。 一、             移植环境 主 机:VMWare-ubuntu 开发板:ok6410—512M nandflash,K

xiao229404041的专栏 1515

uboot2011.09源代码ReadMe译文

# # (C) Copyright 2000 - 2011 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. #查看建立这个工程的文件列表人 # #这个程序是自由软件,你可以重新分配它或者修改它在GNU通用公共许可证以由自由软件基#金会发布;第二版或者任何之后的版本。 #本程序是分布在希望它是有用的,

吴英强的技术博客 9792
上一篇: Udev学习总结
下一篇: LINUX动态链接库高级应用
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值