Hi,大家好!我是CrazyCatJack,你們可以叫我CCJ或者瘋貓。今天我給大家帶來的是u-boot的源代碼彙編段分析,以後還會給大家講解後續的C代碼,請持續關註哦^_^ 先簡單說一下u-boot,在嵌入式開發中,u-boot起著至關重要的作用:讀出嵌入式系統內核並啟動內核。因此非常有必要對u- ...
Hi,大家好!我是CrazyCatJack,你們可以叫我CCJ或者瘋貓。今天我給大家帶來的是u-boot的源代碼彙編段分析,以後還會給大家講解後續的C代碼,請持續關註哦^_^
先簡單說一下u-boot,在嵌入式開發中,u-boot起著至關重要的作用:讀出嵌入式系統內核並啟動內核。因此非常有必要對u-boot進行理解,瞭解其是如何啟動內核的,這樣我們才能隨心所欲地初始化系統,無論基於什麼架構,什麼開發板,都能夠輕鬆的去啟動內核。這一點難道不是最有吸引力的嗎?
如果大家有看到我的前一篇博客,就會對u-boot的啟動有一定程度的瞭解了。執行u-boot,首先是從啟動文件start.S開始的。它位於你所用CPU的文件下。比如我的路徑就是:“uboot-1.1.6/cpu/arm920t/start.S”。這基於你具體使用的CPU架構。打開它:
首先看第一條語句,跳轉到reset語句執行。那我們來看reset。
根據註釋,我們知道是要先讓CPU進入SVC32模式,也就是管理模式。具體的彙編代碼不再分析,需要大家自己去學習。若是你已經掌握了一定的彙編,則完全可以閱讀本篇博客,不然還是建議先學習一下彙編。u-boot代碼量還是很大的,再接著往下來看:
根據註釋,我們要關閉看門狗,否則此時CPU會不斷地重啟重啟。。。很明顯,在定義了具體的SOC型號後,define寄存器地址。包括看門狗控制寄存器、中斷屏蔽寄存器、還有時鐘分頻。關閉看門狗,關閉所有的中斷。
這裡如果你是從NOR Flash啟動的,這裡的r0就是0。如果你是從下載器或者調試器直接將代碼下載到SDRAM的,r0就為你自己設置的SDRAM代碼段的啟動地址(詳情看我的上一篇博客)。這裡會比較一下這兩個地址是否相同,就可以知道你是從哪裡啟動的了,是從NOR Flash還是直接從SDRAM。如果你從SDRAM啟動,則說明你已經初始化了SDRAM。如果你是從FLASH啟動,則這裡跳轉到 cpu_init_crit函數執行。
這裡是關caches,關MMU,然後跳轉到lowlevel_init函數執行開發板相關的配置。
這一部分程式博主開始很不理解,因為這裡涉及到了一個鏈接地址的概念。博主分不清此刻程式到底是在FLASH還是在RAM上。但是後來在論壇提問,大神給予瞭解答,博主終於懂了。這裡的SMRDATA是即將在SDRAM存儲的13個寄存器的鏈接地址,也就是說此刻這13個寄存器的值並未真正存儲到SDRAM,而是在NOR FLASH中。但是我們用這個SDRAM上的寄存器鏈接地址減去SDRAM代碼段開始地址(_TEXT_BASE),就得出了相對地址。又因為NOR FLASH的起始地址是0,所以起始地址+相對地址就是這13個寄存器在NOR FLASH上真正存儲的開始地址。這段代碼就是因為上述原因而進行的地址轉換。目的是得到13個寄存器在NOR FLASH上存儲的開始地址。
我們接著分析,下一步根據註釋是設置堆棧,將代碼段地址給r0,這裡我們設置的是0x33F80000.然後設置MALLOC段:分配空間,r0減去此段大小。再設置CFG_GBL_DATA段,同理r0減去此段大小,分配空間。再設置IRQ段、FIQ段。最後r0減去12,留出3個位元組的空間。下一步是跳轉到clock_init設置時鐘。
relocate這段代碼是要將u-boot從FLASH複製到RAM。_start是當前代碼的開始地址,_TEXT_BASE是代碼段的鏈接地址,如果二者相等則證明是從RAM啟動,無需複製代碼。轉去執行清BSS段代碼。_armboot_start是在當前文件即start.S中定義的第一條指令的運行地址,_bss_start是在board/開發板型號/u-boot.lds中定義的代碼段結束地址。結束地址減去開始地址等於代碼段長度,賦值給r2。然後就是如果你是從FLASH啟動則需進行代碼賦值,這裡是用C函數實現。
這裡我們設置的是USB48MHZ,總時鐘400MHZ.根據代碼,再接下來是清BSS段。
所謂的BSS段就是未初始化的靜態變數和全局變數,或者初始化為0的靜態變數和全局變數。將他們存入只會浪費空間。所以用到他們的時候再去初始化。這裡的清BSS段就是這樣的作用。
清完BSS段就是要複製代碼到RAM。這裡韋東山老師是自己用C語言實現的從FLASH到RAM程式的複製。因為版權原因,我們不便貼出。其實也是很容易的記憶體塊複製。
最後是進入到了_start_armboot。這是一個C函數,從這裡開始就是用C來實現讀出內核,啟動內核了。硬體相關的彙編程式講解結束!
版權聲明:
本博客未經允許,禁止轉載。
我尊重DENX Software Engineering為開源代碼做出的貢獻,他們做出u-boot,並將其開源供全世界的人們下載、學習和使用。
博主是跟隨韋東山老師學習的嵌入式Linux開發,其中的CopyCode2Ram函數為韋東山老師編寫。本文源於對學習成果的總結。
CCJ
2016-11-19 11:14:00