經過前面的調試瞭解到s5pv210這個芯片的啓動流程是須要將u-boot分爲兩部分的分別爲SPL和u-boot。這裏我使用網上的方式不直接使用u-boot的SPL鏈接腳本單獨生成SPL的image而是用前面介紹的方法 [http://www.javashuo.com/article/p-cksnnieg-ve.html](u-boot 移植 --->三、S5PV210啓動序列)將u-boot的前16k直接截取出來做爲SPL。
IROM中
這一部分能夠參考其餘博文,或者三星的文檔。
在IRAM中
經過啓動鏈接腳本arch\arm\cpu\u-boot.lds 咱們找到了整個代碼的入口_start。全局尋找找到文件arch\arm\lib\vectors.S符合本次架構因此整個代碼入口就在這裏內容以下:html
_start: #ifdef CONFIG_SYS_DV_NOR_BOOT_CFG .word CONFIG_SYS_DV_NOR_BOOT_CFG #endif b reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq
因此能夠看出來這裏也是符合ARM架構要求,在這裏定義了中斷向量表,而後第一句指令是一個跳轉指令,將執行流跳轉到reset符號了,通過查找這個符號定義在arch\arm\cpu\armv7\start.S 這是架構通用的部分因此能夠參考u-boot源碼這裏僅羅列這段程序操做的內容:
1. 檢查是否使能了大物理頁面擴展,若是使能了則進行必要的配置。(CP15)
2. 禁止IRQ和FIQ,配置處理器模式爲SVC。(CPSR)
3. 設置_start 符號地址爲異常向量表基址,並禁止cache,TLB,BP,MMU(CP15)
4. 調用lowlevel_init(若是定義了CONFIG_SKIP_LOWLEVEL_INIT_ONLY則不執行),這一部分就是芯片移植人員須要早期初始化的內容能夠放在這個標號下實現,我這裏就是配置時鐘,配置芯片DRAM接口,配置UART0。
5. 設置堆棧爲IRAM空間,並拷貝SD卡中特定地址的完整u-boot鏡像到DRAM指定地址,SD的驅動實在芯片的IROM中完成的。(這一部分是原本的u-boot內容沒有的由於咱們未使用u-boot的SPL方式單獨構建SPL程序因此修改了這部份內容)。數組
DRAM中緩存
完成上面的操做後進行絕對跳轉就能到DRAM地址空間繼續運行代碼了,由於代碼自己就是鏈接在這個地址的。跳轉後運行_main 符號處的指令他實如今rch\arm\lib\crt0.S 中操做序列大體以下:
1. 從新修改棧基址到DRAM地址空間中
2. 調整棧指針 (實際則是在棧中分配內存)這裏是爲malloc和struct global_data 的GD變量預留內存
3. 初始化 GD變量的部分紅員,這是整個u-boot的一個重要的全局數據用來記錄各類數據狀態等。架構
執行了以上的處理步驟後將又可使用C代碼調用了。而後調用board_init_f 這是在common\board_f.c 中實現的屬於u-boot的內容的代碼,主要就是圍繞GD變量進行操做詳細的操做這裏不深刻分析,就是進行一些配置初始化相關的主要就是調用initcall_run_list 這個函數依次執行一個初始化list進行初始化,這個初始化函數數組init_sequence_f也是在common\board_f.c 中定義並根據u-boot的使用kbuild配置產生的配置文件編譯生成。其中大部分初始化函數都是平臺無關的少許與平臺相關須要注意對應修改下,除此以外須要注意的是在這裏執行board_init_f 相關調用時有打開cache。這裏執行完成後GD變量的成員也愈來愈完善,再次根據GD中記錄的信息修改SP棧指針。而後還須要再次移動並重定位代碼,這一次移動是爲了爲了將u-boot放到DRAM高地址爲拷貝Linux內核image準備空間,拷貝完成後無效指令和數據cache(由於原來地址空間的緩存已經無效了)。這裏還使用了一個技巧使拷貝完成後直接返回到新地址的下一條指令執行。使用的方式就是在LR寄存器上作文章,具體參考代碼實現。而後在次修改異常向量表地址到新的地址空間。注意的是這裏代碼重定向仍是比較複雜一點的不是簡單的拷貝,由於前面的GD變量也是須要維護的,主要就是而後對新地址的數據段的拷貝。而後就是調用common\board_r.c 文件中的board_init_r 函數,這個函數的實現和board_init_f 一模一樣他們末尾的字母就是標記他們調用的配置是在重定向前(f)和以後(r)執行的初始化。最後執行的就是 run_main_loop這裏就是u-boot程序的主循環,在這裏進行u-boot命令等相關功能的操做。函數
總結
u-boot的整個執行過程的粗流程實際上是不復雜的,調試過程最複雜的感受就是DRAM的配置那些部分。整個移植實際上出去kbuild配置工具外就是,一部分關於底層的初始化配置相關內容,其他就是u-boot的大體執行流程。流程我在作一下梳理總結以下:
_start(arch\arm\lib\vectors.S)向量表,而後跳轉(reset)--->arch\arm\cpu\armv7\start.SARM 架構相關的操做,調用(lowlevel_init)---> 平臺相關的底層或前提初始化部分的必要配置,調用(_main)--->arch\arm\lib\crt0.S 進行u-boot相關功能的變量,棧等部分的維護初始化等,調用(board_init_f)--->common\board_f.c 根據配置調用以系列的初始化調用,返回crt0.S,重定位u-boot代碼在DRAM中的位置,調用(board_init_f)--->common\board_r.c 繼續進行必要的初始化--->u-boot loop(若是引導Linux則u-boot就執行完了)。若是像知道更詳細的內容能夠參考這個博主的博客:https://to-run-away.blog.csdn.net/article/details/81711413?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.control工具