日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

uboot流程——uboot启动流程

發布時間:2025/3/21 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 uboot流程——uboot启动流程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
[uboot] (第五章)uboot流程——uboot啟動流程
2016年11月07日 20:12:07閱讀數:2230

以下例子都以project X項目tiny210(s5pv210平臺,armv7架構)為例

[uboot] uboot流程系列:?
[project X] tiny210(s5pv210)上電啟動流程(BL0-BL2)?
[project X] tiny210(s5pv210)從存儲設備加載代碼到DDR?
[uboot] (第一章)uboot流程——概述?
[uboot] (第二章)uboot流程——uboot-spl編譯流程?
[uboot] (第三章)uboot流程——uboot-spl代碼流程?
[uboot] (第四章)uboot流程——uboot編譯流程?
[uboot] (番外篇)global_data介紹?
[uboot] (番外篇)uboot relocation介紹

建議先看《[project X] tiny210(s5pv210)上電啟動流程(BL0-BL2)》,根據例子了解一下上電之后的BL0\BL1\BL2階段,以及各個階段的運行位置,功能。?
建議可以和《[uboot] (番外篇)global_data介紹》和《[uboot] (番外篇)uboot relocation介紹》結合起來看。

=================================================================================

一、uboot說明

1、uboot要做的事情

CPU初始剛上電的狀態。需要小心的設置好很多狀態,包括cpu狀態、中斷狀態、MMU狀態等等。其次,就是要根據硬件資源進行板級的初始化,代碼重定向等等。最后,就是進入命令行狀態,等待處理命令。?
在armv7架構的uboot,主要需要做如下事情

  • arch級的初始化

    • 關閉中斷,設置svc模式
    • 禁用MMU、TLB
    • 關鍵寄存器的設置,包括時鐘、看門狗的寄存器
  • 板級的初始化

    • 堆棧環境的設置
    • 代碼重定向之前的板級初始化,包括串口、定時器、環境變量、I2C\SPI等等的初始化
    • 進行代碼重定向
    • 代碼重定向之后的板級初始化,包括板級代碼中定義的初始化操作、emmc、nand flash、網絡、中斷等等的初始化。
    • 進入命令行狀態,等待終端輸入命令以及對命令進行處理

上述工作,也就是uboot流程的核心。

2、疑問

  • 在前面的文章中雖然已經說明了,在spl的階段中已經對arch級進行了初始化了,為什么uboot里面還要對arch再初始化一遍??
    回答:spl對于啟動uboot來說并不是必須的,在某些情況下,上電之后uboot可能在ROM上或者flash上開始執行而并沒有使用spl。這些都是取決于平臺的啟動機制。因此uboot并不會考慮spl是否已經對arch進行了初始化操作,uboot會完整的做一遍初始化動作,以保證cpu處于所要求的狀態下。

  • 和spl在啟動過程的差異在哪里??
    回答:以tiny210而言,前期arch的初始化流程基本上是一致的,出現本質區別的是在board_init_f開始的。

    • spl的board_init_f是由board自己實現相應的功能,例如tiny210則是在board/samsung/tiny210/board.c中。其主要實現了復制uboot到ddr中,并且跳轉到uboot的對應位置上。一般spl在這里就可以完成自己的工作了。
    • uboot的board_init_f是在common下實現的,其主要實現uboot relocate前的板級初始化以及relocate的區域規劃,其還需要往下走其他初始化流程。

3、代碼入口

project-X/u-boot/arch/arm/cpu/u-boot.lds

ENTRY(_start)
  • 1

所以uboot-spl的代碼入口函數是_start?
對應于路徑project-X/u-boot/arch/arm/lib/vector.S的_start,后續就是從這個函數開始分析。

二、代碼整體流程

1、首先看一下主枝干的流程(包含了arch級的初始化)

在arch級初始化是和spl完全一致的?
_start———–>reset————–>關閉中斷?
………………………………|?
………………………………———->cpu_init_cp15———–>關閉MMU,TLB?
………………………………|?
………………………………———->cpu_init_crit————->lowlevel_init————->關鍵寄存器的配置和初始化?
………………………………|?
………………………………———->_main————–>進入板級初始化,具體看下面

2、板級初始化的流程

_main————–>board_init_f_alloc_reserve —————>堆棧、GD、early malloc空間的分配?
…………|?
…………————->board_init_f_init_reserve —————>堆棧、GD、early malloc空間的初始化?
…………|?
…………————->board_init_f —————>uboot relocate前的板級初始化以及relocate的區域規劃?
…………|?
…………————->relocate_code、relocate_vectors —————>進行uboot和異常中斷向量表的重定向?
…………|?
…………————->舊堆棧的清空?
…………|?
…………————->board_init_r —————>uboot relocate后的板級初始化?
…………|?
…………————->run_main_loop —————>進入命令行狀態,等待終端輸入命令以及對命令進行處理

三、arch級初始化代碼分析

1、_start

上述已經說明了_start是整個uboot的入口,其代碼如下:?
arch/arm/lib/vector.S

_start: #ifdef CONFIG_SYS_DV_NOR_BOOT_CFG.word CONFIG_SYS_DV_NOR_BOOT_CFG #endifb reset
  • 1
  • 2
  • 3
  • 4
  • 5

會跳轉到reset中。

2、reset

建議先參考[kernel 啟動流程] (第二章)第一階段之——設置SVC、關閉中斷,了解一下為什么要設置SVC、關閉中斷以及如何操作。

代碼如下:?
arch/arm/cpu/armv7/start.S

.globl reset.globl save_boot_params_retreset:/* 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, cpsrand r1, r0, #0x1f @ mask mode bitsteq r1, #0x1a @ test for HYP modebicne r0, r0, #0x1f @ clear all mode bitsorrne r0, r0, #0x13 @ set SVC modeorr r0, r0, #0xc0 @ disable FIQ and IRQmsr cpsr,r0 @@ 以上通過設置CPSR寄存器里設置CPU為SVC模式,禁止中斷 @@ 具體操作可以參考《[kernel 啟動流程] (第二章)第一階段之——設置SVC、關閉中斷》的分析/* the mask ROM code should have PLL and others stable */ #ifndef CONFIG_SKIP_LOWLEVEL_INITbl cpu_init_cp15 @@ 調用cpu_init_cp15,初始化協處理器CP15,從而禁用MMU和TLB。 @@ 后面會有一小節進行分析bl cpu_init_crit @@ 調用cpu_init_crit,進行一些關鍵的初始化動作,也就是平臺級和板級的初始化 @@ 后面會有一小節進行分析 #endifbl _main @@ 跳轉到主函數,也就是板級初始化函數 @@ 下一節中進行說明。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

3、cpu_init_cp15

建議先參考[kernel 啟動流程] (第六章)第一階段之——打開MMU兩篇文章的分析。?
cpu_init_cp15主要用于對cp15協處理器進行初始化,其主要目的就是關閉其MMU和TLB。?
代碼如下(去掉無關部分的代碼):?
arch/arm/cpu/armv7/start.S

ENTRY(cpu_init_cp15)/** Invalidate L1 I/D*/mov r0, #0 @ set up for MCRmcr p15, 0, r0, c8, c7, 0 @ invalidate TLBsmcr p15, 0, r0, c7, c5, 0 @ invalidate icachemcr p15, 0, r0, c7, c5, 6 @ invalidate BP arraymcr p15, 0, r0, c7, c10, 4 @ DSBmcr p15, 0, r0, c7, c5, 4 @ ISB @@ 這里只需要知道是對CP15處理器的部分寄存器清零即可。 @@ 將協處理器的c7\c8清零等等,各個寄存器的含義請參考《ARM的CP15協處理器的寄存器》/** disable MMU stuff and caches*/mrc p15, 0, r0, c1, c0, 0bic r0, r0, #0x00002000 @ clear bits 13 (--V-)bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)orr r0, r0, #0x00000002 @ set bit 1 (--A-) Alignorr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB #ifdef CONFIG_SYS_ICACHE_OFFbic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache #elseorr r0, r0, #0x00001000 @ set bit 12 (I) I-cache #endifmcr p15, 0, r0, c1, c0, 0 @@ 通過上述的文章的介紹,我們可以知道cp15的c1寄存器就是MMU控制器 @@ 上述對MMU的一些位進行清零和置位,達到關閉MMU和cache的目的,具體的話去看一下上述文章吧。ENDPROC(cpu_init_cp15)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

4、cpu_init_crit

cpu_init_crit,進行一些關鍵寄存器的初始化動。其代碼核心就是lowlevel_init,如下?
arch/arm/cpu/armv7/start.S

ENTRY(cpu_init_crit)/** Jump to board specific initialization...* The Mask ROM will have already initialized* basic memory. Go here to bump up clock rate and handle* wake up conditions.*/b lowlevel_init @ go setup pll,mux,memory ENDPROC(cpu_init_crit)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

所以說lowlevel_init就是這個函數的核心。?
lowlevel_init一般是由板級代碼自己實現的。但是對于某些平臺來說,也可以使用通用的lowlevel_init,其定義在arch/arm/cpu/lowlevel_init.S中?
以tiny210為例,在移植tiny210的過程中,就需要在board/samsung/tiny210下,也就是板級目錄下面創建lowlevel_init.S,在內部實現lowlevel_init。(其實只要實現了lowlevel_init了就好,沒必要說在哪里是實現,但是通常規范都是創建了lowlevel_init.S來專門實現lowlevel_init函數)。

在lowlevel_init中,我們要實現如下:

  • 檢查一些復位狀態
  • 關閉看門狗
  • 系統時鐘的初始化
  • 內存、DDR的初始化
  • 串口初始化(可選)
  • Nand flash的初始化

下面以tiny210的lowlevel_init為例(這里說明一下,當時移植tiny210的時候,是直接把kangear的這個lowlevel_init.S文件拿過來用的)?
這部分代碼和平臺相關性很強,簡單介紹一下即可?
board/samsung/tiny210/lowlevel_init.S

lowlevel_init:push {lr}/* check reset status */ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)ldr r1, [r0]bic r1, r1, #0xfff6ffffcmp r1, #0x10000beq wakeup_reset_precmp r1, #0x80000beq wakeup_reset_from_didle @@ 讀取復位狀態寄存器0xE010_a000的值,判斷復位狀態。/* IO Retention release */ldr r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)ldr r1, [r0]ldr r2, =IO_RET_RELorr r1, r1, r2str r1, [r0] @@ 讀取混合狀態寄存器E010_e000的值,對其中的某些位進行置位,復位后需要對某些wakeup位置1,具體我也沒搞懂。/* Disable Watchdog */ldr r0, =ELFIN_WATCHDOG_BASE /* 0xE2700000 */mov r1, #0str r1, [r0] @@ 關閉看門狗@@ 這里忽略掉一部分對外部SROM操作的代碼/* when we already run in ram, we don't need to relocate U-Boot.* and actually, memory controller must be configured before U-Boot* is running in ram.*/ldr r0, =0x00ffffffbic r1, pc, r0 /* r0 <- current base addr of code */ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */bic r2, r2, r0 /* r0 <- current base addr of code */cmp r1, r2 /* compare r0, r1 */beq 1f /* r0 == r1 then skip sdram init */ @@ 判斷是否已經在SDRAM上運行了,如果是的話,就跳過以下兩個對ddr初始化的步驟 @@ 判斷方法如下: @@ 1、獲取當前pc指針的地址,屏蔽其低24bit,存放與r1中 @@ 2、獲取_TEXT_BASE(CONFIG_SYS_TEXT_BASE)地址,也就是uboot代碼段的鏈接地址,后續在uboot篇的時候會說明,并屏蔽其低24bit @@ 3、如果相等的話,就跳過DDR初始化的部分/* init system clock */bl system_clock_init @@ 初始化系統時鐘,后續有時間再研究一下具體怎么配置的/* Memory initialize */bl mem_ctrl_asm_init @@ 重點注意:在這里初始化DDR的!!!后續會寫一篇文章說明一下s5pv210平臺如何初始化DDR. @@ 其實,在tiny210的項目中,已經在spl里面對ddr初始化了一遍,這里還是又重新初始化了一遍,從實際測試結果來看,并不影響正常的使用。1:/* for UART */bl uart_asm_init @@ 串口初始化,到這里串口會打印出一個'O'字符,后續通過寫字符到UTXH_OFFSET寄存器中,就可以在串口上輸出相應的字符。bl tzpc_init#if defined(CONFIG_NAND)/* simple init for NAND */bl nand_asm_init @@ 簡單地初始化一下NAND flash,有可能BL2的鏡像是在nand flash上面的。 #endif/* Print 'K' */ldr r0, =ELFIN_UART_CONSOLE_BASEldr r1, =0x4b4b4b4bstr r1, [r0, #UTXH_OFFSET] @@ 再串口上打印‘K’字符,表示lowlevel_init已經完成pop {pc} @@ 彈出PC指針,即返回。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76

當串口中打印出‘OK’的字符的時候,說明lowlevel_init已經執行完成。

三、板級初始化代碼分析

1、_main

板級初始化代碼的入口就是_main。從這里開始分析。?
建議可以和《[uboot] (番外篇)global_data介紹》和《[uboot] (番外篇)uboot relocation介紹》結合起來看。?
代碼如下,去除無關代碼部分?
arch/arm/lib/crt0.S

ENTRY(_main)/** Set up initial C runtime environment and call board_init_f(0).*/ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)bic sp, sp, #7 /* 8-byte alignment for ABI compliance */mov r0, spbl board_init_f_alloc_reservemov sp, r0/* set up gd here, outside any C code */mov r9, r0bl board_init_f_init_reserve @@ 以上是堆棧、GD、early malloc空間的分配,具體參考《[uboot] (番外篇)global_data介紹》mov r0, #0bl board_init_f @@ uboot relocate前的板級初始化以及relocate的區域規劃,后續小節繼續說明 @@ 其中relocate區域規劃也可以參考一下《[uboot] (番外篇)uboot relocation介紹》/** Set up intermediate environment (new sp and gd) and call* relocate_code(addr_moni). Trick here is that we'll return* 'here' but relocated.*/ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ldr r9, [r9, #GD_BD] /* r9 = gd->bd */sub r9, r9, #GD_SIZE /* new GD is below bd */adr lr, hereldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */add lr, lr, r0ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */b relocate_code here: /** now relocate vectors*/bl relocate_vectors @@ GD、uboot、異常中斷向量表的relocate,可以參考《[uboot] (番外篇)uboot relocation介紹》,這里不詳細說明/* Set up final (full) environment */bl c_runtime_cpu_setup /* we still call old routine here */ @@ 通過操作協處理器的c7寄存器來關閉Icacheldr r0, =__bss_start /* this is auto-relocated! */ldr r3, =__bss_end /* this is auto-relocated! */mov r1, #0x00000000 /* prepare zero to clear BSS */subs r2, r3, r0 /* r2 = memset len */bl memset @@ 因為堆棧段已經被relocate,所以這里需要清空原來的堆棧段的內容bl coloured_LED_initbl red_led_on @@ LED燈的初始化,可以不實現,想要實現的話,可以在board里重新實現一個函數定義。/* call board_init_r(gd_t *id, ulong dest_addr) */mov r0, r9 /* gd_t */ldr r1, [r9, #GD_RELOCADDR] /* dest_addr *//* call board_init_r */ldr pc, =board_init_r /* this is auto-relocated! *//* we should not return here. */ @@ uboot relocate后的板級初始化,注意,uboot必須在這里就完成工作,或者在里面實現死循環,不應該返回。 ENDPROC(_main)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

通過上述,有兩個很重要的初始化函數,board_init_f和board_init_r,后續繼續說明。

2、board_init_f

代碼如下:?
common/board_f.c

void board_init_f(ulong boot_flags) {gd->flags = boot_flags;gd->have_console = 0; // 設置global_data里面的一些標志位if (initcall_run_list(init_sequence_f))hang(); // 調用initcall_run_list依次執行init_sequence_f函數數組里面的函數,initcall_run_list這里不深究 // 一旦init_sequence_f的函數出錯,會導致initcall_run_list返回不為0,而從卡掉 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

打開DEBUG宏之后,可以通過log觀察哪些init函數被調用,如下log:

uboot log中有如下log: initcall: 23e005a4 根據u-boot.map可以發現對應.text.print_cpuinfo0x23e005a4 0x8 arch/arm/cpu/armv7/built-in.o0x23e005a4 print_cpuinfo 也就是說print_cpuinfo被initcall調用了。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

所以uboot relocate之前的板級初始化的核心就是init_sequence_f中定義的函數了。?
如下,這里只做簡單的說明,需要的時候再具體分析:

static init_fnc_t init_sequence_f[] = {setup_mon_len, // 計算整個鏡像的長度gd->mon_leninitf_malloc, // early malloc的內存池的設定initf_console_record, // console的log的緩存arch_cpu_init, /* basic arch cpu dependent setup */ // cpu的一些特殊的初始化initf_dm,arch_cpu_init_dm,mark_bootstage, /* need timer, go after init dm *//* TODO: can any of this go into arch_cpu_init()? */env_init, /* initialize environment */ // 環境變量的初始化,后續會專門研究一下關于環境變量的內容init_baud_rate, /* initialze baudrate settings */ // 波特率的初始化serial_init, /* serial communications setup */ // 串口的初始化console_init_f, /* stage 1 init of console */ // console的初始化print_cpuinfo, /* display cpu info (and speed) */ // 打印CPU的信息init_func_i2c,init_func_spi, // i2c和spi的初始化dram_init, /* configure available RAM banks */ // ddr的初始化,最重要的是ddr ram size的設置!!!!gd->ram_size // 如果說uboot是在ROM、flash中運行的話,那么這里就必須要對DDR進行初始化 //========================================setup_dest_addr,reserve_round_4k,reserve_trace,setup_machine,reserve_global_data,reserve_fdt,reserve_arch,reserve_stacks, // ==以上部分是對relocate區域的規劃,具體參考《[uboot] (番外篇)uboot relocation介紹》setup_dram_config,show_dram_config,display_new_sp,reloc_fdt,setup_reloc, // relocation之后gd一些成員的設置NULL, };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

注意,必須保證上述的函數都正確地返回0值,否則會導致hang。

3、board_init_r

代碼如下:?
common/board_r.c

void board_init_r(gd_t *new_gd, ulong dest_addr) {if (initcall_run_list(init_sequence_r))hang(); // 調用initcall_run_list依次執行init_sequence_r函數數組里面的函數,initcall_run_list這里不深究 // 一旦init_sequence_r的函數出錯,會導致initcall_run_list返回不為0,而從卡掉/* NOTREACHED - run_main_loop() does not return */hang(); // uboot要求在這個函數里面終止一切工作,或者進入死循環,一旦試圖返回,則直接hang。 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

所以uboot relocate之前的板級初始化的核心就是init_sequence_r中定義的函數了。?
如下,這里只做簡單的說明,需要的時候再具體分析:?
common/board_r.c

init_fnc_t init_sequence_r[] = {initr_trace, // trace相關的初始化initr_reloc, // gd中一些關于relocate的標識的設置initr_reloc_global_data, // relocate之后,gd中一些的成員的重新設置initr_malloc, // malloc內存池的設置initr_console_record,bootstage_relocate,initr_bootstage, #if defined(CONFIG_ARM) || defined(CONFIG_NDS32)board_init, /* Setup chipselects */ // 板級自己需要的特殊的初始化函數,如board/samsung/tiny210/board.c中定義了board_init這個函數 #endifstdio_init_tables,initr_serial, // 串口初始化initr_announce, // 打印uboot運行位置的loginitr_logbuffer, // logbuffer的初始化power_init_board, #ifdef CONFIG_CMD_NANDinitr_nand, // 如果使用nand flash,那么這里需要對nand進行初始化 #endif #ifdef CONFIG_GENERIC_MMCinitr_mmc, // 如果使用emmc,那么這里需要對nand進行初始化 #endifinitr_env, // 初始化環境變量initr_secondary_cpu,stdio_add_devices,initr_jumptable,console_init_r, /* fully init console as a device */interrupt_init, // 初始化中斷 #if defined(CONFIG_ARM) || defined(CONFIG_AVR32)initr_enable_interrupts, // 使能中斷 #endifrun_main_loop, // 進入一個死循環,在死循環里面處理終端命令。 };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

最終,uboot運行到了run_main_loop,并且在run_main_loop進入命令行狀態,等待終端輸入命令以及對命令進行處理。?
到此,uboot流程也就完成了,后續會專門說明uboot的run_main_loop是怎么運行的。

總結

以上是生活随笔為你收集整理的uboot流程——uboot启动流程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。