mini2440 u-boot linux 内核启动,u-boot.2012.10——mini2440(二、启动流程分析)
參考資料:https://blog.csdn.net/suiyuan19840208/article/details/7239949
https://blog.csdn.net/pugu12/article/details/47011159
http://tscsh.blog.163.com/blog/static/200320103201312645149965/
https://blog.csdn.net/winheroii58/article/details/6803327
1、第一階段功能
* 硬件設備初始化
* 加載u-boot第二段代碼到RAM空間
* 設置好棧
* 跳轉到第二段代碼入口
2、第二段代碼的功能
* 初始化本階段使用的硬件設備
* 檢測系統的內存映射
* 將內核從Flash讀到RAM中
* 為內核設置啟動參數
* 調用內核
3 、u-boot第一階段代碼分析
我們在編譯完成之后,觀察頂層目錄有個u-boot.lds的鏈接腳本
* 經過編譯之后,查看文件u-boot.lds鏈接腳本,可以看到第一個鏈接文件是start.S
4、start.S
* 設置異常向量
當一個異常產生時,CPU根據異常號在異常向量表中找到對應的異常向量,然后執行異常向量處的跳轉指令,,CPU跳轉到對應的異常處理程序執行。
其中復位異常向量的指令“b start_code”決定了啟動后將自動跳轉到標號"start_code"處執行。
* CPU進入SVC模式
從數據手冊上可以看到10011就是設置為管理模式
* 設置控制寄存器的地址
* 關閉看門狗
* 屏蔽中斷
*設置時鐘
CPU上電幾毫秒后,晶振輸出穩定,FCLK=Fin(晶振頻率),CPU開始執行指令。但實際上,FCLK可以高于Fin,為了提高系統時鐘,需要用軟件來啟用PLL。這就需要設置CLKDIVN,MPLLCON,UPLLCON這3個寄存器。
CLKDIVN寄存器,CLKDIVN寄存器用于設置FCLK,HCLK,PCLK三者間的比例
設置CLKDIVN為5,就將HDIVN設置為二進制的10,由于CAMDIVN[9]沒有被改變過,取默認值0,因此HCLK = FCLK/4。
PDIVN被設置為1,因此PCLK= HCLK/2。因此分頻比FCLK:HCLK:PCLK = 1:4:8 。
FCLK提供給ARM920T的時鐘
HCLK 是提供給用于 ARM920T,存儲器控制器,中斷控制器,LCD 控制器,DMA 和 USB 主機模塊的 AHB總線的時鐘
PCLK 是提供給用于外設如WDT,IIS,I2C,PWM 定時器,MMC/SD 接口,ADC,UART,GPIO,RTC 和SPI的 APB 總線的時鐘
FCLK與Fin的關系如下面公式:
MPLLCON寄存器用于設置FCLK與Fin的倍數。MPLLCON的位[19:12]稱為MDIV,位[9:4]稱為PDIV,位[1:0]稱為SDIV。
MPLLCON與UPLLCON的值可以根據參考:
MPLLCON=(0x7f<<12) | (0x02<<4) | (0x01) = 0x7f021
UPLLCON=(0x38<<12) | (0x02<<4) | (0x02) = 0x38022
5、關閉 MMU、cache
代碼中的c0,c1,c7,c8都是ARM920T的協處理器CP15的寄存器。其中c7是cache控制寄存器,c8是TLB控制寄存器。325~327行代碼將0寫入c7、c8,使Cache,TLB內容無效。
第332~337行代碼關閉了MMU。這是通過修改CP15的c1寄存器來實現的,先看CP15的c1寄存器的格式(僅列出代碼中用到的位):
V : 表示異常向量表所在的位置,0:異常向量在0x00000000;1:異常向量在 0xFFFF0000
I : 0 :關閉ICaches;1 :開啟ICaches
R、S : 用來與頁表中的描述符一起確定內存的訪問權限
B : 0 :CPU為小字節序;1 : CPU為大字節序
C : 0:關閉DCaches;1:開啟DCaches
A : 0:數據訪問時不進行地址對齊檢查;1:數據訪問時進行地址對齊檢查
M : 0:關閉MMU;1:開啟MMU
332~337行代碼將c1的 M位置零,關閉了MMU。
6 、初始化 RAM 控制寄存器
其中的lowlevel_init就完成了內存初始化的工作,由于內存初始化是依賴于開發板的,
因此lowlevel_init的代碼一般放在board下面相應的目錄中。
對于mini2440,lowlevel_init在board/samsung/mini2440/lowlevel_init.S中定義如下:
7、初始化堆棧、復制U-Boot第二階段代碼到RAM
* 設置棧,跳轉到board_init_f
*?board_init_f
* 設置gd結構體
* 初始化函數
* board_early_init_f函數在board/samsung/smdk2410目錄下的smdk2410.c文件內
* timer_init函數在arch/arm/cpu/arm920t/s3c24x0目錄下的timer.c文件內
* env_init函數在common目錄下的env_flash.c文件內
* init_baudrate函數在arch/arm/lib目錄下的board.c文件內
* serial_init函數在drivers/serial目錄下的serial_s3c24x0.c文件內,在include/configs/smdk2410.h中CONFIG_S3C24X0_SERIAL
* console_init_f函數在common目錄下的console.c文件內
* display_banner函數在arch/arm/lib目錄下的board.c文件內
* dram_init函數在board/samsung/smdk2410目錄下的smdk2410.c文件內
env_init最后關聯到這個數組,用于設置環境變量
'\0'表示未進行設置
board_init_f 先是把RAM的地方給大家分好,設置各個模塊的地址,例如堆棧、第二段代碼的鏈接地址,
最后復制地位段代碼到RAM上去。
8、跳轉到第二階段執行
2、board_init_r:各種初始化
enable_caches();
board_init(); /* Setup chipselects 、初始化啟動參數的位置*/
set_cpu_clk_info();
serial_initialize();
nand_init(); /* go init the NAND */
env_relocate();/* initialize environment */
stdio_init(); /* get the devices list going. */
console_init_r(); /* fully init console as a device */
2、開始執行 main_loop():執行各種命令
main_loop()函數做的都是與具體平臺無關的工作,主要包括初始化啟動次數限制機制、設置軟件版本號、打印啟動信息、解析命令等。
參考資料:https://blog.csdn.net/winheroii58/article/details/6803327
bootcmd 、 bootargs這兩個環境變量比較重要,下面我們介紹這兩個環境變量
bootcmd
#define CONFIG_BOOTARGS "console=ttySAC0 root=/dev/mtdblock3"
#define CONFIG_BOOTCOMMAND "nand read 30000000 kernel;bootm 30000000"
參考資料:https://blog.csdn.net/g_salamander/article/details/8463854
https://blog.csdn.net/liangkaiming/article/details/5986680
* 一些小知識點
bootm
1.設置傳遞給內核的參數
2.啟動
代碼中執行獲取執行bootcmd
s = getenv ("bootcmd");//獲取環境變量
run_command_list(s, -1, 0);//執行環境變量
總結
以上是生活随笔為你收集整理的mini2440 u-boot linux 内核启动,u-boot.2012.10——mini2440(二、启动流程分析)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 内核维护,Linux 4.1
- 下一篇: linux下运行hadoop,Linux