对于uboot中的start.S主要做的事情就是系统各个方面的初始化,大致可以分为以下6个部分:
1、设置CPU模式
2、关闭看门狗
3、关闭中断
4、设置堆栈SP指针
5、清除bss段
6、异常中断处理
下面按照start.S源码逐个分析以上部分
1、设置CPU模式
41行,globl相当于,相当于C语言的extern,全局变量,外部可以访问;而_start是整个文件的开始执行的入口
42行,进入_start之后跳转到reset的位置。我们跟踪reset看看做了什么东西:
113行,将cpsr的值赋给R0寄存器
114行,清除r0的bit[4:0]位
115行,将r0和0xd3进行或运算,然后将结果给r0,即把r0的bit[7:6]和bit[4]和bit[2:0]置为1
116行,将r0的值赋给cpsr
功能:
首先来看一下cpsr的结构
r0中的值经过几条语句的运算之后,r0的bit[7:6]和bit[4]和bit[2:0]置为1,将r0的值赋给cpsr也就是将cpsr对应的位也置为1,从上面的结构中我们可以看到,置位之后,将CPU设置为SVC模式,也就是管理模式,并且屏蔽外部中断(IRQ)和快速中断(FIQ)。
好了,分析完reset那我们回到最开始的地方
43-49行以及51-57行,也就是将各个步骤的地址存到pc中,pc是程序计数器,相关消息请查阅ARM汇编的相关知识,此处不再赘述。
43-57行分别对应着在发生“未定义指令”、“软件中断”、“预取指错误”、“数据错误”、“未定义”、“普通中断”、“快速中断”时,跳转到对应的位置执行相应的代码。
59行,说明接下来的代码都要16字节对齐,不足之处要用0xdeadbeef补充,嘿嘿~坏牛肉
_bss_start和_bss_end的定义则是在脚本文件中,目的是保存命令参数。
小结:第一步骤要做的事情主要就是设置CPU为SVC模式,并且关闭中断。
2、关闭看门狗
我就直接看对应的板子,就是往WTCON中写0就能关闭看门狗。有兴趣可以去查看datasheet中的描述,如下:
3、关闭中断
关中断也很简单,直接置起中断屏蔽位就可以了,因为我用的是2440的板子,所以直接看对应的代码吧
嘿嘿,说到mask,我倒是想到我高中同桌了,一直叫他mask,许久不见,不知道他最近怎么样了......
说白了就是屏蔽下面这些中断,有兴趣还是去看datasheet,如下:
4、设置堆栈SP指针
注意,前面说到TEXT_BASE 的定义为TEXT_BASE = 0x33D00000,而我们也能找到192和193行的两个立即数的定义
#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024)
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
194-196行,如果用到中断的话,那么再把r0的值减去IRQ 和FIQ的堆栈值
197行,再减去终止异常所用到的堆栈的大小,也就是12个字节,最后存入sp
说了那么多,还是直接上图:
5、清理bss
200-201把bss_start和bss_end的地址分别存入r0和r1,然后开始清理。
206行,比较当前地址是否到了bss段结束位置
207行,如果小于或者等于,就重新开始,直到地址超过bss的_end位置,即实现了整个bss段都清零
5、设置异常中断
这部分代码最让语句看上去并不难,但是irq_save_user_regs和bad_save_user_regs具体实现的流程是怎么样的,还是弄得不太清楚,日后再说吧。
总结
最后再说一下,第一阶段拼死拼活做了那么多准备工作,最最最重要的就是调用start_armboot这个C语言函数,这也就是第二阶段的入口。具体start_armboot如何工作的,请看第二阶段的分析。