天天看點

【Nanopi T2】 3.uboot 2016 啟動流程源碼解析

目錄

        • s5p4418 uboot sd卡方式啟動流程
        • 鏡像檔案記憶體布局
        • uboot啟動(BL1)
          • start.S
          • lowlevel_init.S
          • _main
          • board_init_f
          • board_init_r
          • main_loop

s5p4418 uboot sd卡方式啟動流程

4418上電後會先加載運作片内啟動代碼(BL0),大緻工作是判斷CPU的啟動方式,初始化啟動裝置。拷貝uboot前16k(BL1)到内部RAM,對代碼做校驗,然後開始運作BL1。4418的BL1也是廠商直接提供的,屬于閉源代碼。4418的BL1大緻由2nboot和2nboot配置組成,2nboot的配置可以在友善之臂的uboot源碼中找到(tools/nexell/nish/nanop2.txt)。2nboot大緻工作是初始化中斷向量,關閉看門口,初始化ddr記憶體,拷貝整個uboot到ddr,然後跳轉到ddr中運作uboot的後半部分(BL2)。

鏡像檔案記憶體布局

友善支之臂不同版本的2nboot代碼量大小不一樣,具體見我前兩篇部落格中的介紹

uboot 2010:https://blog.csdn.net/qq_16054639/article/details/105770048

uboot 2016:https://blog.csdn.net/qq_16054639/article/details/105829051

uboot啟動(BL1)

uboot中的CONFIG_SPL是沒有啟用的,整個uboot的前半部分啟動代碼是閉源的,是以手裡的源碼都是從後半部分開始的。

檢視源碼檔案/arch/arm/armv7/s5p4418/u-boot.lds

.text :
 {
  *(.__image_copy_start) //拷貝開始的位置
  *(.vectors)            //存放中斷向量表
  CPUDIR/start.o (.text*)//代碼開始
  *(.text*)
 }
           

發現開始代碼段為vectors,這個vectors的來源是在配置檔案tools/nexell/nish/nanop2.txt中

E59FF018 // 0x000 : MOV PC, ResetV
E59FF018 // 0x004 : MOV PC, UndefV
E59FF018 // 0x008 : MOV PC, SWIV
E59FF018 // 0x00C : MOV PC, PAbortV
E59FF018 // 0x010 : MOV PC, DAbortV
E59FF018 // 0x014 : MOV PC, NotUsed
E59FF018 // 0x018 : MOV PC, IRQV
E59FF018 // 0x01C : MOV PC, FIQV

FFFF0200 // 0x020 : SRAMBASE + Header
FFFF0204 // 0x024 : SRAMBASE + Header
FFFF0208 // 0x028 : SRAMBASE + Header
FFFF020C // 0x02C : SRAMBASE + Header
FFFF0210 // 0x030 : SRAMBASE + Header
FFFF0214 // 0x034 : SRAMBASE + Header
FFFF0218 // 0x038 : SRAMBASE + Header
FFFF021C // 0x03C : SRAMBASE + Header
           
start.S

之後接着開始代碼/arch/arm/armv7/start.S

.globl reset
 .globl save_boot_params_ret
 reset:
 /* Allow the board to save important registers */
 b save_boot_params
save_boot_params_ret:
 /*
  * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
  * except if in HYP mode already
  */
 mrs r0, cpsr
 and r1, r0, #0x1f  @ mask mode bits
 teq r1, #0x1a  @ test for HYP mode
 bicne r0, r0, #0x1f  @ clear all mode bits
 orrne r0, r0, #0x13  @ set SVC mode
 orr r0, r0, #0xc0  @ disable FIQ and IRQ
 msr cpsr,r0
 /*
 * Setup vector:
 * (OMAP4 spl TEXT_BASE is not 32 byte aligned.
 * Continue to use ROM code vector only in OMAP4 spl)
 */
 #if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD)) //沒配置這裡不會執行
	 /* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
	 mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTLR Register
	 bic r0, #CR_V  @ V = 0
	 mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTLR Register
	 /* Set vector address in CP15 VBAR register */
	 ldr r0, =_start
	 mcr p15, 0, r0, c12, c0, 0 @Set VBAR
#endif
 /* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
	 bl cpu_init_cp15
	 bl cpu_init_crit
#endif
 	bl _main
           

執行流程:

  1. save_boot_params(沒做什麼)
  2. save_boot_params_ret(禁用中斷,設定運作模式)
  3. cpu_init_cp15(初始化cp15寄存器,主要設定cache,mmu,TLBs位址映射表,不深入分析)
  4. cpu_init_crit
  5. ->lowlevel_init(其實也沒做什麼,祥見下文)
  6. _main(開始後半部分初始化)
lowlevel_init.S

/arch/arm/armv7/lowlevel_init.S

【Nanopi T2】 3.uboot 2016 啟動流程源碼解析

執行流程:

  1. 初始化C語言棧
  2. 初始化global data全局結構體起始位址
  3. s_init(什麼也沒做)
_main

/arch/arm/lib/crt0.S

【Nanopi T2】 3.uboot 2016 啟動流程源碼解析

執行流程:

  1. 設定c語言運作環境(設定sp指針)
  2. board_init_f_mem(初始化記憶體配置,起始就是向global data寫入棧頂位址,malloc起始位址)
  3. board_init_f(這個很重要,初始化了很多功能)
  4. 繼續填充global data結構體參數(不深入分析)
  5. coloured_LED_init(初始化LED)
  6. red_led_on(點亮LED)
  7. board_init_r(很重要初始化了非常多東西)
board_init_f

/common/board_f.c

【Nanopi T2】 3.uboot 2016 啟動流程源碼解析

board_init_f這個函數主要周遊執行了init_sequence_f這個數組中的函數

挑出幾個主要關鍵函數解釋:

  1. fdtdec_setup(初始化裝置樹描述符)
  2. arch_cpu_init(初始化cpu,時鐘)
  3. initf_dm(初始化dm驅動架構,掃描裝置樹,初始化裝置節點)
  4. timer_init(初始化時鐘線)
  5. env_init(讀取環境變量)
  6. show_board_info(列印闆子資訊)
board_init_r

/common/board_c.c

board_init_r函數跟board_init_f函數類似,也是周遊執行一個數組中的所有函數

【Nanopi T2】 3.uboot 2016 啟動流程源碼解析

挑出幾個主要關鍵函數解釋:

  1. initr_dm(初始化裝置樹描述符)
  2. board_init(闆級初始化)
  3. initr_net(初始化網絡驅動)
  4. run_main_loop(進入主循環)
main_loop
【Nanopi T2】 3.uboot 2016 啟動流程源碼解析

執行流程:

  1. run_preboot_environment_command(執行預設環境變量指令,也就是啟動指令preboot)

    preboot定義在include/env_default.h

#ifdef CONFIG_PREBOOT
 "preboot=" CONFIG_PREBOOT   "\0" //CONFIG_PREBOOT這個宏沒有定義,是以這裡等于什麼也沒做
#endif
           
  1. bootdelay_process(等待使用者按下按鍵,按下按鍵将進入指令行模式,如果沒有按下将傳回系統啟動指令bootcmd)
  2. autoboot_command(如果上一步有指令,執行上一步傳回的指令)
  3. cli_loop(進入指令行模式)

至此整個uboot的主要啟動流程就梳理結束了

繼續閱讀