/********************设置处理器模式****************************************/
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
*/
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)
orr
r0, r0, #0x00000002
@ set bit 1 (--A-) Align
orr
r0, r0, #0x00000800
@ set bit 12 (Z---) BTB
mcr
p15, 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.
*/
mov
ip, lr
@ persevere link reg across call
bllowlevel_init @板级初始化
mov
lr, ip
@ restore link
mov
pc, 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
#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