成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

詳解Cortex-A9 uboot啟動代碼

系統 Linux
本篇給大家介紹一款比較常用的bootloader:uboot,通過uboot的介紹以及源代碼的詳細分析,讓大家把之前所有ARM相關的知識點融會貫通起來。

[[378325]]

 前言

我們在前面的arm系列課程,已經講解了arm的架構、匯編指令、異常、常用外設的控制器驅動,那么我們已經具備開發arm系列產品的基本技能。

本篇給大家介紹一款比較常用的bootloader:uboot,通過uboot的介紹以及源代碼的詳細分析,讓大家把之前所有ARM相關的知識點融會貫通起來。

一、uboot

1. 概念

U-Boot 是一個主要用于嵌入式系統的引導加載程序,可以支持多種不同的計算機系統結構,包括PPC、ARM、AVR32、MIPS、x86、68k、Nios與MicroBlaze。這也是一套在GNU通用公共許可證之下發布的自由軟件。

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

2. uboot基本功能

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

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

3. 常用命令

uboot命令比較多,下面只列舉網絡啟動要用到的命令:

4. 配置參數舉例

以下以網絡下載內核、網絡掛載nfs為例。

1)ubuntu環境

ubuntu ip:192.168.6.186

nfs配置:

配置文件如下:

  1. /etc/exports 

配置信息如下:

 

nfs

2)開發板設置

開發板ip:192.168.6.187

配置命令:

  1. setenv ipaddr 192.168.6.187      ;板子的ip 
  2. setenv serverip 192.168.6.186    ;虛擬機的ip 
  3. setenv gatewayip 192.168.1.1     ;網關 
  4. saveenv                          ;保存配置 

加載內核和設備樹

  1. setenv bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-fs4412.dtb\;bootm 41000000 - 42000000 

bootcmd:uboot2啟動之后,首先先執行找到這個參數,執行后面的命令。

從tftp服務器下載內核鏡像uImage到地址41000000,設備樹文件exynos4412-fs4412.dtb到42000000,并通過命令bootm加載啟動內核。

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

掛載nfs文件系統

  • root=/dev/nfs
  • nfsroot=192.168.6.186:/rootfs nfs服務器地址192.168.6.186,目錄為/rootfs,
  • rw 文件系統操作權限為可續寫
  • console=ttySAC2,115200 串口名稱和波特率
  • init=/linuxrc 內核啟動后運行的進程為linuxrc
  • ip=192.168.6.187 開發板地址

二、exynos-4412 Soc 啟動順序

要想了解exynos-4412的啟動順序,我們首先需要了解該soc的內存布局。

1. exynos-4412內存布局

通常一款soc的內存在廠家設計的時候就已經規定死了,對于使用者來說,我們無法改變。


我們只關心和啟動相關的一個地址,

  1. iROM 在soc內部,出廠時廠家固化了特定的程序,iROM中程序對應用戶來說不可改變
  2. iRAM 在soc內部,速度較快,但空間不大
  3. DMC RAM控制器,位于SOC內部,用于驅動RAM,大容量的RAM都需要連接到該控制器

2. Booting Sequence

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


根據上圖,系統啟動的大概順序:

  • iROM在SOC內部,是一個64KB的ROM,他樹池化一些系統啟動必須的功能。比如:時鐘、棧。
  • iROM負責從特殊的啟動外設加載BL1的image到soc內部的256KB的SRAM中。啟動的外設由操作按鈕來決定的。根據不同按鍵的值,iROM將會對bl1 的image做不同的校驗。
  • BL1初始化系統時鐘和DRAM控制器,然后從啟動外設加載OS image到DRAM中。根據啟動按鈕的值的不同,BL1會對OS做不同的校驗。
  • 啟動完成之后,BL1跳轉到操作系統(kernel)。

iROM會根據OM 引腳的不同選擇不同的啟動設備,對應的OM寄存器需要提供對應的啟動信息。

三、內核啟動流程概述

1. 內核啟動流程 概述

 

uboot啟動流程

如上圖所示:

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

2. 內核啟動詳細流程

開發板從上電到啟動內核的過程

四、uboot啟動流程代碼詳解

1. lds文件

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

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

uboot鏈接腳本如下:

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

文件內容:

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

核心內容解釋:

  1. 27 OUTPUT_ARCH(arm)       :    該鏡像運行在arm架構的硬件上 
  2. 28 ENTRY(_start)          :    程序的入口是 _start 
  3. 29 SECTIONS 
  4. 30 { 
  5. 31  . = 0x00000000;      :   程序的鏈接地址,不是運行地址【uboot一定是位置無關碼】 
  6. 34     .text : 
  7. 35     { 
  8. 36         __image_copy_start = .;    : 宏對應整個程序編譯好后首地址,自搬移代碼的初始位置 
  9. 37         CPUDIR/start.o (.text*)    : 第一個目標文件CPUDIR/start.o中的代碼段 
  10. 38         *(.text*)                  : 剩下的目標文件的代碼段 
  11. 39     } 
  12. 60     __image_copy_end = .;          : 自搬移代碼的結束為止 

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

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

2. uboot啟動代碼流程概要

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


3. 啟動代碼詳細分析

_start入口位于以下文件:

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

第一階段:

 

第二階段

第二階段代碼從_main開始:


以上代碼詳細解釋,請結合B站視頻同步學習。

五、uboot啟動的幾個關鍵知識點

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

鏈接腳本決定了內存的布局。

uboot鏈接腳本如下:

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

文件內容:

  1. 28 ENTRY(_start) 
  2. 29 SECTIONS 
  3. 30 { 
  4. 31     . = 0x00000000; 
  5. 32  

uboot的入口是_start

鏈接地址是0x00000000

2.uboot如何搬運代碼?

代碼位于:

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

搬移代碼如下:

  1. ENTRY(relocate_code) 
  2.  mov r4, r0 /* save addr_sp */ 
  3.  mov r5, r1 /* save addr of gd */ 
  4.  mov r6, r2 /* save addr of destination */ 
  5.  
  6.  adr r0, _start 
  7.  cmp r0, r6 
  8.  moveq r9, #0  /* no relocation. relocation offset(r9) = 0 */ 
  9.  beq relocate_done  /* skip relocation */ 
  10.  mov r1, r6   /* r1 <- scratch for copy_loop */ 
  11.  ldr r3, _image_copy_end_ofs 
  12.  add r2, r0, r3  /* r2 <- source end address     */ 
  13.  
  14. copy_loop: 
  15.  ldmia r0!, {r9-r10}  /* copy from source address [r0]    */ 
  16.  stmia r1!, {r9-r10}  /* copy to   target address [r1]    */ 
  17.  cmp r0, r2   /* until source end address [r2]    */ 
  18.  blo copy_loop 

詳情參考第四章,第3節。

3.uboot中,如何判斷此次開機是從斷電狀態開機還是從休眠狀態啟動的?

  1. board/samsung/fs4412/lowlevel_init.S 

代碼如下:

  1. 41   lowlevel_init: 
  2. 54     /* AFTR wakeup reset */ 
  3. 55     ldr r2, =S5P_CHECK_DIDLE 
  4. 56     cmp r1, r2 
  5. 57     beq exit_wakeup 
  6. 58  
  7. 59     /* LPA wakeup reset */ 
  8. 60     ldr r2, =S5P_CHECK_LPA 
  9. 61     cmp r1, r2 
  10. 62     beq exit_wakeup 
  11. 63  
  12. 64     /* Sleep wakeup reset */ 
  13. 65     ldr r2, =S5P_CHECK_SLEEP 
  14. 66     cmp r1, r2 
  15. 67     beq wakeup_reset 
  16.  
  17. 112 wakeup_reset: 
  18. 113     bl system_clock_init 
  19. 114     bl mem_ctrl_asm_init 
  20. 115     bl tzpc_init 
  21. 116  
  22. 117 exit_wakeup: 
  23. 118     /* Load return address and jump to kernel */ 
  24. 119     ldr r0, =(EXYNOS4_POWER_BASE + INFORM0_OFFSET) 
  25. 120  
  26. 121     /* r1 = physical address of exynos4210_cpu_resume function */ 
  27. 122     ldr r1, [r0] 
  28. 123  
  29. 124     /* Jump to kernel*/ 
  30. 125     mov pc, r1 

由上可知,當手機因為各種原因進入休眠時,會將當前程序執行的上下文保護起來,并向一些pmic的寄存器中寫入指定的數據,以表明此次是因為何種原因進入休眠。

而手機并沒有完全斷電,而是處于一個低功耗模式下,此時啟動RAM仍然有數據,所以在此啟動后,只需要從特殊的寄存器中讀取相應的值,就可以知道之前是因為什么原因休眠,進而回復休眠之前的上下文即可。

3.uboot代碼搬到ram之后,代碼的運行地址發生了變化,如何保證程序跳轉不會出錯?

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

位置無關碼參考《15. 從0學ARM-什么是位置無關碼?》

4.設備啟動的時候,有可能直接從ram啟動, 如何知道當前是從flah啟動還是ram啟動的?

文件:

  1. board/samsung/fs4412/lowlevel_init.S 

代碼:

lowlevel_init:

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

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

 

責任編輯:姜華 來源: 一口Linux
相關推薦

2021-01-19 19:32:01

Cortex-A9 R嵌入式系統i2c 外設

2021-01-06 05:42:42

Cortex-A9 R嵌入式系統 RTC

2021-01-16 11:40:28

ARM嵌入式開發ADC應用

2020-12-22 11:54:42

C語言Cortex-A9LED匯編

2021-01-08 12:06:59

WDT定時裝置

2020-12-30 15:17:25

Cortex-A9UARTprintf函數

2009-11-11 10:19:59

uboot內核

2021-04-20 09:26:40

Cortex M架構Cortex A架構STM32系列

2019-08-19 00:31:16

Pytorch神經網絡深度學習

2012-02-21 23:05:17

Windows啟動順序

2011-02-23 15:26:01

FileZilla

2024-11-27 08:14:43

2025-06-26 02:45:00

UbootSoC系統

2017-08-03 10:25:26

AndroidActivity

2010-06-13 15:58:20

GRUB啟動命令

2024-12-16 08:10:00

Spring開發

2010-06-09 13:52:55

OpenSUSE桌面

2009-09-07 14:54:47

CCNA學習筆記

2009-12-24 14:14:41

Fedora 9

2009-12-22 17:46:56

Fedora 9嵌入式
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产成人精品一区二区三区四区 | 自拍偷拍亚洲视频 | 久久男人| 综合网在线 | 久久国产一区二区三区 | 国产一区二区三区四区五区加勒比 | 国产成人精品一区二区 | 99久久国产免费 | 欧美激情 一区 | 美国十次成人欧美色导视频 | 99这里只有精品视频 | 欧美日韩综合 | 亚洲精品一区二区三区在线 | 亚洲精品视频免费观看 | 在线看黄免费 | 欧美在线视频一区 | 涩爱av一区二区三区 | 成人免费看片网 | 人人艹人人 | 美女视频一区 | 黄瓜av | 国产精品不卡一区 | 成人亚洲精品久久久久软件 | 久久手机视频 | 亚洲福利精品 | 97在线超碰| 国产欧美一区二区三区日本久久久 | 国产精品五月天 | 亚洲精品68久久久一区 | 神马影院一区二区三区 | 久久亚洲国产精品日日av夜夜 | 天天干免费视频 | 亚洲日韩欧美一区二区在线 | 不卡一区 | 亚洲视频免费在线观看 | 成年人在线视频 | 国产亚洲高清视频 | 国产1区| 免费在线一区二区 | av网站在线播放 | 在线观看国产 |