start.S详解
引入
如何找到uboot的入口?
因为uboot中有汇编阶段,所以不能直接找main.c;而uboot中整个程序的入口取决于u-boot.lds中链接脚本ENTRY声明的地方。( ENTRY(_stsrt) 。
总结: _start符号所在的文件就是整个程序的起始文件, _start所在处的代码就是整个程序的起始代码。
lowlevel_init函数分析
push {lr} //将lr寄存器压栈,以便于后面再进行bl调用lr存储的是函数的返回地址
lowlevel_init函数44-104行代码不重要。
/* when we already run in ram, we don't need to relocate U-Boot.
* and actually, memory controller must be configured before U-Boot
* is running in ram.
*/
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 1f /* r0 == r1 then skip sdram init */
/*beq 1f的意思是:如果r1==r2则向下跳转去执行标号1(f向下跳转,b向上跳转)*/
/* init system clock */
bl system_clock_init
/* Memory initialize */
bl mem_ctrl_asm_init
1:
/* for UART */
bl uart_asm_init
bl tzpc_init
/*
(1)本段的功能是检测当前代码的执行位置。判断是在SRAM中还是DDR中,即CPU是冷启动还是休眠唤醒复位,从而来决定是否要跳过后面的时钟、DDR的初始化代码。
(2)bic是位清除指令,其功能是:将pc中的某些位清零(r0中为1的位清零),剩下一些特殊的bit位赋值给r1。
(3)比较链接地址和当前地址的特定位,即比较r1和r2。若比较链接地址和当前地址的特定位相等,说明当前代码处于DDR中(休眠唤醒),则跳转到标号1处执行后面的代码(即跳过时钟、DDR的初始化代码);否则,继续执行后续的时钟、DDR的初始化代码
*/
物理地址
物理地址是物理设备设计生产时赋予的地址(像裸机中使用的寄存器地址是CPU设计时指定的,这就是物理地址),一旦确定不能更改。
虚拟地址
虚拟地址意思就是在软件操作和硬件操作之间增加一个层次,叫做虚拟地址映射层;有了虚拟地址映射后,软件操作只需要给虚拟地址,而硬件操作还是用原来的物理地址;映射层建立一个虚拟地址到物理地址的映射表。
MMU单元的作用
- MMU就是memory management unit是一个内部管理单元,实际上是SoC的一个硬件单元。
- 主要功能:实现虚拟地址到物理地址的映射。
- MMU单元是在cp15协处理器中进行控制(即要操控MMU进行虚拟地址映射就是对cp15协处理的寄存器进行编程)。
地址映射的额外收益
访问控制
(1)访问控制就是:在管理上对内存进行分块,然后每块进行独立的虚拟地址映射,然后在每一块的映射关系中同时还实现了访问控制(对该块可读、可写、只读、只写、不可访问等控制)
(2)在C语言中编程中经常会出现一个错误:Segmentation fault。实际上这个段错误就和MMU实现的访问控制有关。当前程序只能操作自己有权操作的地址范围(若干个内存块),如果当前程序指针出错访问了不该访问的内存块则就会触发段错误。
cache
(1)cache的工作和虚拟地址映射有关系。
(2)cache是快速缓存,意思就是比CPU慢但是比DDR块。CPU嫌DDR太慢了,于是乎把一些DDR中常用的内容事先读取缓存在cache中,然后CPU每次需要找东西时先在cache中找。如果cache中有就直接用cache中的;如果cache中没有才会去DDR中寻找。
参考博文
https://blog.youkuaiyun.com/wangdapao12138/article/details/79721012
https://www.cnblogs.com/linfeng-learning/p/9284060.html