{//-----------------------------启动步骤(重点)----------------------------- 1. 上电启动bootloader //阶段一(汇编) 设置为SVC模式,关闭中断,MMU,看门狗 //准备 硬件基本初始化 //初始化时钟,串口,flash,内存 见cpu/xxxx/start.S的 cpu_init_crit 自搬移到内存 //copy_uboot_to_arm 或relocate 设置好栈 //stack_setup 跳转到二阶段代码入口 //ldr pc,_start_armboot //阶段二(C语言) 大部分硬件初始化 //lib_arm/board.c/start_armboot->init_sequence 搬移内核到内存 //common/main.c main_loop->getenv("bootcmd") bootdelay>= 0 && s && !abortboot(bootdelay)下的run_command(bootcmd) 传递内核启动参数(parmer_struct 或taglist) 2. 加载内核 a. 自解压内核 decompess //arch/arm/boot/compressed/head.S b. 运行内核汇编部分 head.S 入口stext //arch/arm/kernel/head.S 检测合法性(CPU 类型,机器类型) c. 运行内核C部分 start_kernel //init/main.c CPU,机器参数的安装 setup_arch 中断,定时,终端,内存等最基本的初始化 创建核心进程 kernel_init运行,启动多任务调度,原父进程空转cpu_ide 3. 挂载rootfs (mount_root) 4. 运行应用程序 //第一个应用程序是init (由u-boot的bootargs里的init=/linuxrc来指定) a. 运行启动脚本 (run_init_process("/etc/init.d/rcS")) //由init来解析脚本执行 b. 其它应用程序 //一般添加在脚本的最后(如在rcS末尾加 ./app) }
{//---u-boot.lds 或 u-boot.map 指明了第一条指令位置 arch/arm/cpu/armv7/start.o }
{//---arch/arm/cpu/armv7/start.S u-boot的启动入口 _start: b reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq reset: /* * set the cpu to SVC32 mode */ mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr cpsr,r0 bl cpu_init_cp15 //关闭中断 cache MMU等 bl cpu_init_crit bl _main //跳到C部分 位置 arch/arm/lib/board.c ( 在u-boot.map里搜索_main) ENTRY(relocate_code) //自搬移 重定位 (运行时机见 u-boot.map 里执行位置) adr r0, _start cmp r0, r6 moveq r9, #0 /* no relocation. relocation offset(r9) = 0 */ beq relocate_done /* skip relocation */ mov r1, r6 /* r1 <- scratch for copy_loop */ ldr r3, _image_copy_end_ofs add r2, r0, r3 /* r2 <- source end address */ copy_loop: ldmia r0!, {r9-r10} /* copy from source address [r0] */ stmia r1!, {r9-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end address [r2] */ blo copy_loop ENDPROC(relocate_code) ENTRY(cpu_init_cp15) /* * Invalidate L1 I/D */ mov r0, #0 @ set up for MCR mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs mcr p15, 0, r0, c7, c5, 0 @ invalidate icache /* * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x00002000 @ clear bits 13 (--V-) bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) mcr p15, 0, r0, c1, c0, 0 mov pc, lr @ back to my caller ENDPROC(cpu_init_cp15) ENTRY(cpu_init_crit) b lowlevel_init @ go setup pll,mux,memory //位置board/samsung/fs4412/libfs4412.o( 在u-boot.map里搜索lowlevel_init) ENDPROC(cpu_init_crit) }
{//---board/samsung/fs4412/lowlevel_init.S 基本硬件初始化 (关闭看门狗中断 时钟初始化 串口初始化 nand初始化 dram初始化) lowlevel_init: //有些初始化,已被三星剥离到 BLO或BL1 中 /* init system clock */ bl system_clock_init /* Memory initialize */ bl mem_ctrl_asm_init /* for UART */ bl uart_asm_init mov pc, lr }
{//---arch/arm/lib/board.c 大部分硬件初始化, 调用主循环main_loop(见common/main.c) init_fnc_t *init_sequence[] = { arch_cpu_init, /* basic arch cpu dependent setup */ mark_bootstage, #if defined(CONFIG_BOARD_EARLY_INIT_F) board_early_init_f, #endif timer_init, /* initialize timer */ env_init, /* initialize environment */ init_baudrate, /* initialze baudrate settings */ serial_init, /* serial communications setup */ console_init_f, /* stage 1 init of console */ display_banner, /* say that we are here */ dram_init, /* configure available RAM banks */ NULL, }; void board_init_r(gd_t *id, ulong dest_addr) { board_init(); /* Setup chipselects */ /* main_loop() can return to retry autoboot, if so just run it again. */ for (;;) { main_loop(); //调用主循环main_loop } } void board_init(ulong bootflag) { for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { //大部分硬件初始化 if ((*init_fnc_ptr)() != 0) { hang (); } } } }
{//5.common/main.c //主循环main_loop 实现 bootdelay延时时间到之前无输入,则加载bootcmd进入自启动模式;如果有输入则进入交互模式 void main_loop (void) { s = getenv ("bootdelay"); //获取env环境变量中的 bootdelay 参数 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; s = getenv ("bootcmd"); //获取自启动命令如 bootcmd = tftp 20008000 zImage ; go zImage 表示从网络加载内核运行 if (bootdelay >= 0 && s && !abortboot (bootdelay)) { run_command (s, 0); //如果延时大于等于零,并且没有在延时过程中接收到按键,则运行bootcmd命令,引导内核。进入自启动模式 } //否则进入交互模式 /* * Main Loop for Monitor Command Processing */ for (;;) { len = readline (CONFIG_SYS_PROMPT); //读取命令 rc = run_command (lastcommand, flag); //运行命令 } } } }
一般厂商 或者 方案提供商都会给出demo,比如4412参考的就是origen这个demo,模仿着写即可。
beyond对比工具使用
将要比较的两个版本的u-boot文件分别打开,点击ctrl+A 全选,然后点右键,选择比较,按2进制方式。然后点确定即可。
文件/文件夹 的颜色:灰色 无任何改动,红色 有修改 ,紫色 有新增。
选择官方源码版本下载, 配置编译
a. 指定交叉编译工具链
b. 指定cpu 和board(参考最类似配置如origen)
c. 编译
实现串口信息输出
a. 跟踪运行路径(led点灯法)
b. 串口输出(检查uart初始化相关部分代码 见lowlevel_init.s)
网卡移植(实现能用tftp nfs 方便开发调试)
a. 寄存器地址
b. 参数设置
FLASH移植(实现能下载软件到FLASH,产品能离线运行)