这一节我们继续来分析lowlevel_init。
一、判断当前代码执行的位置
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 */
/* init system clock */
bl system_clock_init
/* Memory initialize */
bl mem_ctrl_asm_init
1:
/* for UART */
bl uart_asm_init
bl tzpc_init
影像逻辑的主要在下面两行:
cmp r1, r2
beq 1f
比较r1和r2 如果相等就 beq 1f 1:是个标号,可以认为是跳转标记,类似于c语言中的goto。f:是向前找,也就是向前找到标号为“1”的位置继续执行。
仔细看可以看出如果r1和r2不相等说明是冷启动直接上电,如果相等说明是热启动不用在初始化时钟和内存,直接从串口开始初始化。
ldr r0, =0xff000fff
bic r1, pc, r0 //bi是将r0中的数取反再和pc(当前的运行地址)值做“与”操作目的是清除pc值中的开头的2*4位和最后的3*4位保留bit_12~bit_23
ldr r2, _TEXT_BASE //取链接地址做出同上的操作,最终将“链接地址的12~23位”与“PC”的12~23位进行比较,其实是从4K(0xfff)之后的位置开始比较,这里做了一个小技巧,因为uboot启动到这里肯定不会超过4K,故比较一部分地址即可。
bic r2, r2, r0
cmp r1, r2
beq 1f
如果是冷启动最终都会执行:
bl system_clock_init //时钟系统初始化
bl mem_ctrl_asm_init //内存单元初始化比如说 DDR
之后还会执行
bl uart_asm_init
bl tzpc_init
这里会初始化串口,同时打印字符“O”“K”。
二、总结
到此lowlevel_init就算是万事大吉,是不是觉得很简单料狠少。其实不然,最后的几部分:时钟系统、DDR、串口都是重头戏,会单独用篇幅来讲解。起初把lowlevel_init分成两部分是想在第二部分展开说,但是发现还是每个大块,单独说把,之后我会把链接粘到响应的位置。
lowlevel_init的内容包括:
0)关看门狗
1)供电锁存
2)时钟系统初始化
3)DDR初始化
4)串口初始化同时打印"O“”K“