这一篇主要讲述uboot对于CPU的初始化
Uboot源码开始的地方可以参考链接文件u-boot.lds里面的.text段的第一句话,对于2010.12版本的uboot(基于4412平台),其内容是这样的:
.text :
{
arch/arm/cpu/armv7/start.o (.text)
board/samsung/smdk4212/libsmdk4212.o(.text)
arch/arm/cpu/armv7/exynos/libexynos.o (.text)
*(.text)
}
可见uboot源码的第一条语句位于arch/arm/cpu/armv7/start.S文件中
下面进入到arch/arm/cpu/armv7/start.S文件,(分析的顺序不是按照程序的书写顺序,而是程序的执行顺序)
.globl _start
_start: b reset
可见程序的开始就是跳到标号为reset的地方执行
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr,r0
…….
bl cpu_init_crit
从程序的注释就可以看出以上语句是让cpu进入SVC模式,然后跳转到cpu_init_crit
cpu_init_crit:
blcache_init
/*
*Invalidate L1 I/D
*/
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,#0x00001000 @ set bit 12 (---I) Icache
orr r0,r0,#0x00000002 @ set bit 1 (--A--) Align
orr r0,r0,#0x00000800 @set bit 11 (Z--) BTB
mrc p15,0,r0,c1,c0,0
mov ip,lr @persevere link reg across call
bl lowlevel_init @go setup pll,mux,memory
mov lr,ip @restore link
mov pc,lr @back to my caller
cpu_init_cirt主要是初始化cache,关闭MMU和中断,然后进入到lowlevel_init,lowlevel_init位于board/samsung/smdk4212/lowlevel_init.s文件中
.globllowlevel_init
lowlevel_init:
ldr r0,=(INF_REG_BASE+INF_REG1_OFFSET)
ldr r1,[r0]
/*Sleepwakeup reset*/
ldr r2,=S5P_CHECK_SLEEP
cmp r1.r2
beq wakeup_reset
判断CPU是怎样进入复位的,如果是从睡眠唤醒进入复位的,就跳转到wakeup_reset,否则继续往下执行
blpmic_init
bl uart_asm_init
初始化电源管理芯片和串口,Uboot运行时打印出来的信息都是通过这个初始化的串口打印出来的
bl read_om
......
read_om:
/*Readbooting information*/
ldr r0,=S5PV310_POWER_BASE
ldr r1,[r0,#OMR_OFFSET]
bic r2,r1,#0cffffffc1
S5PV310_POWER_BASE是OM_STAT寄存器,存储OM管脚的信息,整个语句下来,就把OM管脚信息(启动信息)存储在了寄存器r2中,接下来的程序就是判断从何处启动了
……
/* eMMC 4.4 BOOT*/
cmp r2, #0x8
moeeq r2,#BOOT_EMMC_4_4
cmp r2,#0x28
moveq r3,#BOOT_EMMC_4_4
ldr r0,=INF_RGE_BASE
str r3,[r0,#INF_REG3_OFFSET]
ldr pc,lr
我这个开发板是从emmc4.4启动所以满足上述语句,同时将启动信息保存在INFORM3寄存器中,然后回到程序跳转的地方,接着bl read_om往下执行
ldr r0, =0xff000fff
bic r1,pc,r0 /*r0<-current base addr of code*/
ldr r2,_TEXT_BASE /*r1<-original base addr in ram*/
bic r2,r2,r0 /*r0<-current base addr of code*/
cmp r1,r2 /*compare r0,r1*/
beq after_copy
判断当前程序指针是否在SDRAM中,如果是,则跳过SDRAM的初始化,也不需要装载u-boot.bin了,直接执行after_copy,我这个开发板是从emmc启动的,所以程序此时还不在SDRAM中,还要接着往下执行
/*Memory initialize */
bl mem_ctrl_asm_init
/*initsystem clock*/
bl system_clock_init
b 1f
内存初始化以及系统时钟初始化,然后跳转到前面的标号为1处
1:
bl tzpc_init
b load_uboot
初始化trustzoneprotection controller,并跳转到load_uboot
load_uboot:
ldr r0,=INF_REG_BASE
ldr r1,[r0,#INF_REG3_OFFSET]
......
cmp r1,#BOOT_NAND
......
cmp r1,#BOOT_EMMC_4_4
beq emmc_boot_4_4
......
通过判断从何处启动,跳转到相应的标号处执行,我这块开发板将跳转到emmc_boot_4_4,该标号处的语句作用就是从emmc处拷贝uboot到SDRAM中,然后跳转到after_copy处
after_copy:
#ifdef CONFIG_SMDKC220
/*set up C2C*/
ldr r0,=S5PV310_SYSREG_BASE
ldr r2,=GENERAL_CTRL_C2C_OFFSET
ldr r1,[r0,r2]
ldr r3,=0x4000
orr r1,e1,r3
str r1,[r0,f2]
#endif
#ifdef CONFIG_ENABLE_MMU
bl enable_mmu
#endif
/*store second boot information in u-boot C lelve variable*/
ldr r0,=CONFIG_PHY_UBOOT_BASE
sub r0,r0,#8
ldr r1,[r0]
ldr r0,_second_boot_info
str r1,[r0]
........
ldr r0,_board_init_f
mov pc,r0
after_copy所做的工作主要就是初始化设置C2C,打开MMU,并跳到board_init_f执行板级初始化。
总结:
CPU的初始化主要工作如下:
1、 将CPU设成SVC模式,并且关闭中断和MMU
2、 初始化串口,便于UBOOT执行时打印相关信息
3、 判断电路板设置为从何处启动
4、 将uboot从启动设备拷贝到SDRAM