logo资料库

Uboot启动流程.PDF

第1页 / 共15页
第2页 / 共15页
第3页 / 共15页
第4页 / 共15页
第5页 / 共15页
第6页 / 共15页
第7页 / 共15页
第8页 / 共15页
资料共15页,剩余部分请下载后查看
U-Boot 启动过程 (国嵌) 开发板上电后,执行 U-Boot 的第一条指令,然后顺序执行 U-Boot 启动函数。看一下 board/smdk2410/u-boot.lds 这个链 接脚本,可以知道目标程序的各部分链接顺序。第一个要链接的 是 cpu/arm920t/start.o,那么 U-Boot 的入口指令一定位于这 个程序中。下面分两阶段介绍启动流程: 1.cpu/arm920t/start.S 第一阶段 这个汇编程序是U-Boot 的入口程序,开头就是复位向量的代码。 _start: b reset //复位向量 ldr ldr ldr ldr ldr ldr ldr pc, _undefined_instruction pc, _software_interrupt pc, _prefetch_abort pc, _data_abort pc, _not_used pc, _irq //中断向量 pc, _fiq //中断向量 … /* the actual reset code */
reset: //复位启动子程序 /* 设置 CPU 为 SVC32 模式 */ mrs r0,cpsr bic orr r0,r0,#0x1f r0,r0,#0xd3 msr cpsr,r0 /* 关闭看门狗 */ …… relocate: …… /* 把 U-Boot 重新定位到 RAM */ adr ldr 址 */ cmp r0, _start /* r0 是代码的当前位置 */ r1, _TEXT_BASE /*_TEXT_BASE 是 RAM 中的地 r0, r1 /* 比较 r0 和 r1,判断当前是从 Flash 启动,还是 RAM */ beq stack_setup /* 如果 r0 等于 r1,跳过重定位代码 */ /* 准备重新定位代码 */ ldr ldr sub add r2, _armboot_start r3, _bss_start r2, r3, r2 /* r2 得到 armboot 的大小 */ r2, r0, r2 /* r2 得到要复制代码的末尾地址 */
copy_loop: /* 重新定位代码 */ ldmia r0!, {r3-r10} /*从源地址[r0]复制 */ stmia r1!, {r3-r10} /* 复制到目的地址[r1] */ cmp r0, r2 /* 复制数据块直到源数据末尾地址[r2] */ ble copy_loop /* 初始化堆栈等 */ stack_setup: ldr r0, _TEXT_BASE /* 上面是 128 KiB 重定位的 u-boot */ sub */ sub r0, r0, #CFG_MALLOC_LEN /* 向下是内存分配空间 r0, r0, #CFG_GBL_DATA_SIZE /* 然后是 bdinfo 结构 体地址空间 */ #ifdef CONFIG_USE_IRQ sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif sub sp, r0, #12 /* 为 abort-stack 预留 3 个字 */ clear_bss: ldr r0, _bss_start /* 找到 bss 段起始地址 */ ldr r1, _bss_end /* bss 段末尾地址 */
mov r2, #0x00000000 /* 清零 */ clbss_l:str r2, [r0] /* bss 段地址空间清零循环... */ add cmp r0, r0, #4 r0, r1 bne clbss_l /* 跳转到 start_armboot 函数入口,_start_armboot 字保存函 数入口指针 */ ldr pc, _start_armboot _start_armboot: .word start_armboot 函数在 lib_arm/board.c 中实现 //start_armboot 2.lib_arm/board.c 第二阶段 start_armboot 是 U-Boot 执行的第一个 C 语言函数,完成系统 初始化工作,进入主循环,处理用户输入的命令。 3.init_sequence[] init_sequence[]数组保存着基本的初始化函数指针。 init_fnc_t *init_sequence[] = {
cpu_init, /* 基本的处理器相关配置 -- cpu/arm920t/cpu.c */ board_init, /* 基 本 的 板 级 相 关 配 置 board/smdk2410/smdk2410.c */ interrupt_init, /* 初 始 化 中 断 处 理 -- -- cpu/arm920t/s3c24x0/interrupt.c */ env_init, /* 初始化环境变量 -- common/cmd_flash.c */ init_baudrate, /* 初始化波特率设置 -- lib_arm/board.c */ serial_init, /* 串 口 通 讯 设 置 -- cpu/arm920t/s3c24x0/serial.c */ console_init_f, /* 控 制 台 初 始 化 阶 段 1 -- common/console.c */ display_banner, lib_arm/board.c */ dram_init, /* 打 印 u-boot 信 息 -- /* 配 置 可 用 的 RAM -- board/smdk2410/smdk2410.c */ display_dram_config, /* 显 示 RAM 的 配 置 大 小 -- lib_arm/board.c */ NULL, }; void start_armboot (void)
{ /* 顺序执行 init_sequence 数组中的初始化函数 */ for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { hang (); } } /*配置可用的 Flash */ size = flash_init (); display_flash_config (size); /* _armboot_start 在 u-boot.lds 链接脚本中定义 */ mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); /* 配置环境变量*/ env_relocate (); /* 从环境变量中获取 IP 地址 */ gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); /* 以太网接口 MAC 地址 */ ……
devices_init (); /* 获取列表中的设备 */ jumptable_init (); console_init_r (); /* 完整地初始化控制台设备 */ enable_interrupts (); /* 使能中断处理 */ /* 通过环境变量初始化 */ if ((s = getenv ("loadaddr")) != NULL) { load_addr = simple_strtoul (s, NULL, 16); } /* main_loop()循环不断执行 */ for (;;) { main_loop (); /* 主循环函数处理执行用户命令 -- common/main.c */ } 命令实现 U-Boot 作为 Bootloader,具备多种引导内核启动的方式。常用 的 go 和 bootm 命令可以直接引导内核映像启动。U-Boot 与内 核的关系主要是内核启动过程中参数的传递。 1.go 命令的实现 /* common/cmd_boot.c */
int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { ulong addr, rc; int rcode = 0; if (argc < 2) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } addr = simple_strtoul(argv[1], NULL, 16); printf ("## Starting application at 0x%08lX ...\n", addr); rc = ((ulong (*)(int, char []))addr) (--argc, &argv[1]); /* 运行程序 */ if (rc != 0) rcode = 1; printf ("## Application terminated, rc = 0x%lX\n", rc); /*如果是运行 linux,这条指令是否能运行?*/ return rcode; } go 命令调用 do_go()函数,跳转到某个地址执行的。如果在这 个地址准备好了自引导的内核映像,就可以启动了。尽管 go 命
分享到:
收藏