對於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如何工作的,請看第二階段的分析。