從0移植uboot (二) _啟動流程分析

来源:http://www.cnblogs.com/xiaojiang1025/archive/2017/02/23/6435839.html
-Advertisement-
Play Games

經過了上一篇的配置,我們已經執行make就可以編譯出一個uboot.bin,但這還不夠,首先,此時的uboot並不符合三星晶元對bootloader的格式要求,其次,此時的uboot.bin也沒有結合我們的開發板進行配置,還無法使用。而要進行這樣的個性化配置,前提條件就是對uboot開機流程和編譯系 ...


經過了上一篇的配置,我們已經執行make就可以編譯出一個uboot.bin,但這還不夠,首先,此時的uboot並不符合三星晶元對bootloader的格式要求,其次,此時的uboot.bin也沒有結合我們的開發板進行配置,還無法使用。而要進行這樣的個性化配置,前提條件就是對uboot開機流程和編譯系統有所瞭解,本文主要討論前者。uboot是一個兩階段bootloader,第一階段主要做硬體直接相關的初始化,使用彙編編寫;第二階段主要為操作系統的運行準備環境,主要用C編寫,這裡以ARM平臺為例分析其啟動流程。下麵是啟動過程中主要涉及的文件

arch/arm/cpu/armv7/start.S
board/samsung/myboard/lowlevel_init.S
arch/arm/lib/crt0.S
arch/arm/lib/board.c
arch/samsung/myboard/myboard.c

第一階段

第一階段的主要文件和任務如下

arch/arm/cpu/armv7/start.S
           1. 設置CPU為SVC模式
           2. 關閉中斷,MMU,Cache
board/samsung/origen/lowlevel_init.S
           3. 關閉看門狗
           4. 初始化記憶體,串口
           5. 設置棧
           6. 代碼自搬移
           7. 清BSS
           8. 跳轉到C入口????

start.S

 39 .globl _start
 40 _start: b       reset
 41         ldr     pc, _undefined_instruction
 42         ldr     pc, _software_interrupt
 43         ldr     pc, _prefetch_abort
 44         ldr     pc, _data_abort
 45         ldr     pc, _not_used
 46         ldr     pc, _irq
 47         ldr     pc, _fiq

--40--> 異常向量表設置

126 reset:
127         bl      save_boot_params
131         mrs     r0, cpsr
132         bic     r0, r0, #0x1f
133         orr     r0, r0, #0xd3
134         msr     cpsr,r0

--126-->設置CPU為SVC模式

下麵這三行代碼非常重要,是整個uboot啟動過程的交叉點

154         bl      cpu_init_cp15
155         bl      cpu_init_crit
158         bl      _main

--154-->跳轉執行cpu_init_cp15,即初始化CP15協處理器
--155-->跳轉執行cpu_init_crit,
--158-->跳轉執行_main,即第二階段

287 ENTRY(cpu_init_cp15)
291         mov     r0, #0                  @ set up for MCR
292         mcr     p15, 0, r0, c8, c7, 0   @ invalidate TLBs
293         mcr     p15, 0, r0, c7, c5, 0   @ invalidate icache
294         mcr     p15, 0, r0, c7, c5, 6   @ invalidate BP array
295         mcr     p15, 0, r0, c7, c10, 4  @ DSB
296         mcr     p15, 0, r0, c7, c5, 4   @ ISB
297 
301         mrc     p15, 0, r0, c1, c0, 0
302         bic     r0, r0, #0x00002000     @ clear bits 13 (--V-)
303         bic     r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
304         orr     r0, r0, #0x00000002     @ set bit 1 (--A-) Align
305         orr     r0, r0, #0x00000800     @ set bit 11 (Z---) BTB
307         bic     r0, r0, #0x00001000     @ clear bit 12 (I) I-cache
311         mcr     p15, 0, r0, c1, c0, 0
312         mov     pc, lr                  @ back to my caller
313 ENDPROC(cpu_init_cp15)

--291-->關閉Cache
--301-->關閉MMU

324 ENTRY(cpu_init_crit)
331         b       lowlevel_init           @ go setup pll,mux,memory
332 ENDPROC(cpu_init_crit)

--331-->跳轉到lowlevel_init,位於board/samsung/origen/lowlevel_init.S,進行板級相關的設置。

lowlevel_init.S

這是位於目錄的初始化文件,主要完成特定開發板的初始化工作,包括時鐘、記憶體和串口等。

 82         bl system_clock_init
 85         bl mem_ctrl_asm_init
 87 1:
 88         /* for UART */
 89         bl uart_asm_init
 90         bl tzpc_init
 91         pop     {pc}
114 system_clock_init:
329 uart_asm_init:
357 tzpc_init:

--82-->初始化系統時鐘,即跳轉到114行
--85-->初始化系統記憶體
--89-->初始化UART串口,即跳轉到329行
--90-->初始化TrustZoneProtectorController,即跳轉到357行

執行完lowlevel_init.S,依據上面那三行代碼,執行流程就該回到start.S執行156行跳轉到_main,開始執行第二階段。

第二階段

從start.S跳轉到_main ,標緻著uboot啟動過程的第二階段的開始。在第二階段,核心文件是crt0.S,但我們最關心的是其中回調板級C程式的入口位置。第二階段的流程如下:

arch/arm/lib/crt0.S
           1. 初始化C運行環境,調用board_init_f()
arch/arm/lib/board.c
           1. board_init_f對全局信息GD結構體進行填充
arch/arm/lib/crt0.S
           1. 代碼重定位
           2. 代碼自搬移
           3. 執行超迴圈
arch/arm/lib/board.c
           1. board_init_r()是進入定製板目錄的入口

crt0.S

進入第二階段是首要任務就是準備C語言運行的環境:

 96 _main:
102 #if defined(CONFIG_NAND_SPL)
103         /* deprecated, use instead CONFIG_SPL_BUILD */
104         ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
105 #elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
106         ldr     sp, =(CONFIG_SPL_STACK)
107 #else
108         ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
109 #endif
110         bic     sp, sp, #7      /* 8-byte alignment for ABI compliance */
111         sub     sp, #GD_SIZE    /* allocate one GD above SP */
112         bic     sp, sp, #7      /* 8-byte alignment for ABI compliance */
113         mov     r8, sp          /* GD is above SP */
114         mov     r0, #0
115         bl      board_init_f

_main
--104-->初始化SP,為C語言做準備
--110-->保存128B放GD結構體來存放全局信息,
--111-->GD的地址放在r8中,
--115-->跳轉到board_init_f(),這個整個初始化過程中第一次執行的C代碼

board.c

下麵這個函數就是uboot初始化過程中執行的第一個C函數,可以看作這個文件的入口函數。函數比較長,我就不逐句分析了,這個函數主要的作用就是執行一些高等級的初始化。其中最重要的就是準備全局信息GD結構體

209 typedef int (init_fnc_t) (void);
243 init_fnc_t *init_sequence[] = {
244         arch_cpu_init,          /* basic arch cpu dependent setup */
245         mark_bootstage,
246 #ifdef CONFIG_OF_CONTROL
247         fdtdec_check_fdt,
            ...
277 void board_init_f(ulong bootflag)
278 {
        ...
291         gd->mon_len = _bss_end_ofs;
292 #ifdef CONFIG_OF_EMBED
293         /* Get a pointer to the FDT */
294         gd->fdt_blob = _binary_dt_dtb_start;
295 #elif defined CONFIG_OF_SEPARATE
296         /* FDT is at end of image */
297         gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);
298 #endif
299         /* Allow the early environment to override the fdt address */
300         gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
301                                                 (uintptr_t)gd->fdt_blob);
302 
303         for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
304                 if ((*init_fnc_ptr)() != 0) {
305                         hang ();
306                 }
307         }
        ...

board_init_f()
--243--> 全局的函數指針數組,每個指針都是int (*ptr)(void)型的。
--291-->mon_len 通過鏈接腳本可以知道存放的是 uboot 代碼大小;
--294-->fdt_blob 存放設備數地址;
--303--遍歷函數指針數組init_sequence中的每一個成員,就是將數組中的每一個初始化函數都執行一次,這種寫法可以借鑒

crt0.S

函數board_init_f()返回後,繼續執行crt0.S中115行之後的部分,主要的工作是執行代碼自搬移,代碼重定位等工作,執行完這些之後,我們我們找到了最感興趣的下麵這幾句

163         /* call board_init_r(gd_t *id, ulong dest_addr) */
164         mov     r0, r8                  /* gd_t */
165         ldr     r1, [r8, #GD_RELOCADDR] /* dest_addr */
166         /* call board_init_r */
167         ldr     pc, =board_init_r       /* this is auto-relocated! */

--167-->跳轉到board_init_r函數執行,這次跳出去這個文件的語句就執行完畢了,不會再回來了

board.c

這也是最後一次跳轉到這個文件了,執行額函數如下

519 void board_init_r(gd_t *id, ulong dest_addr)
520 {
521         ulong malloc_start;
522 #if !defined(CONFIG_SYS_NO_FLASH)
523         ulong flash_size;
524 #endif
525 
526         gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */
527         bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
528 
529         monitor_flash_len = _end_ofs;
530 
531         /* Enable caches */
532         enable_caches();
533 
534         debug("monitor flash len: %08lX\n", monitor_flash_len);
535         board_init();   /* Setup chipselects */
        ...
650          /* set up exceptions */
651         interrupt_init();
652         /* enable exceptions */
653         enable_interrupts(); 
667         eth_initialize(gd->bd);
        ...
701         /* main_loop() can return to retry autoboot, if so just run it again. */
702         for (;;) {
703                 main_loop();
704         }
705 

board_init_r()
--532-->很多緊急工作都做完了,可以打開cache了
--535-->關鍵!!!這個就是我們苦苦尋找的板級定製文件的xxx.c的入口函數!!!
--651-->中斷初始化
--653-->使能中斷
--667-->網卡初始化,函數的實現在net/eth.c,會回調板級xxx.c中的board_eth_init()
--703-->執行超迴圈,主要功能是處理環境變數,解析命令,也就是uboot中和我們交互的命令的解析工作都在這裡執行!!!

main_loop()與啟動內核

main_loop()的實現在common/main.c,它的主要功能就是迴圈檢測輸入的命令並執行,其中一個環境變數bootdelay(自啟動)的設置決定了是否啟動內核,如果延時大於等於零,並且沒有在延時過程中接收到按鍵,則引導內核。ootloader 要想啟動內核,可以直接跳到內核的第一個指令處,即內核的起始地址,這樣便可以完成內核的啟動工作了。但是要想啟動內核還需要滿足下麵的一些條件,這些條件在Linux內核文檔"/Documentation/kernel-parameters.txt"中有說明,
1、cpu 寄存器設置

* R0 = 0
* R1 = 機器類型 id
* R2 = 啟動參數在記憶體中的起始地址

2、cpu 模式

* 禁止所有中斷
* 必須為 SVC(超級用戶)模式

3、Cache、MMU

* 關閉 MMU
* 指令 Cache 可以開啟或者關閉
* 數據 Cache 必須關閉

4、設備

* DMA 設備應當停止工作

5、PC 為內核的起始地址

關於uboot的啟動分析,本文只是冰山一角的一丟丟,不過希望通過我的這一堆廢話下來,能幫助你對uboot的啟動流程有一個整體的認識,當然,如果文中有錯誤,歡迎批評指正^-^



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 編譯環境:RVMDK CPU :STM32F103VC 錯誤:.\obj\movSERVO.sct(7): error: L6235E: More than one section matches selector - cannot all be FIRST/LAST. 原因:項目中同時包含以下啟動 ...
  • 讀取excel文件:libxls-1.4.0.zip下載地址:http://sourceforge.net/projects/libxls/安裝方法: ./configure make make install sudo cp -r -v /usr/local/libxls/include/libx ...
  • 裝系統 Deepin是一個國產的linux發行版,因為其極高的顏值和不需要折騰的操作吸引了我。正好厭倦了windows 10,又趕上大四的畢業設計,就拿來玩玩了。 首先,Deepin系統的安裝是非常傻瓜式的,參照官網上的 "教程" 幾步就可裝好。我採用的是體驗安裝,重啟之後即可選擇進入Deepin系 ...
  • 之前要在linux下麵安裝nginx,弄了半天,終於搞定了,下麵給大家詳細一下安裝流程及安裝報錯解決方案: 安裝共分為5步搞定: 1.進入src目錄(下載存放目錄) cd /usr/local/src/ 2.wget下載:http://nginx.org/en/download.html(nginx ...
  • Windows 10 中包含了一個 WSL(Windows Subsystem for Linux)子系統,我們可以在其中運行未經修改過的原生 Linux ELF 可執行文件。利用它我們可以做很多事情,對開發人員和普通用戶都是如此。當然對開發人員的吸引力更大一些,因為這意味著在一些情況,不再需要使用... ...
  • 本文首發於:http://www.fengzheng.pub/archives/238.html 背景說明 伺服器為阿裡雲 ECS,操作系統為 CentOS 6.5。 部署配置說明 第一步,安裝nginx 之所以要先安裝 nginx,是因為下麵配置功能變數名稱解析的時候可以直接在瀏覽器看到效果,當然了,先配 ...
  • 序言 提到LVS,就從章文嵩博士開始吧,反正也不知道如何下筆來寫這一篇。章大博士,讀博時候創建這個lvs軟體項目,但是他提倡開源精神,在用戶的建議和反饋中,這個花了他兩周時間開發的開源軟體不斷得到改建和豐富。到1999年,該款軟體已在負載均衡領域中比較出名,章文嵩仍舊堅持開源,將源代碼分享給所有人。 ...
  • 前兩篇介紹了uboot 2013.01的配置原理以及大體的運行流程,本文將討論如何對uboot源碼進行配置,將一個可用的uboot燒錄到SD卡中。 定製自己的core board 市面上能買到的開發板的核心板基本都是基於官方參考板製作的,所以雖然標準操作是"定製"自己的core board,但鑒於我 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...