在uboot源码的顶层目录下:
#make smdkv210single_config
Configuring for smdkv210single board...
Makefile文件中的配置入口:
smdkv210single_config : unconfig
@$(MKCONFIG) $(@:_config=) arm s5pc11x smdkc110 samsung s5pc110
@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/smdkc110/config.mk
二、配置过程完成三个工作
1、unconfig
将上一次的配置全部删除
@rm -f $(obj)include/config.h $(obj)include/config.mk
$(obj)board/*/config.tmp $(obj)board/*/*/config.tmp
$(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep
$(obj)board/$(VENDOR)/$(BOARD)/config.mk
问题1:
@ --->在Makefile中,引用shell命令时,shell命令前面加一个@,--->取消回显
2、@$(MKCONFIG) $(@:_config=) arm s5pc11x smdkc110 samsung s5pc110
调用一个shell脚本文件,并向该脚本文件传递参数,这些参数是用来描述一个硬件平台的具体信息(cpu架构、cpu型号、板子名称、厂家...)。
根据这些参数信息,对源码进行配置,使源码应用于某一个具体平台。
$(MKCONFIG) ----> MKCONFIG := $(SRCTREE)/mkconfig <---shell脚本
在mkconfig脚本中:
$0 = mkconfig
$1 = smdkv210single
$2 = arm
$3 = s5pc11x
$4 = smdkc110
$5 = samsung
$6 = s5pc110
在mkconfig文件中,所做的工作:
1)输出一个提示信息:
echo "Configuring for ${BOARD_NAME} board..."
2)做一个连接asm->asm-arm //指向cpu架构
cd ./include
rm -f asm
ln -s asm-$2 asm
3)做一个连接asm-arm/arch->arch-s5pc110 //没有作用
rm -f asm-$2/arch
ln -s ${LNPREFIX}arch-$6 asm-$2/arch
4) 创建连接文件:regs.h->s5pc110.h //指向cpu
asm-arm/arch->arch-s5pc11x
if [ "$3" = "s5pc11x" ] ; then
rm -f regs.h
ln -s $6.h regs.h
rm -f asm-$2/arch
ln -s arch-$3 asm-$2/arch
fi
5)创建连接asm-arm/proc->proc-armv
if [ "$2" = "arm" ] ; then
rm -f asm-$2/proc
ln -s ${LNPREFIX}proc-armv asm-$2/proc
fi
6)config.mk文件中写入硬件平台的信息
echo "ARCH = $2" > config.mk
echo "CPU = $3" >> config.mk
echo "BOARD = $4" >> config.mk
[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk
[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk
7)创建一个头文件 config.h
在该头文件中加入:
#include
echo >> config.h
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include " >>config.h
3.@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/smdkc110/config.mk
TEXT_BASE:代码段的基地址,0xc3e00000 --->虚拟地址,实际使用过程中,MMU将0xc3e00000转换成物理地址0x33e00000
uboot在链接的时候,就代码链接到TEXT_BASE地址上。
/*****************************************************************************/
一、如何找到uboot的入口点
分析连接文件:u-boot-samsung-dev/board/samsung/smdkc110/u-boot.lds
OUTPUT_ARCH(arm)
ENTRY(_start) //入口程序
SECTIONS
{
. = 0x00000000;
. = ALIGN(4); //4字节对齐
.text : //代码段
{
cpu/s5pc11x/start.o (.text) //第一个执行的源文件:start.S
cpu/s5pc11x/s5pc110/cpu_init.o (.text)
board/samsung/gec210/lowlevel_init.o (.text)
cpu/s5pc11x/onenand_cp.o (.text)
cpu/s5pc11x/nand_cp.o (.text)
cpu/s5pc11x/movi.o (.text)
common/secure_boot.o (.text)
common/ace_sha1.o (.text)
cpu/s5pc11x/pmic.o (.text)
*(.text)
}
. = ALIGN(4);
.rodata : { *(.rodata) }
. = ALIGN(4);
.data : { *(.data) }
. = ALIGN(4);
.got : { *(.got) }
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
.mmudata : { *(.mmudata) }
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}
找到uboot的入口:
cpu/s5pc11x/start.S中的一个_start的子程序
二、uboot的启动流程:
1、入口(start.S --> _start)
_start: b reset
2、跳转到reset
reset:
/*
* set the cpu to SVC32 mode and IRQ & FIQ disable
*/
msr cpsr_c, #0xd3 @ I & F disable, Mode: 0x13 - SVC
3、cache初始化
bl disable_l2cache
bl set_l2cache_auxctrl_cycle
bl enable_l2cache
4、通过读取寄存器,得到210的启动方式
/* Read booting information */
ldr r0, =PRO_ID_BASE
ldr r1, [r0,#OMR_OFFSET]
bic r2, r1, #0xffffffc1 //r2=OM[5:1]
cmp r2, #0x2 @ 2KB 5-cycle
moveq r3, #BOOT_NAND //r3=启动方式的值
ldr r0, =INF_REG_BASE
str r3, [r0, #INF_REG3_OFFSET]
ldr r0, =INF_REG_BASE
str r3, [r0, #INF_REG3_OFFSET] //将r3的值保存到一个寄存器中
5、bllowlevel_init 底层的硬件初始化(lowlevel_init.S)
关闭看门狗
bl system_clock_init //时钟
bl mem_ctrl_asm_init //DDR2内存
bl uart_asm_init //串口 输出'O'
bl tzpc_init
bl nand_asm_init
//输出‘K’
6、 进入nand_boot(start.S)
ldr r0, =INF_REG_BASE
ldr r1, [r0, #INF_REG3_OFFSET]
cmp r1, #BOOT_NAND /* 0x0 => boot device is nand */
beq nand_boot
nand_boot:
mov r0, #0x1000
bl copy_from_nand //将BL2 copy到内存的0x33e00000
b after_copy
7、bafter_copy
MMU初始化(memory management unit)
初始化stack
将BSS段清0
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
clbss_l:
str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1 //判断是否清完
ble clbss_l
8、跳转到start_armboot
ldr pc, _start_armboot
_start_armboot:
.word start_armboot
----------------------------------前面是BL1(stage1),后面是BL2(stage2)--------------------------------------------
9、板子信息的初始化
void start_armboot (void) //公共的代码
{
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
init_fnc_t *init_sequence[] = {
cpu_init, /* basic cpu dependent setup */
#if defined(CONFIG_SKIP_RELOCATE_UBOOT)
reloc_init, /* Set the relocation done flag, must
do this AFTER cpu_init(), but as soon
as possible */
#endif
board_init, /* basic board dependent setup */
interrupt_init, /* set up exceptions */
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 */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info */
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,
#endif
dram_init, /* configure available RAM banks */
display_dram_config,
NULL,
};
10、进入主循环
for (;;) {
main_loop ();
}
main_loop 函数中,等待bootdelay(3S),在3S中内输入按键,就进入uboot的命令行,执行uboot命令
;如果3S中内,没有按键按下,就启动操作系统(执行bootcmd)