uboot启动阶段分析二

物理基址定义

_TEXT_PHY_BASE:
	.word	CFG_PHY_UBOOT_BASE

start.s 中使用 _TEXT_PHY_BASE 存放物理基址。这个变量很重要,因为我们在 u-boot 中使用 MMU ,在 MMU 没有开启之前,需要这个变量来保证程序能在正确的地址运行

通过在 u-boot 源码中全局搜索可以发现, CFG_PHY_UBOOT_BASE 定义在 uboot/include/configs/x210_sd.h

#define MEMORY_BASE_ADDRESS	0x30000000
...
#define CFG_PHY_UBOOT_BASE	MEMORY_BASE_ADDRESS + 0x3e00000

CFG_PHY_UBOOT_BASE 这个宏是在 MEMORY_BASE_ADDRESS 的位置上偏移了 0x3e00000 的空间

链接脚本需要的变量

.globl _bss_start
_bss_start:
	.word __bss_start

.globl _bss_end
_bss_end:
	.word _end

_bss_start _bss_end 这两个变量之前也在链接脚本中见过

BSS 段通常是指用来存放程序中未初始化的或者初始化为0的全局变量和静态变量的一块内存区域

BSS 段使用前需要清0,通过在这里提供 BSS 段的地址,方便链接时清0

复位

reset:
	/*
	 * set the cpu to SVC32 mode and IRQ & FIQ disable
	 */
	@;mrs	r0,cpsr
	@;bic	r0,r0,#0x1f
	@;orr	r0,r0,#0xd3
	@;msr	cpsr,r0
	msr	cpsr_c, #0xd3		@ I & F disable, Mode: 0x13 - SVC

到这里就是 u-boot 真正的复位代码了

MSR 指令用亍将操作数的内容传送到程序状态寄存器的特定域中

cpsr 是 ARM 架构的当前程序状态寄存器,而 cpsr_c 是程序状态寄存器的后8位,也就是控制位

cpsr 寄存器的描述如下

在这里插入图片描述

I 和 F 位对应的是 IRQ 和 FIQ 中断的标志位,置1为关闭

因为模式位是前5位控制的,所以 0xd3 相当于 0x13,对应的就是 SVC(管理)模式

再加上代码中的注释,我们就可以知道这段代码的作用就是让处理器进入 SVC 模式并关闭中断

cpu_init_crit

这里是为了初始化一些重要的寄存器和内存的时钟

cpu_init_crit 只会在重启的时候运行,当 u-boot 在 ram 中的时候不会运行

这部分做了这些事

  1. 重新初始化开启 L2 cache
  2. 刷新 L1 的数据和指令 cache
  3. 关闭 MMU
  4. 读取启动介质选择

## 读取启动信息

ldr	r0, =PRO_ID_BASE        @ PRO_ID_BASE=E000 0000
ldr	r1, [r0,#OMR_OFFSET]    @ OMR_OFFSET=0000 0004
bic	r2, r1, #0xffffffc1     

这段代码目的是从 E000 0004 这个寄存器读取电平信息,这个寄存器是 OM 引脚的地址。通过设置 OM 引脚的电平,就可以设置 u-boot 的启动介质

bic 的作用是为了清除无关的位,方便后面进行启动介质的判断

/* NAND BOOT */
cmp	r2, #0x0		@ 512B 4-cycle
moveq	r3, #BOOT_NAND

...

/* SD/MMC BOOT */
cmp     r2, #0xc
moveq   r3, #BOOT_MMCSD	

/* NOR BOOT */
cmp     r2, #0x14
moveq   r3, #BOOT_NOR	

通过判断前面存入 r2 的值,得到不同的启动介质的信息

lowlevel_init

ldr	sp, =0xd0036000 /* end of sram dedicated to u-boot */
sub	sp, sp, #12	/* set stack */
mov	fp, #0

bl	lowlevel_init	/* go setup pll,mux,memory */

在这里插入图片描述

从图中可以看出 0xd0036000 是 sram 的地址空间,此时 ddr 还没有初始化完成,只能使用不需要初始化的 sram

通过 sub 创建了一个 stack,再让 fp(栈帧指针)指向 stack 的开头(fp 用作栈的开头,sp 作为栈的当前位置,fp 和 sp 一起组成了一个栈帧)

设置 stack 是为了用来存储 LR 的值,因为当前是被调用的子函数中, LR 中存储着当前子函数的范围地址,如果直接使用 bl 调用子函数,就会丢失当前子函数的返回地址

所以在子函数中调用子函数时,需要先将当前的 LR 压栈

后记

关于 SP FP PC LR 寄存器有空会说说的,我也是在学习汇编才接触到这些寄存器,也是在看了些资料才稍微了解了些


个人博客
公众号:greedyhao

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值