九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
ARM上電后都干了哪些事uboot啟動(dòng)代碼詳解(uboot的入口是start鏈接地址0x00000000)

 (uboot的入口是start鏈接地址0x00000000)


https://m.toutiao.com/is/RSrVyEH/?=ARM上電后都干了哪些事 



關(guān)于本文配套的視頻《uboot啟動(dòng)詳解-1》《uboot啟動(dòng)詳解-2

前言

我們?cè)谇懊娴腶rm系列課程,已經(jīng)講解了arm的架構(gòu)、匯編指令、異常、常用外設(shè)的控制器驅(qū)動(dòng),那么我們已經(jīng)具備開發(fā)arm系列產(chǎn)品的基本技能。

本篇給大家介紹一款比較常用的bootloader:uboot,通過uboot的介紹以及源代碼的詳細(xì)分析,讓大家把之前所有ARM相關(guān)的知識(shí)點(diǎn)融會(huì)貫通起來。

一、uboot

1. 概念

U-Boot 是一個(gè)主要用于嵌入式系統(tǒng)的引導(dǎo)加載程序,可以支持多種不同的計(jì)算機(jī)系統(tǒng)結(jié)構(gòu),包括PPC、ARM、AVR32、MIPS、x86、68k、Nios與MicroBlaze。這也是一套在GNU通用公共許可證之下發(fā)布的自由軟件。

U-Boot不僅僅支持嵌入式Linux系統(tǒng)的引導(dǎo),它還支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS, android嵌入式操作系統(tǒng)。其目前要支持的目標(biāo)操作系統(tǒng)是OpenBSD, NetBSD, FreeBSD,4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, LynxOS, pSOS, QNX, RTEMS, ARTOS, android。

2. uboot基本功能

U-Boot可支持的主要功能列表:

  • 系統(tǒng)引導(dǎo)支持NFS掛載、RAMDISK(壓縮或非壓縮)形式的根文件系統(tǒng);支持NFS掛載、從FLASH中引導(dǎo)壓縮或非壓縮系統(tǒng)內(nèi)核;
  • 基本輔助功能強(qiáng)大的操作系統(tǒng)接口功能;可靈活設(shè)置、傳遞多個(gè)關(guān)鍵參數(shù)給操作系統(tǒng),適合系統(tǒng)在不同開發(fā)階段的調(diào)試要求與產(chǎn)品發(fā)布,尤以Linux支持最為強(qiáng)勁;支持目標(biāo)板環(huán)境參數(shù)多種存儲(chǔ)方式,如FLASH、NVRAM、EEPROM;
  • CRC32校驗(yàn)可校驗(yàn)FLASH中內(nèi)核、RAMDISK鏡像文件是否完好;
  • 設(shè)備驅(qū)動(dòng)串口、SDRAM、FLASH、以太網(wǎng)、LCD、NVRAM、EEPROM、鍵盤、USB、PCMCIA、PCI、RTC等驅(qū)動(dòng)支持;
  • 上電自檢功能SDRAM、FLASH大小自動(dòng)檢測(cè);SDRAM故障檢測(cè);CPU型號(hào)。

3. 常用命令

uboot命令比較多,下面只列舉網(wǎng)絡(luò)啟動(dòng)要用到的命令:

命令 含義 bootdelay 執(zhí)行自動(dòng)啟動(dòng)(bootcmd中的命令)的等候秒數(shù) baudrate 串口控制臺(tái)的波特率 netmask 以太網(wǎng)的網(wǎng)絡(luò)掩碼 ethaddr 以太網(wǎng)的MAC地址 bootfile 默認(rèn)的下載文件名 printenv 打印Uboot環(huán)境變量 setenv 設(shè)置Uboot環(huán)境變量 ipaddr 本地的IP地址 serverip TFTP服務(wù)器端的IP地址 gateway 以太網(wǎng)的網(wǎng)關(guān) bootcmd 自動(dòng)啟動(dòng)時(shí)執(zhí)行命令 bootargs 傳遞給Linux內(nèi)核的啟動(dòng)參數(shù) bootm 引導(dǎo)啟動(dòng)存儲(chǔ)在內(nèi)存中的程序映像。這些內(nèi)存包括RAM和可以永久保存的Flash。

4. 配置參數(shù)舉例

以下以網(wǎng)絡(luò)下載內(nèi)核、網(wǎng)絡(luò)掛載nfs為例。

1)ubuntu環(huán)境

ubuntu ip:192.168.6.186

nfs配置:

配置文件如下:

/etc/exports

配置信息如下:

nfs

2)開發(fā)板設(shè)置

開發(fā)板ip:192.168.6.187

配置命令:

setenv ipaddr 192.168.6.187      ;板子的ipsetenv serverip 192.168.6.186    ;虛擬機(jī)的ipsetenv gatewayip 192.168.1.1     ;網(wǎng)關(guān)saveenv                          ;保存配置
  • 加載內(nèi)核和設(shè)備樹
setenv bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-fs4412.dtb\;bootm 41000000 - 42000000

bootcmd:uboot2啟動(dòng)之后,首先先執(zhí)行找到這個(gè)參數(shù),執(zhí)行后面的命令。 從tftp服務(wù)器下載內(nèi)核鏡像uImage到地址41000000,設(shè)備樹文件exynos4412-fs4412.dtb到42000000,并通過命令bootm加載啟動(dòng)內(nèi)核。

  • 掛載nfs
setenv bootargs root=/dev/nfs nfsroot=192.168.6.186:/rootfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.6.187

掛載nfs文件系統(tǒng),

  • root=/dev/nfs
  • nfsroot=192.168.6.186:/rootfs nfs服務(wù)器地址192.168.6.186,目錄為/rootfs,
  • rw 文件系統(tǒng)操作權(quán)限為可續(xù)寫
  • console=ttySAC2,115200 串口名稱和波特率
  • init=/linuxrc 內(nèi)核啟動(dòng)后運(yùn)行的進(jìn)程為linuxrc
  • ip=192.168.6.187 開發(fā)板地址

二、exynos-4412 Soc 啟動(dòng)順序

要想了解exynos-4412的啟動(dòng)順序,我們首先需要了解該soc的內(nèi)存布局。

1. exynos-4412內(nèi)存布局

通常一款soc的內(nèi)存在廠家設(shè)計(jì)的時(shí)候就已經(jīng)規(guī)定死了,對(duì)于使用者來說,我們無法改變。

我們只關(guān)心和啟動(dòng)相關(guān)的一個(gè)地址,

  • iROM 在soc內(nèi)部,出廠時(shí)廠家固化了特定的程序,iROM中程序?qū)?yīng)用戶來說不可改變
  • iRAM 在soc內(nèi)部,速度較快,但空間不大
  • DMC RAM控制器,位于SOC內(nèi)部,用于驅(qū)動(dòng)RAM,大容量的RAM都需要連接到該控制器

2. Booting Sequence

不同的廠家的啟動(dòng)順序是不太一樣的,本篇主要以三星的exynos-4412 soc為基礎(chǔ),講解該基于該板子的uboot啟動(dòng)順序。

根據(jù)上圖,系統(tǒng)啟動(dòng)的大概順序:

  • iROM在SOC內(nèi)部,是一個(gè)64KB的ROM,他樹池化一些系統(tǒng)啟動(dòng)必須的功能。比如:時(shí)鐘、棧。
  • iROM負(fù)責(zé)從特殊的啟動(dòng)外設(shè)加載BL1的image到soc內(nèi)部的256KB的SRAM中。啟動(dòng)的外設(shè)由操作按鈕來決定的。根據(jù)不同按鍵的值,iROM將會(huì)對(duì)bl1 的image做不同的校驗(yàn)。
  • BL1初始化系統(tǒng)時(shí)鐘和DRAM控制器,然后從啟動(dòng)外設(shè)加載OS image到DRAM中。根據(jù)啟動(dòng)按鈕的值的不同,BL1會(huì)對(duì)OS做不同的校驗(yàn)。
  • 啟動(dòng)完成之后,BL1跳轉(zhuǎn)到操作系統(tǒng)(kernel)。

iROM會(huì)根據(jù)OM 引腳的不同選擇不同的啟動(dòng)設(shè)備,對(duì)應(yīng)的OM寄存器需要提供對(duì)應(yīng)的啟動(dòng)信息。

三、內(nèi)核啟動(dòng)流程概述

1. 內(nèi)核啟動(dòng)流程 概述

如上圖所示:

  1. 設(shè)備上電之后,先執(zhí)行iROM中的出廠代碼,先進(jìn)行必要硬件的初始化 去執(zhí)行uboot,
  2. 通常把kernel、設(shè)備樹文件放到flash中
  3. 程序啟動(dòng)之后,往往先從flash啟動(dòng),運(yùn)行uboot
  4. 第一步:先進(jìn)行硬件的初始化(svc模式棧、clock、內(nèi)存、串口) 第二步:自搬移:把uboot從flash中拷貝到RAM中,跳轉(zhuǎn)到RAM中執(zhí)行剩下的uboot代碼
    第三步:把內(nèi)核拷貝到RAM中,執(zhí)行內(nèi)核,把控制權(quán)交給內(nèi)核。

2. 內(nèi)核啟動(dòng)詳細(xì)流程

開發(fā)板從上電到啟動(dòng)內(nèi)核的過程

四、uboot啟動(dòng)流程代碼詳解

在三星的SoC中, 啟動(dòng)流程可以分為三個(gè)階段BL0, BL1, BL2, BL3, 三星自己的手冊(cè)對(duì)BL1的解釋也不盡相同, 一種是將在iRAM中運(yùn)行的程序都?xì)w結(jié)為BL1; 一種是將iRAM中三星加密的代碼bl1.bin作為BL1, iRAM中剩余的部分作為BL2, 本文采用后者, 他們的主要分工如下:

  • BL0: ARM的起始地址都是0地址, 三星的芯片一般將0地址映射到iROM中, BL0就是指iROM中固化的啟動(dòng)代碼, 主要負(fù)責(zé)加載BL1
  • BL1: 三星對(duì)于bootloader的加密代碼bl1.bin, 要放在外設(shè)中uboot.bin的頭上, 和一部分uboot.bin一起加載到iRAM中運(yùn)行.
  • BL2: 從(nand/sd/usb)中拷貝的uboot.bin頭最大14K到iRAM中代碼中除去bl1.bin后剩余的部分, 負(fù)責(zé)設(shè)置CPU為SVC模式, 關(guān)閉MMU, 關(guān)閉中斷, 關(guān)閉iCache, 關(guān)閉看門狗, 初始化DRAM,初始化時(shí)鐘, 初始化串口, 設(shè)置棧, 校驗(yàn)BL2并將其搬移到DRAM高位地址, 重定位到DRAM中執(zhí)行BL3
  • BL3:是指在代碼重定向后在內(nèi)存中執(zhí)行的uboot的完整代碼, 負(fù)責(zé)初始化外設(shè),更新向量表, 清BSS, 準(zhǔn)備內(nèi)核啟動(dòng)參數(shù), 加載并運(yùn)行OS內(nèi)核

可以借助下圖理解這個(gè)流程

img

我們常說的uboot是一個(gè)兩階段bootloader,就是指上述的BL2和BL3. BL2主要做硬件直接相關(guān)的初始化,使用匯編編寫;BL3主要為操作系統(tǒng)的運(yùn)行準(zhǔn)備環(huán)境,主要用C編寫,這里以ARM平臺(tái)為例分析其啟動(dòng)流程。下面是啟動(dòng)過程中主要涉及的文件

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

1. BL2

BL2的主要文件和任務(wù)流程如下


arch/arm/cpu/armv7/start.S
\1. 設(shè)置CPU為SVC模式 \2. 關(guān)閉MMU \3. 關(guān)閉Cache \4. 跳轉(zhuǎn)到lowlevel_init.S low_level_init
board/samsung/origen/lowlevel_init.S
\5. 初始化時(shí)鐘 \6. 初始化內(nèi)存 \7. 初始化串口 \8. 關(guān)閉看門狗 \9. 跳轉(zhuǎn)到crt0.S _main arch/arm/lib/crt0.S \10. 設(shè)置棧 \11. 初始化C運(yùn)行環(huán)境 \12. 調(diào)用board_init_f() arch/arm/lib/board.c \13. board_init_f對(duì)全局信息GD結(jié)構(gòu)體進(jìn)行填充 arch/arm/lib/crt0.S \14. 代碼重定位------------BL2的最后的工作, 執(zhí)行完就進(jìn)入DRAM執(zhí)行BL2

2. lds文件

要想了解uboot整個(gè)項(xiàng)目的代碼流程,必須首先了解鏈接腳本【鏈接腳本參考《7. 從0開始學(xué)ARM-GNU偽指令,lds使用》】。

該文件決定了uboot最終生成的鏡像文件,各個(gè)段的布局。

uboot鏈接腳本如下:

u-boot-2013.01/arch/arm/cpu/u-boot.lds

文件內(nèi)容:

26 OUTPUT_FORMAT('elf32-littlearm', 'elf32-littlearm', 'elf32-littlearm') 27 OUTPUT_ARCH(arm) 28 ENTRY(_start) 29 SECTIONS 30 { 31     . = 0x00000000; 32  33     . = ALIGN(4); 34     .text : 35     { 36         __image_copy_start = .; 37         CPUDIR/start.o (.text*) 38         *(.text*) 39     } 40  41     . = ALIGN(4); 42     .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } 43  44     . = ALIGN(4); 45     .data : { 46         *(.data*) 47     } 48  49     . = ALIGN(4); 50  51     . = .; 52  53     . = ALIGN(4); 54     .u_boot_list : { 55     #include <u-boot.lst> 56     } 57  58     . = ALIGN(4); 59  60     __image_copy_end = .; 61  62     .rel.dyn : { 63         __rel_dyn_start = .; 64         *(.rel*) 65         __rel_dyn_end = .; 66     } 67  68     .dynsym : { 69         __dynsym_start = .; 70         *(.dynsym) 71     } 72  73     _end = .; 74  75     /* 76      * Deprecated: this MMU section is used by pxa at present but 77      * should not be used by new boards/CPUs. 78      */ 79     . = ALIGN(4096); 80     .mmutable : { 81         *(.mmutable) 82     } 83  84     .bss __rel_dyn_start (OVERLAY) : { 85         __bss_start = .; 86         *(.bss*) 87          . = ALIGN(4); 88         __bss_end__ = .; 89     } 90  91     /DISCARD/ : { *(.dynstr*) } 92     /DISCARD/ : { *(.dynamic*) } 93     /DISCARD/ : { *(.plt*) } 94     /DISCARD/ : { *(.interp*) } 95     /DISCARD/ : { *(.gnu*) } 96 } 97 

核心內(nèi)容解釋:

 27 OUTPUT_ARCH(arm)       :    該鏡像運(yùn)行在arm架構(gòu)的硬件上 28 ENTRY(_start)          :    程序的入口是 _start 29 SECTIONS 30 { 31  . = 0x00000000;      :   程序的鏈接地址,不是運(yùn)行地址【uboot一定是位置無關(guān)碼】 34     .text : 35     { 36         __image_copy_start = .;    : 宏對(duì)應(yīng)整個(gè)程序編譯好后首地址,自搬移代碼的初始位置 37         CPUDIR/start.o (.text*)    : 第一個(gè)目標(biāo)文件CPUDIR/start.o中的代碼段 38         *(.text*)                  : 剩下的目標(biāo)文件的代碼段 39     } 60     __image_copy_end = .;          : 自搬移代碼的結(jié)束為止

BSS全局未初始化變量、全局初始化為0的變量所在的段:

 84     .bss __rel_dyn_start (OVERLAY) : { 85         __bss_start = .; 88         __bss_end__ = .; 89     }

3. uboot啟動(dòng)代碼流程概要

代碼只分析到uboot命令行,函數(shù)main_loop()位置。

4. 啟動(dòng)代碼詳細(xì)分析

_start入口位于以下文件:

u-boot-2013.01/arch/arm/cpu/armv7/start.S

第一階段:

第二階段

第二階段代碼從_main開始:

以上代碼詳細(xì)解釋,請(qǐng)結(jié)合視頻同步學(xué)習(xí)。

五、uboot啟動(dòng)的幾個(gè)關(guān)鍵知識(shí)點(diǎn)

  1. 如何判斷第一條機(jī)器指令的位置?

鏈接腳本決定了內(nèi)存的布局。

uboot鏈接腳本如下:

u-boot-2013.01/arch/arm/cpu/u-boot.lds

文件內(nèi)容:

 28 ENTRY(_start) 29 SECTIONS 30 { 31     . = 0x00000000; 32 

uboot的入口是_start 鏈接地址是0x00000000

  1. uboot如何搬運(yùn)代碼? 代碼位于:
u-boot-2013.01/arch/arm/cpu/armv7/start.S

搬移代碼如下:

ENTRY(relocate_code) mov r4r0 /* save addr_sp */ mov r5r1 /* save addr of gd */ mov r6r2 /* save addr of destination */ adr r0_start cmp r0r6 moveq r9#0  /* no relocation. relocation offset(r9) = 0 */ beq relocate_done  /* skip relocation */ mov r1r6   /* r1 <- scratch for copy_loop */ ldr r3_image_copy_end_ofs add r2r0r3  /* r2 <- source end address     */copy_loopldmia r0!, {r9-r10}  /* copy from source address [r0]    */ stmia r1!, {r9-r10}  /* copy to   target address [r1]    */ cmp r0r2   /* until source end address [r2]    */ blo copy_loop

詳情參考第四章,第3節(jié)。

  1. uboot中,如何判斷此次開機(jī)是從斷電狀態(tài)開機(jī)還是從休眠狀態(tài)啟動(dòng)的?
board/samsung/fs4412/lowlevel_init.S

代碼如下:

 41   lowlevel_init: 54     /* AFTR wakeup reset */ 55     ldr r2, =S5P_CHECK_DIDLE 56     cmp r1, r2 57     beq exit_wakeup 58  59     /* LPA wakeup reset */ 60     ldr r2, =S5P_CHECK_LPA 61     cmp r1, r2 62     beq exit_wakeup 63  64     /* Sleep wakeup reset */ 65     ldr r2, =S5P_CHECK_SLEEP 66     cmp r1, r2 67     beq wakeup_reset 112 wakeup_reset: 113     bl system_clock_init 114     bl mem_ctrl_asm_init 115     bl tzpc_init 116  117 exit_wakeup: 118     /* Load return address and jump to kernel */ 119     ldr r0, =(EXYNOS4_POWER_BASE + INFORM0_OFFSET) 120  121     /* r1 = physical address of exynos4210_cpu_resume function */ 122     ldr r1, [r0] 123  124     /* Jump to kernel*/ 125     mov pc, r1

由上可知,當(dāng)手機(jī)因?yàn)楦鞣N原因進(jìn)入休眠時(shí),會(huì)將當(dāng)前程序執(zhí)行的上下文保護(hù)起來,并向一些pmic的寄存器中寫入指定的數(shù)據(jù),以表明此次是因?yàn)楹畏N原因進(jìn)入休眠。

而手機(jī)并沒有完全斷電,而是處于一個(gè)低功耗模式下,此時(shí)啟動(dòng)RAM仍然有數(shù)據(jù),所以在此啟動(dòng)后,只需要從特殊的寄存器中讀取相應(yīng)的值,就可以知道之前是因?yàn)槭裁丛蛐菝撸M(jìn)而回復(fù)休眠之前的上下文即可。

  1. uboot代碼搬到ram之后,代碼的運(yùn)行地址發(fā)生了變化,如何保證程序跳轉(zhuǎn)不會(huì)出錯(cuò)?

除了要保證uboot代碼是基于地址無關(guān)的,此外.rel.dyn幫我們解決了,其實(shí)主要還是編譯器幫我們做了很多工作。

位置無關(guān)碼參考《15. 從0開始學(xué)ARM-位置無關(guān)碼》

  1. 設(shè)備啟動(dòng)的時(shí)候,有可能直接從ram啟動(dòng), 如何知道當(dāng)前是從flah啟動(dòng)還是ram啟動(dòng)的?

文件:

board/samsung/fs4412/lowlevel_init.S

代碼:

lowlevel_init:

85     /* 86      * If U-boot is already running in ram, no need to relocate U-Boot. 87      * Memory controller must be configured before relocating U-Boot 88      * in ram. 89      */ 90     ldr r0, =0x0ffffff      /* r0 <- Mask Bits*/ 91     bic r1, pc, r0      /* pc <- current addr of code */ 92                     /* r1 <- unmasked bits of pc */ 93     ldr r2, _TEXT_BASE      /* r2 <- original base addr in ram */ 94     bic r2, r2, r0      /* r2 <- unmasked bits of r2*/ 95     cmp r1, r2          /* compare r1, r2 */ 96     beq 1f          /* r0 == r1 then skip sdram init */

原理: RAM地址空間是:0x40000000-0xA0000000 0xA0000000-0x00000000 而iROM/iRAM地址的bit:28-31均是0,所以只需要讀取出執(zhí)行到lowlevel_init時(shí)pc的值,判斷其bit:28-31是否是0即可知道現(xiàn)在代碼是否運(yùn)行在RAM中。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
arm-linux之uboot向內(nèi)核傳遞參數(shù)(setup_arch分析)
uboot-與linux內(nèi)核機(jī)器碼
Linux2.6.34.2在TQ6410上的移植詳解
Tiny6410開發(fā)板Linux系統(tǒng)自學(xué)筆記
小靜的ARM學(xué)習(xí)日志04
u-boot移植(友善smart210開發(fā)板)(轉(zhuǎn)載)
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服