针对uboot2016
一、编译U-boot的用到的基本命令
1、make xxx_config
在根目录下生成.config
CONFIG_SYS_ARCH="arm" CONFIG_SYS_CPU="arm920t" CONFIG_SYS_SOC="s3c24x0" CONFIG_SYS_VENDOR="samsung" CONFIG_SYS_BOARD="smdk2410" CONFIG_SYS_CONFIG_NAME="smdk2410"
CONFIG_CPU_ARM920T=y CONFIG_SYS_ARM_ARCH=4 CONFIG_SYS_CACHE_SHIFT_5=y CONFIG_SYS_CACHELINE_SIZE=32
CONFIG_TARGET_SMDK2410=y
2、指定架构和编译器
export ARCH=arm export CROSS_COMPILE=/xxx/xxx/arm-none-linux-gnueabi-2014-05/bin/arm-none-linux-gnueabi-
3、make
二、移植uboot2016需要修改的内容
以三星2410为例
- board/samsung/smdk2410/
- include/configs/smdk2410.h
- configs/smdk2410_defconfig
三、Uboot程序执行大体流程
1、arch/arm/cpu/arm920t/start.S
程序执行入口,设置CPU模式,关闭MMU,Cache;跳到board/vender_name/board_name/lowlevel_init.S执行cpu_init_crit.
reset: /* * set the cpu to SVC32 mode */ mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr cpsr, r0
#ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit #endif bl _main
cpu_init_crit: /* * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) orr r0, r0, #0x00000002 @ set bit 1 (A) Align orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache mcr p15, 0, r0, c1, c0, 0 #ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY /* * before relocating, we have to setup RAM timing * because memory timing is board-dependend, you will * find a lowlevel_init.S in your board directory. */ mov ip, lr ...... bl lowlevel_init mov lr, ip #endif
2、board/vender_name/board_name/lowlevel_init.S
start.S中cpu_init_crit调用lowlevel_init完成板子初始化工作包括时钟,内存,串口等(这些初始化函数实体定义在其他文件中,会继续调用)
.globl lowlevel_init lowlevel_init: /* memory control configuration */ /* make r0 relative the current location so that it */ /* reads SMRDATA out of FLASH rather than memory ! */ ldr r0, =SMRDATA ldr r1, =CONFIG_SYS_TEXT_BASE sub r0, r0, r1 ldr r1, =BWSCON /* Bus Width Status Controller */ add r2, r0, #13*4
3、cpu_init_crit执行完返回start.S, start.S继续调用arch/arm/lib/crt0.S中的 _main
_main设置栈,初始化C运行环境,继续调用uboot/common/board_f.c/board_init_f() 和board_init_r()
ENTRY(_main) /* * Set up initial C runtime environment and call board_init_f(0). */ #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) ldr sp, =(CONFIG_SPL_STACK) #else ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) #endif
#else bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ #endif mov r0, sp bl board_init_f_alloc_reserve mov sp, r0 /* set up gd here, outside any C code */ mov r9, r0 bl board_init_f_init_reserve mov r0, #0 bl board_init_f
#if defined(CONFIG_SYS_THUMB_BUILD) ldr lr, =board_init_r /* this is auto-relocated! */ bx lr #else ldr pc, =board_init_r /* this is auto-relocated! */ #endif /* we should not return here. */ #endif ENDPROC(_main)
4、uboot/common/board_f.c 和board_r.c
board_init_f是uboot初始化过程中执行的第一个C函数,可以看作这个文件的入口函数。其中最重要的就是准备全局信息GD结构体, 内核启动参数就是来自于这个结构体。board_init_t完成代码重定位工作。board_init_t()不会再返回,它调用自身的run_main_loop函数,run_main_loop进入无限循环,已知调用common/mian.c下的main_loop
void board_init_f(ulong boot_flags) { #ifdef CONFIG_SYS_GENERIC_GLOBAL_DATA /* * For some archtectures, global data is initialized and used before * calling this function. The data should be preserved. For others, * CONFIG_SYS_GENERIC_GLOBAL_DATA should be defined and use the stack * here to host global data until relocation. */ gd_t data; gd = &data;
void board_init_r(gd_t *new_gd, ulong dest_addr) { #ifdef CONFIG_NEEDS_MANUAL_RELOC int i; #endif #ifdef CONFIG_AVR32 mmu_init_r(dest_addr); #endif
static int run_main_loop(void) { #ifdef CONFIG_SANDBOX sandbox_main_loop_init(); #endif /* main_loop() can return to retry autoboot, if so just run it again */ for (;;) main_loop(); return 0; }
5、最后执行uboot/common/mian.c下的main_loop
读取命令,再执行命令
void main_loop(void) { const char *s; bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop"); #ifdef CONFIG_VERSION_VARIABLE setenv("ver", version_string); /* set version variable */ #endif /* CONFIG_VERSION_VARIABLE */ cli_init(); run_preboot_environment_command(); #if defined(CONFIG_UPDATE_TFTP) update_tftp(0UL, NULL, NULL); #endif /* CONFIG_UPDATE_TFTP */ s = bootdelay_process(); if (cli_process_fdt(&s)) cli_secure_boot_cmd(s); autoboot_command(s); cli_loop(); panic("No CLI available"); }