针对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");
}