http://blog.csdn.net/gameit/article/details/17464621
UBOOT之start.s分析
/**********设置处理器模式******************************/
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr,r0
/*********************CPU和板级初始化*********************/
ifndef CONFIG_SKIP_LOWLEVEL_INIT
blcpu_init_crit //此函数就在start.s中
endif
cpu_init_crit:
/*
* I使无效TLB和指令cache
*/
movr0, #0
@ set up for MCR
mcrp15, 0, r0, c8, c7, 0
@ invalidate TLBs
mcrp15, 0, r0, c7, c5, 0
@ invalidate icache
/*
* disable MMU stuff and caches
*/
mrcp15, 0, r0, c1, c0, 0
bicr0, r0, #0x00002000
@ clear bits 13 (–V-)
bicr0, r0, #0x00000007
@ clear bits 2:0 (-CAM)
orrr0, r0, #0x00000002
@ set bit 1 (–A-) Align
orrr0, r0, #0x00000800
@ set bit 12 (Z—) BTB
mcrp15, 0, r0, c1, c0, 0
/*
* Jump to board specific initialization…
* The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle
* wake up conditions.
*/
movip, lr @ persevere link reg across call
bllowlevel_init @板级初始化
movlr, ip @ restore link
movpc, lr
@ back to my caller
lowlevel_init做的主要工作就是关闭看门狗,关闭中断,初始化时钟,初始化DDR,初始化串口,如果定义了CONFIG_NAND,还会初始化nand控制器,初始化安全域控制器。此函数在lowlevel_init.S文件中,该文件目录为: board/厂家名/板名/,如 :board/samsung/smdkc100/lowlevel_init.S
主要由以下几个函数组成:
bl system_clock_init 初始化时钟
bl mem_ctrl_asm_init 初始化DDR
bl uart_asm_init 初始化串口
bl tzpc_init 初始化安全域
if defined(CONFIG_NAND)
bl nand_asm_init 简单初始化NAND
endif
对于以上函数不做详细说明,对照数据手册可自己更改。
以上函数全在lowlevel_init.S中,但注意 mem_ctrl_asm_init 可能不在 lowlevel_init.S中,而在mem_setup.S文件中,此文件与lowlevel_init.S在一个目录中。
/**************重定位****************/
relocate: @ relocate U-Boot to RAM
adr r0, _start @ r0 <- current position of code
ldr r1, _TEXT_BASE @ test if we run from flash or RAM
cmp r0, r1 @ don’t reloc during debug
beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 @ r2 <- size of armboot
add r2, r0, r2 @ r2 <- source end address
copy_loop: @ copy 32 bytes at a time
ldmia r0!, {r3 - r10} @ copy from source address [r0]
stmia r1!, {r3 - r10} @ copy to target address [r1]
cmp r0, r2 @ until source end addreee [r2]
ble copy_loop
endif /* CONFIG_SKIP_RELOCATE_UBOOT */
其实这个段重定位代码是将片内IRAM中的代码搬移到DDR中。而我们通常是要将NAND中的数据搬移到DDR中,所以上面这段搬移代码可以忽略,自己写一个从NAND搬移数据到DDR的函数,放在此处。可以用C语言写,但注意一定要是位置无关码,因为此时我们的程序还运行在IRAM中,实际运行地址与链接地址不符。用C语言写位置无关码时,要全部使用局部变量。
ldr sp,=(0x22000000)
bl copy_uboot_to_ram
copy_uboot_to_ram函数便是一个从nand搬移代码到DDR的C语言函数,具体自己实现。
_TEXT_BASE:
.wordTEXT_BASE
_TEXT_BASE这个变量定义在start.S中,TEXT_BASE在链接脚本中定义
/*****分配空间****************/
stack_setup:
ldr r0, _TEXT_BASE @ upper 128 KiB: relocated uboot
sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area
sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo
ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ)
endif
sub sp, r0, #12 @ leave 3 words for abort-stack
and sp, sp, #~7 @ 8 byte alinged for (ldr/str)d
以上这段代码主要为环境变量,动态内存malloc,全局结构体变量gd_t分配空间。以及设置了一个absort栈。分配空间后,uboot的空间分配如下:
CONFIG_SYS_MALLOC_LEN
CONFIG_SYS_GBL_DATA_SIZE
以上两个值在include/autoconf.mk中定义
/*****清除BSS段****************/
clear_bss:
ldr r0, _bss_start @ find start of bss segment
ldr r1, _bss_end @ stop here
mov r2, #0x00000000 @ clear value
clbss_l:
str r2, [r0] @ clear BSS location
cmp r0, r1 @ are we at the end yet
add r0, r0, #4 @ increment clear index pointer
bne clbss_l @ keep clearing till at end
以上这段代码主要的作用为清除BSS段
ldr pc, _start_armboot
跳到C函数,此函数在lib_arm/Board.c中定义,注:此时uboot才从片内ram跳转到了DDR2