总结于朱有鹏老师的嵌入式课程,感谢朱老师
以k210为例
物理地址:物理设备设计生产时赋予的地址,是确定的硬件编码
虚拟地址:在我们软件操作和硬件被操作之间增加一个层次,叫做虚拟地址映射层。软件操作只需要给虚拟地址,映射层建立一个虚拟地址到物理地址的映射表。虚拟地址在映射表中查询得到对应的物理地址再发给硬件去执行
内存管理单元。MMU实际上是SOC中一个硬件单元,它的主要功能就是实现虚拟地址到物理地址的映射。
通过操控MMU可以进行虚拟地址映射,方法就是对cp15协处理器的寄存器进行编程。
在管理上对内存进行分块,然后每块进行独立的虚拟地址映射,每一块的映射关系中同时还实现了对该块可读、可写、只读、只写、不可访问等控制
实现cache(快速缓存),把一些DDR中常用的内容事先读取缓存在cache中,加快读取数据的速度
转换表分2部分,表索引和表项。表索引对应虚拟地址,表项对应物理地址。一对表索引和表项构成一个转换表单元,能够对一个内存块进行虚拟地址转换。真正的转换表就是由若干个转换表单元构成的,每个单元负责1个内存块,总体的转换表负责整个内存空间(0-4G)的映射。整个建立虚拟地址映射的主要工作就是建立转换表
转换表不需要软件去干涉使用,而是将基地址TTB设置到cp15的c2寄存器中,然后MMU工作时会自动去查转换表。
使能MMU单元
enable_mmu:
/* enable domain access */
ldr r5, =0x0000ffff
mcr p15, 0, r5, c3, c0, 0 @load domain access register
/* Set the TTB register */
ldr r0, _mmu_table_base
ldr r1, =CFG_PHY_UBOOT_BASE
ldr r2, =0xfff00000
bic r0, r0, r2
orr r1, r0, r1
mcr p15, 0, r1, c2, c0, 0
/* Enable the MMU */
mmu_on:
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #1
mcr p15, 0, r0, c1, c0, 0
nop
nop
nop
nop
第三次设置栈, 上一次设置栈只是简单的放置在DDR中。而这一次会把栈放在一个安全又不浪费内存的地方(uboot起始地址上方2MB处)
stack_setup:
#if defined(CONFIG_MEMORY_UPPER_CODE)
ldr sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000)
#else
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#if defined(CONFIG_USE_IRQ)
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
#endif
清理bss段代码
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
ldr pc, _start_armboot //清理完,远跳转到start_armboot即uboot/lib_arm/board.c中直接开始uboot的第二阶段