uboot源码——汇编阶段的start.S文件
以下內容源于朱有鵬嵌入式課程的學習,如有侵權,請告知刪除。
?
一、相關內容
(1)?階段的定義
- 第一階段,即在內部SRAM運行的階段,簡單地理解為匯編階段,此階段主要涉及start.S文件,在cpu/s5pc11x/目錄下。第一階段以ldr pc _start_armboot為結束。
- 第二階段,即在DDR中運行的階段,簡單地理解為C語言階段,此階段主要涉及start_armboot函數,在uboot/lib_arm/board.c文件的444~908行。
(2)總結第一階段主要完成的任務
- 異常向量表的實現; ? ??
- 設置進入特權模式,即SVC模式;
- 檢查恢復狀態; ? ? ? ? ? ??
- IO狀態恢復;
- 關看門狗; ? ? ? ? ? ? ? ? ? ??
- 一些與SRAM、SROM相關的GPIO設置;
- 開發板的供電鎖存; ? ??
- 時鐘的初始化;
- DDR的初始化; ? ? ? ? ?
- 重新設置棧空間;
- uboot的重定位;? ? ??
- 轉換表的建立;
- 使能MMU。
可見,uboot的第一階段初始化了SoC內部的一些部件,初始化DDR并且重定位。
另外,學完整個uboot內容后,回過頭來看。uboot被分割成兩部分,即前8kb和整個ubooot。則前8k內容肯定包括了第一階段的操作任務,其中很重要的操作有重定位。
(3)程序入口和SI工具
- uboot中整個程序的入口取決于鏈接腳本中ENTRY聲明的地方。因為鏈接腳本(即board\samsung\x210\u-boot.lds)中有ENTRY(_start),因此_start符號所在的文件就是起始文件,所處的位置就是起始位置。
- SI工具的使用:search—>lookup reference.
二、start.S解析1
(1)config.h文件在mkconfig腳本中生成,此文件內容為#include <configs/x210.h>;
(2)version.h文件中的內容是#include "version_autogenerated.h。
- version_autogenerated.h文件是在主Makefile中自動生成的,相關的生成代碼:
?
- version_autogenerated.h文件中內容為:#define U_BOOT_VERSION "U-Boot 1.3.4"
(3)由于定義了宏CONFIG_ENABLE_MMU,因此包含asm/proc/domain.h,實際包含include\asm-arm\proc-arm\domain.h文件。
三、start.S解析2
1、啟動代碼的16字節頭部
(1)arm7和arm9的arm指令集,一個字類型是32bit。
(2)此段代碼用16個字節填充占位(這些數字貌似可以任意?字節內容后續計算重新填充?)。這里填充的原因是SD卡需要16字節的校驗?
(3).word是arm匯編的偽指令,含義是當前地址的值為XX,XX的內容一般為數值或者地址。
- 如:.word 0x2000表示當前地址的值為0x2000;.word _start 表示當前地址的值為_start。
2、構建異常向量表
?
(1)異常向量表由硬件決定,軟件只是參照硬件設計來實現。
(2)此向量表只是虛有其表,并未做非常細致的異常處理。
(3)復位異常處理代碼是b reset,reset是個函數。
(4)上圖中的最后一句是讓內存16字節對齊,如果不對齊,用0xdeadbeef這個數字填充。
(5)學完裸機中的中斷向量表可知,這里類似的處理。
?
3、一些地址值
?
(1)_TEXT_BASE(4字節)這個內存地址出的值為TEXT_BASE(即0xc3e00000)。
(2)_TEXT_PHY_BASE(4字節)這個內存存放的值為CFG_PHY_UBOOT_BASE(uboot的物理基地址)。
(3)CFG_PHY_UBOOT_BASE(定義在x210_sd.h中)為 MEMORY_BASE_ADDRESS + 0x3e00000
- 在x210_sd.h中有#define MEMORY_BASE_ADDRESS 0x30000000;
- 因此CFG_PHY_UBOOT_BASE為0x33e00000,這個是uboot在DDR中的物理地址。
(4)總結,即標簽表示地址,.word后面的表示此內存地址中存儲的值。
- 如_bss_end: .word _end表示地址_bss_end上存放的值是_end。
四、start.S解析3?
1、reset中斷處理函數
?
(1)由博客http://blog.csdn.net/oqqhutu12345678/article/details/71215628可知,因為0xd3=1101 0011,則cpu設置為SVC模式、arm狀態,禁止FIQ、IRQ中斷。
(2)整個uboot工作時,cpu一直處于SVC模式。
?
2、Cpu的初始化(設置l1,l2cache和MMU等內容)
3、識別并暫存啟動介質選擇
(1)啟動介質由SoC的OM0:OM5這6個引腳的高低電平決定?
(2)由#define PRO_ID_BASE 0xE0000000和#define OMR_OFFSET 0x04得到寄存器0xE000 0004
- 這個寄存器會根據OM引腳狀況,硬件自動設置值。
(3)此三行代碼后,r2存儲了一個數字,后續通過該數字進行啟動介質的判斷。
??
(4)通過判斷r2中的值,來確定是從哪里啟動的。
- 如果r2中的值為0xc,那從SD卡啟動,然后把#BOOT_MMCSD(#define ?BOOT_MMCSD? 0x3)賦給r3。
(5)最后兩行中,因為有#define INF_REG_BASE 0xE010F000和#define INF_REG3_OFFSET 0x0c,則合成寄存器0xE010F00C,然后把r3中的值放入其中。
?
4、第一次設置棧
(1)這次設置棧是在SRAM中設置的,因為當前整個代碼還在SRAM中運行,此時DDR還未被初始化還不能用。
- 棧地址0xd0036000是自己指定的,指定的原則就是這塊空間只給棧用,不會被別人占用。
(2)之所以要初始化棧,是因為接下來調用的lowlevel_init函數中還要調用其他函數。
- bl只會將返回地址存儲到LR中,但是只有一個LR,所以在第二層調用函數前要先將LR入棧,否則函數返回時第一層的返回地址就丟了。
---------------------------------------lowlevel_init函數--------------------------------------------
五、start.S解析4?
1、lowlevel_init函數
(1)lowlevel_init在uboot\board\samsung\x210\lowlevel_init.S中。
(2)檢查復位狀態
- 因為復雜CPU支持多種復位狀態(冷上電、休眠復位等),因此在復位代碼中檢查復位狀態,判斷到底是哪一種。
- 冷上電時DDR需要初始化,而休眠狀態下復位不需要再次初始化DDR。
(3)IO狀態恢復;
(4)關看門狗;
(5)一些與SRAM、SROM相關的GPIO設置(下圖);
?
(6)開發板的供電鎖存(下圖)
?
六、start.S解析5?
1、判斷當前代碼執行位置(判斷在SRAM還是DDR中)
為什么要判斷?
- BL1在SRAM中有一份,在DDR中也有一份。
- 如果是冷啟動,則當前代碼是在SRAM中運行的BL1;如果是低功耗狀態的復位,則當前代碼是在DDR中運行的。
- 判斷的目的是指導后面代碼的運行。
- 譬如在lowlevel_init.S中判定當前代碼的運行地址,就是為了確定是否執行時鐘初始化和初始化DDR的代碼。
- 如果當前代碼是在SRAM中,說明是冷啟動,則需要初始化時鐘和DDR;
- 如果當前代碼是在DDR中,說明是熱啟動,則時鐘和DDR都不用再次初始化。
2、時鐘初始化:system_clock_init
- 詳細可以查閱代碼http://blog.csdn.net/oqqhutu12345678/article/details/73188932
3、內存的初始化:mem_ctrl_asm_init
- 代碼見博客http://blog.csdn.net/oqqhutu12345678/article/details/73189059
(1)在uboot/cpu/s5pc11x/s5pc110中。該函數和裸機中初始化DDR代碼是一樣的。實際裸機中初始化DDR的代碼就是從這里抄的。
(2)配置值中有一個和裸機中講的不一樣,即DMC0_MEMCONFIG_0
- 它在裸機中配置值為0x20E01323,在uboot中配置為0x30F01313。
- 在裸機中DMC0的256 MB內存地址范圍是0x20000000-0x2FFFFFFF;
- 在uboot中DMC0的256MB內存地址范圍為0x30000000-0x3FFFFFFF。
- DMC0上允許的地址范圍是20000000-3FFFFFFF(一共是512MB),而實際只接了256MB物理內存,SoC允許我們給這256MB挑選地址范圍。
- 在uboot中,可用的物理地址范圍為:0x30000000-0x4FFFFFFF,一共512MB,其中30000000-3FFFFFFF為DMC0,40000000-4FFFFFFF為DMC1。
- 注意條件編譯的條件,配置頭文件中考慮了不同時鐘配置下的內存配置值,主要目的是讓不同時鐘需求的客戶都能找到合適自己的內存配置值。
4、串口初始化:打印一個“O”
- uart_asm_init函數
5、pop {pc}返回前通過串口打印“K”
?
----------------------------------lowlevel_init函數結束----------------------------------------
七、start.S詳解6
1、第二次設置棧
?
(1)第一次設置棧,是在調用lowlevel_init函數前。那時程序在SRAM中執行,所以在SRAM中分配了一部分內存作為棧。
(2)第二次因為DDR已經被初始化,因此要把棧挪移到DDR中,所以要重新設置棧。
- 實際設置的棧的地址是33E00000,剛好在uboot的代碼段的下面緊挨著。
- 因為是滿減棧,所以棧向下增長。注意uboot基地址在0x33e00000,向上增長。
(3)為什么要再次設置棧?
- DDR已經初始化了,已經有大片內存可以用了,沒必要再把棧放在SRAM中;
- 原來SRAM中內存大小空間有限,棧放在那里要注意不能使用過多,否則棧會溢出;
- 我們及時將棧遷移到DDR中也是為了盡可能避免使用棧時的諸多不便。
?
2、再次判斷運行地址是在SRAM中還是DDR中
(1)上次判斷是為了決定是否要執行初始化時鐘和DDR的代碼,本次判斷是為了決定是否進行uboot的重定位。上圖中最后一行代碼如果不執行,則說明需要重定位。
- 冷啟動時,uboot的前一部分(16kb或者8kb)開機自動從SD卡加載到SRAM中運行,uboot的第二部分(其實第二部分是整個uboot)還躺在SD卡的某個扇區開頭的N個扇區中。此時uboot的第一階段即將結束(第一階段該做的事基本做完了),結束之前要把第二部分加載到DDR中鏈接地址處(0x33e00000),這個加載過程就叫重定位。
- D0037488這個內存地址在SRAM中,這個地址中的值是被硬件自動設置的。硬件根據我們實際電路中SD卡在哪個通道中,會將這個地址中的值設置為相應的數字。譬如我們從SD0通道啟動時,這個值為EB000000;從SD2通道啟動時,這個值為EB200000。
- 我們確定是從MMCSD啟動,因此最終跳轉到mmcsd_boot函數中去執行重定位動作,即把SD卡中相應的內容復制到內存中。
- 真正的重定位是通過調用movi_bl2_copy函數完成的,在uboot/cpu/s5pc11x/movi.c中。
- 此函數包含copy_bl2(2, MOVI_BL2_POS, MOVI_BL2_BLKCNT,CFG_PHY_UBOOT_BASE, 0)函數。
- 參數2表示通道2;
- MOVI_BL2_POS是uboot的第二部分在SD卡中的開始扇區,這個扇區數字必須和燒錄uboot時燒錄的位置相同;
- MOVI_BL2_BLKCNT是uboot的長度占用的扇區數;
- CFG_PHY_UBOOT_BASE是重定位時將uboot的第二部分復制到DDR中的起始地址(33E00000)。
?
?
八、start.S詳解7
最后一段代碼,作用是配置MMU、重新設置棧、清bss、跳轉到start_armboot函數中去執行BL2階段。
1、MMU(memory management unit),內存管理單元。
- MMU實際上是SOC中一個硬件單元,它的主要功能就是實現虛擬地址到物理地址的映射。
- MMU單片在CP15協處理器中進行控制,也就是說要操控MMU進行虛擬地址映射,方法就是對cp15協處理器的寄存器進行編程。
2、第三次設置棧
- 這次設置棧還是在DDR中,之前雖然已經在DDR中設置過一次棧了,但是本次設置棧的目的是將棧放在比較合適(安全,緊湊而不浪費內存)的地方。
- 我們實際將棧設置在uboot起始地址上方2MB處,這樣安全的棧空間是:2MB-uboot大小-0x1000=1.8MB左右。這個空間既沒有太浪費內存,又足夠安全。
3、清理bss
- 注意表示bss段的開頭和結尾地址的符號是從鏈接腳本u-boot.lds得來的。
4、ldr pc, _start_armboot
- start_armboot函數在uboot/lib_arm/board.c中,這是一個C語言實現的函數。這個函數就是uboot的第二階段。
- 這句代碼的作用就是將uboot第二階段執行的函數的地址傳給pc,實際上就是使用一個遠跳轉直接跳轉到DDR中的第二階段開始地址處。
- 遠跳轉的含義就是這句話加載的地址和當前運行地址無關,而和鏈接地址有關。因此這個遠跳轉可以實現從SRAM中的第一階段跳轉到DDR中的第二階段。
- 這里這個遠跳轉就是uboot第一階段和第二階段的分界線。
總結
以上是生活随笔為你收集整理的uboot源码——汇编阶段的start.S文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux中的信号2——进程如何处理信号
- 下一篇: 软件工程学习笔记(二)~软件需求说明书