iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >如何实现Cortex-A9 uboot启动代码
  • 102
分享到

如何实现Cortex-A9 uboot启动代码

2023-06-15 16:06:10 102人浏览 薄情痞子
摘要

小编给大家分享一下如何实现Cortex-A9 uboot启动代码,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、uboot1. 概念U-Boot  是一个主要用于嵌入式系统的引导加载程序,可以支持多种不同的计算

小编给大家分享一下如何实现Cortex-A9 uboot启动代码,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

一、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命令比较多,下面只列举网络启动要用到的命令:

如何实现Cortex-A9 uboot启动代码

4. 配置参数举例

以下以网络下载内核、网络挂载nfs为例。

1)ubuntu环境

ubuntu ip:192.168.6.186

nfs配置:

配置文件如下:

/etc/exports

配置信息如下:

 如何实现Cortex-A9 uboot启动代码

nfs

2)开发板设置

开发板ip:192.168.6.187

配置命令:

setenv ipaddr 192.168.6.187      ;板子的ip setenv serverip 192.168.6.186    ;虚拟机的ip setenv gatewayip 192.168.1.1     ;网关 saveenv                          ;保存配置

加载内核和设备树

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

bootcmd:uboot2启动之后,首先先执行找到这个参数,执行后面的命令。

从tftp服务器下载内核镜像uImage到地址41000000,设备树文件exynos4412-fs4412.dtb到42000000,并通过命令bootm加载启动内核。

  • 挂载nfs

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的内存在厂家设计的时候就已经规定死了,对于使用者来说,我们无法改变。

如何实现Cortex-A9 uboot启动代码

我们只关心和启动相关的一个地址,

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. iROM 在soc内部,出厂时厂家固化了特定的程序,iROM中程序对应用户来说不可改变

  3. iRAM 在soc内部,速度较快,但空间不大

  4. DMC RAM控制器,位于SOC内部,用于驱动RAM,大容量的RAM都需要连接到该控制器

2. Booting Sequence

不同的厂家的启动顺序是不太一样的,本篇主要以三星的exynos-4412 soc为基础,讲解该基于该板子的uboot启动顺序。

如何实现Cortex-A9 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. 内核启动流程 概述

 如何实现Cortex-A9 uboot启动代码

uboot启动流程

如上图所示:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 设备上电之后,先执行iROM中的出厂代码,先进行必要硬件的初始化 去执行uboot,

  3. 通常把kernel、设备树文件放到flash中

  4. 程序启动之后,往往先从flash启动,运行uboot

  5. 先进行硬件的初始化(svc模式栈、clock、内存、串口)  第二步:自搬移:把uboot从flash中拷贝到RAM中,跳转到RAM中执行剩下的uboot代码

  6. 把内核拷贝到RAM中,执行内核,把控制权交给内核。

2. 内核启动详细流程

如何实现Cortex-A9 uboot启动代码

开发板从上电到启动内核的过程

四、uboot启动流程代码详解

1. lds文件

要想了解uboot整个项目的代码流程,必须首先了解链接脚本【链接脚本参考《7. 从0开始学ARM-GNU伪指令,lds使用》】。

该文件决定了uboot最终生成的镜像文件,各个段的布局。

uboot链接脚本如下:

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

文件内容:

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       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

核心内容解释:

27 OUTPUT_ARCH(arm)       :    该镜像运行在arm架构的硬件上 28 ENTRY(_start)          :    程序的入口是 _start 29 SECTIONS 30 { 31  . = 0x00000000;      :   程序的链接地址,不是运行地址【uboot一定是位置无关码】 34     .text : 35     { 36         __image_copy_start = .;    : 宏对应整个程序编译好后首地址,自搬移代码的初始位置 37         CPUDIR/start.o (.text*)    : 第一个目标文件CPUDIR/start.o中的代码段 38         *(.text*)                  : 剩下的目标文件的代码段 39     } 60     __image_copy_end = .;          : 自搬移代码的结束为止

BSS全局未初始化变量、全局初始化为0的变量所在的段:

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

2. uboot启动代码流程概要

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

如何实现Cortex-A9 uboot启动代码

3. 启动代码详细分析

_start入口位于以下文件:

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

第一阶段:

 如何实现Cortex-A9 uboot启动代码

第二阶段

第二阶段代码从_main开始:

如何实现Cortex-A9 uboot启动代码

以上代码详细解释,请结合B站视频同步学习

五、uboot启动的几个关键知识点

1.如何判断第一条机器指令的位置?

链接脚本决定了内存的布局。

uboot链接脚本如下:

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

文件内容:

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

uboot的入口是_start

链接地址是0x00000000

uboot如何搬运代码?

代码位于:

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

搬移代码如下:

ENTRY(relocate_code)  mov r4, r0   mov r5, r1   mov r6, r2    adr r0, _start  cmp r0, r6  moveq r9, #0    beq relocate_done    mov r1, r6     ldr r3, _image_copy_end_ofs  add r2, r0, r3    copy_loop:  ldmia r0!, {r9-r10}    stmia r1!, {r9-r10}    cmp r0, r2     blo copy_loop

详情参考第四章,第3节。

uboot中,如何判断此次开机是从断电状态开机还是从休眠状态启动的?

board/samsung/fs4412/lowlevel_init.S

代码如下:

41   lowlevel_init: 54      55     ldr r2, =S5P_CHECK_DIDLE 56     cmp r1, r2 57     beq exit_wakeup 58  59      60     ldr r2, =S5P_CHECK_LPA 61     cmp r1, r2 62     beq exit_wakeup 63  64      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      119     ldr r0, =(EXYNOS4_POWER_BASE + INFORM0_OFFSET) 120  121      122     ldr r1, [r0] 123  124      125     mov pc, r1

由上可知,当手机因为各种原因进入休眠时,会将当前程序执行的上下文保护起来,并向一些pmic的寄存器中写入指定的数据,以表明此次是因为何种原因进入休眠。

而手机并没有完全断电,而是处于一个低功耗模式下,此时启动RAM仍然有数据,所以在此启动后,只需要从特殊的寄存器中读取相应的值,就可以知道之前是因为什么原因休眠,进而回复休眠之前的上下文即可。

uboot代码搬到ram之后,代码的运行地址发生了变化,如何保证程序跳转不会出错?

除了要保证uboot代码是基于地址无关的,此外.rel.dyn帮我们解决了,其实主要还是编译器帮我们做了很多工作。

位置无关码参考《15. 从0学ARM-什么是位置无关码?》

设备启动的时候,有可能直接从ram启动, 如何知道当前是从flah启动还是ram启动的?

文件:

board/samsung/fs4412/lowlevel_init.S

代码:

lowlevel_init:

85       90     ldr r0, =0x0ffffff        91     bic r1, pc, r0        92                       93     ldr r2, _TEXT_BASE        94     bic r2, r2, r0        95     cmp r1, r2            96     beq 1f          

原理:RAM地址空间是:0x40000000-0xA0000000 0xA0000000-0x00000000  而iROM/iRAM地址的bit:28-31均是0,所以只需要读取出执行到lowlevel_init时pc的值,判断其bit:28-31是否是0即可知道现在代码是否运行在RAM中。

看完了这篇文章,相信你对“如何实现Cortex-A9 uboot启动代码”有了一定的了解,如果想了解更多相关知识,欢迎关注编程网精选频道,感谢各位的阅读!

--结束END--

本文标题: 如何实现Cortex-A9 uboot启动代码

本文链接: https://www.lsjlt.com/news/280858.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何实现Cortex-A9 uboot启动代码
    小编给大家分享一下如何实现Cortex-A9 uboot启动代码,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、uboot1. 概念U-Boot  是一个主要用于嵌入式系统的引导加载程序,可以支持多种不同的计算...
    99+
    2023-06-15
  • SpringBoot怎么实现启动时自动执行代码
    这篇文章主要介绍了SpringBoot怎么实现启动时自动执行代码的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringBoot怎么实现启动时自动执行代码文章都会有所收获,下面我们一起来看看吧。前言目前开发的...
    99+
    2023-06-29
  • Spring源码如何实现动态代理
    小编给大家分享一下Spring源码如何实现动态代理,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!注:这里不阐述Spring和AOP的一些基本概念和用法,直接进入正题。流程  Spring所管理的对象大体会经过确定实例化对象...
    99+
    2023-06-14
  • Dreamweaver代码如何实现自动排版
    小编给大家分享一下Dreamweaver代码如何实现自动排版,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!对于这样的代码是不是很头疼?如果自己慢慢排版的话也会浪费...
    99+
    2023-06-08
  • php如何实现代码自动执行
    本文小编为大家详细介绍“php如何实现代码自动执行”,内容详细,步骤清晰,细节处理妥当,希望这篇“php如何实现代码自动执行”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、PHP的自动执行功能PHP提供了多种方...
    99+
    2023-07-06
  • Springboot如何启动执行特定代码
    这篇文章给大家分享的是有关Springboot如何启动执行特定代码的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。实现InitializingBean接口或使用@PostConstruct注解实现Initializ...
    99+
    2023-06-21
  • C#实现启动项管理的示例代码
    目录实践过程效果代码实践过程 效果 代码 public partial class Form1 : Form { public Form1() { ...
    99+
    2022-12-15
    C#启动项管理 C# 启动项
  • PHP/EclipsePHP如何实现代码自动提示
    这篇文章主要为大家展示了“PHP/EclipsePHP如何实现代码自动提示”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“PHP/EclipsePHP如何实现代码...
    99+
    2024-04-02
  • Python如何实现代码雨动画效果
    本篇内容介绍了“Python如何实现代码雨动画效果”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!代码如下import sysimp...
    99+
    2023-07-04
  • SpringBoot Tomcat启动实例代码详解
    废话不多了,具体内容如下所示:Application configuration class:@SpringBootApplicationpublic class ServletInitializer extends SpringBootS...
    99+
    2023-05-31
    spring boot tomcat
  • SpringBoot启动时自动执行代码的几种实现方式
    目录前言java自身的启动时加载方式static代码块构造方法Spring启动时加载方式代码测试总结前言 目前开发的SpringBoot项目在启动的时候需要预加载一些资源。而如何实现...
    99+
    2024-04-02
  • 如何使用vue代码实现虚拟滚动
    这篇“如何使用vue代码实现虚拟滚动”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“如何使用vue代码实现虚拟滚动”文章吧。滚...
    99+
    2023-07-04
  • CSS代码如何实现多重背景动画
    这篇“CSS代码如何实现多重背景动画”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“CSS代码如何实现多重背景动画”文章吧。C...
    99+
    2023-07-04
  • java动态代理实现代码
    目录1、代理模式2、动态代理3、原理研究4、应用5、总结1、代理模式 代理模式是常用的设计模式之一,也是开发中常见的设计模式。 简单的描述一下,代理模式就是将实现类隔离开,比如你想给...
    99+
    2024-04-02
  • java启动监听mq消息代码如何写
    在Java中启动监听MQ消息的代码可以使用JMS(Java Message Service)的API来实现。下面是一个简单的示例代码...
    99+
    2023-10-27
    java mq
  • 如何实现1秒启动Linux
    本篇内容介绍了“如何实现1秒启动Linux”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!尽可能快的启动系统,对于自动化设备是非常重要的。系统...
    99+
    2023-06-12
  • 如何使用PHP代码实现QQ代码
    要使用PHP代码实现QQ代码,你可以使用QQ互联开放平台提供的SDK来完成。以下是一个简单的示例代码:首先,你需要从QQ互联开放平台...
    99+
    2023-08-28
    PHP
  • windows声卡驱动无法启动代码10如何解决
    本篇内容介绍了“windows声卡驱动无法启动代码10如何解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成...
    99+
    2023-02-08
    windows
  • Jupyter Notebook如何实现代码格式自动补全
    这篇文章将为大家详细讲解有关Jupyter Notebook如何实现代码格式自动补全,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。代码格式自动补全有时jupyter no...
    99+
    2024-04-02
  • CSS3代码如何实现复选框动画特效
    本篇内容主要讲解“CSS3代码如何实现复选框动画特效”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“CSS3代码如何实现复选框动画特效”吧!实例代码<!DOCTYPE html&g...
    99+
    2023-07-04
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作