[嵌入式系统-41]:uboot的启动流程与自拷贝、重定位

目录

一、嵌入式系统启动总体流程

1.1 硬件组成

1.2 内存空间

1.3 代码块结构

1.4 嵌入式系统的启动模块与启动流程 -- 有SPL的情形

1.5 嵌入式系统的启动模块与启动流程 - 无SPL的情形

二、关键步骤1:自拷贝relocate概述

2.1 什么是自拷贝?

2.2 为什么自拷贝?

2.3 relocate() 函数

2.4 代码段自拷贝的源代码

三、关键步骤2:什么是重定位

3.1 程序代码寻址的两种方法:相对寻址与绝对寻址

3.2 地址重定位的方法

3.3 uboot拷贝后的地址重定向:所有的链接地址+新的偏移量

四、跳转到新的uboot地址继续执行

五、异常向量表定义


一、嵌入式系统启动总体流程

1.1 硬件组成

(1)SOC芯片

  • CPU
  • 片内ROM:启动代码
  • 片内SRAM:大小有限的片内RAM, 通常只有xK大小,无法存放整个uboot。
  • 片内FLASH控制器

(2)片外FLASH

  • SPL:初始启动代码,完成SOC芯片和Flash控制器的初始化
  • uboot:用于SOC芯片初始化和操作系统的加载

(3)片外DDR

  • uboot
  • 操作系统
  • 文件系统
  • 应用程序

SPL(Secondary Program Loader)和 U-Boot(Universal Boot Loader)是在嵌入式系统中用于引导启动的两个关键组件,它们之间有一些区别:

  1. 功能:

    • SPL: SPL 是一个辅助程序加载器,主要负责在系统上电后的早期阶段执行。它的主要功能包括硬件初始化、加载引导程序uboot、启动内核以及错误处理等。
    • U-Boot: U-Boot 是一个功能更为完整的引导加载程序,它在系统启动过程的后期阶段执行。除了加载内核之外,U-Boot 还提供了更多的功能,如命令行界面、环境变量配置、网络引导等。
  2. 复杂性:

    • SPL: SPL 通常比较轻量级和简单,因为它主要负责早期的硬件初始化和引导加载,不涉及过多的系统管理功能。
    • U-Boot: U-Boot 则更为复杂,因为它提供了丰富的功能和配置选项,包括文件系统支持、网络协议支持、驱动程序加载等,同时还有一个交互式命令行界面。
  3. 启动过程:

    • SPL: 在系统上电后的最早阶段执行,主要负责启动引导加载程序。
    • U-Boot: 在引导加载程序的后期阶段执行,可以与用户交互,并在加载内核之前执行一系列初始化和配置操作。
  4. 依赖关系:

    • SPL: 通常在系统上电后直接执行,不依赖于其他引导加载程序。
    • U-Boot: 通常依赖于 SPL 或其他辅助程序加载器,在 SPL 加载后才执行

总的来说,SPL 是 U-Boot 的一个组成部分,负责早期的系统初始化和引导加载,而 U-Boot 则是一个更为完整和功能丰富的引导加载程序,提供了更多的系统管理功能和配置选项。

1.2 内存空间

1.3 代码块结构

1.4 嵌入式系统的启动模块与启动流程 -- 有SPL的情形

  • BL1: SPL
  • BL2: uboot

  1. 系统上电后,CPU跳转到复位地址,执行片内的bootrom,片内的boot rom完成CPU的和Flash控制器的初始化,从外部的SPI flash或NAND FLASH读取SPL代码
  2. SPL完成部分初始化,并把自己拷贝到片内的SRAM中,
  3. SPL在SRAM中完成CPU和DDR RAM的初始化。
  4. SPL把uboot拷贝到外部的DDR RAM的0x0000000地址处。
  5. 在外部DDR RAM中执行uboot。
  6. uboot完成SOC系统的初始化,并把自己从RAM低端地址拷贝到RAM的高端地址,把低端地址空间留给操作系统 (可选)
  7. uboot完成地址的重定向,并且在RAM的高端继续执行代码
  8. uboot把OS从Flash中加载到RAM的低地址空间段
  9. uboot把执行控制交给OS(直接跳转), 在RAM的低地址空间段执行OS

1.5 嵌入式系统的启动模块与启动流程 - 无SPL的情形

  1. 系统上电后,CPU跳转到复位地址,执行片内的bootrom,片内的boot rom完成CPU的和Flash控制器的初始化。
  2. 片内的bootrom读取Flash空间的DDR配置信息,并完成DDR RAM的初始化
  3. XXX
  4. bootrom把uboot拷贝到外部的DDR RAM的0x0000000地址处。
  5. 在外部DDR RAM中执行uboot。
  6. uboot完成SOC系统的初始化,并把自己从RAM低端地址拷贝到RAM的高端地址,把低端地址空间留给操作系统 (可选)
  7. uboot完成地址的重定向,并且在RAM的高端继续执行代码
  8. uboot把OS从Flash中加载到RAM的低地址空间段.
  9. uboot把执行控制交给OS(直接跳转), 在RAM的低地址空间段执行OS

二、关键步骤1:自拷贝relocate概述

2.1 什么是自拷贝?

在 U-Boot 中,自拷贝指的是将自身的代码从一个内存区域拷贝到另一个内存区域的操作。

这通常发生在启动过程中,其中的代码需要在不同的内存地址空间中执行,或者需要提高执行效率和可维护性。

2.2 为什么自拷贝?

将 ROM 中的代码拷贝到 RAM 中的主要原因包括:

  1. 执行速度: RAM 通常比 ROM 速度更快,因此将代码从 ROM 拷贝到 RAM 中可以提高代码的执行速度。在启动过程中,执行速度的提升可以缩短启动时间,提升系统的响应速度。

  2. 可写性: ROM 通常是只读的,而 RAM 是可读写的。将代码从 ROM 拷贝到 RAM 中可以使得代码变得可写,从而在运行时可以动态修改或更新代码,例如修复 bug 或者添加新功能,提高系统的可维护性和灵活性。

  3. 位置无关性: 一些代码可能需要在位置无关的环境下执行,而 ROM 中的代码通常是在固定地址上执行的。将代码拷贝到 RAM 中可以使得代码在任意地址上正确地执行,从而增强了代码的可移植性和灵活性。

  4. 内存映射或重定位: 在启动过程中,可能需要对内存进行映射或重定位,以适应不同的硬件配置或启动流程。将代码从 ROM 拷贝到 RAM 中可以确保代码可以正确地在新的内存地址空间中执行

  5. 为OS预留空间:"uboot自拷贝"通常指的是 U-Boot 在启动时将自身代码从存储介质(如闪存、SD 卡等)拷贝到系统内存中执行。这个过程通常是为了在系统启动后,为操作系统(OS)留出足够的空间。

    在嵌入式系统中,U-Boot 通常被加载到系统的非易失性存储器中,例如闪存。但由于闪存等存储介质的读写速度相对较慢,为了提高系统启动速度,U-Boot 会首先将自身代码拷贝到系统内存中执行。这样,一旦系统启动完毕,U-Boot 就可以释放存储介质上的空间,留给操作系统使用。

    因此,"uboot自拷贝"的过程既是为了提高启动速度,又是为了给操作系统预留足够的空间,以便后续操作系统的正常运行。

  6. 硬件限制: 一些硬件平台可能要求代码必须存储在 RAM 中才能正确执行,因此需要将 ROM 中的代码拷贝到 RAM 中才能启动系统。

        总的来说,将 ROM 中的代码拷贝到 RAM 中可以提高代码的执行速度、可写性和灵活性,同时确保代码可以在不同的硬件配置或启动流程中正确执行。

2.3 relocate() 函数

在 U-Boot 中,relocate() 函数是用于执行地址重定位操作的关键函数之一。这个函数通常被调用在 U-Boot 启动过程的早期阶段,它的主要作用是:将 U-Boot 代码从加载地址(链接地址)重定位到实际的内存地址上,以便程序能够正确执行。

relocate() 函数的具体实现可能会因不同的 U-Boot 版本或针对特定的硬件平台而有所不同,但其主要步骤通常包括以下内容:

  1. 计算重定位偏移量
    在开始执行重定位之前,需要计算出实际内存地址与加载地址之间的偏移量。这个偏移量通常是硬件相关的,因为不同的硬件平台可能有不同的内存映射方式。

  2. 更新代码中的地址
    遍历 U-Boot 代码中所有涉及地址的地方,将这些地址加上重定位偏移量,以将其映射到实际的内存地址上。

  3. 更新全局数据指针
    由于 U-Boot 可能包含一些全局数据结构,这些结构中包含了指向代码段、数据段等的指针。在重定位过程中,这些指针也需要相应地更新,以确保指向正确的内存地址。

  4. 处理可能的自修改代码
    如果 U-Boot 中存在一些自修改代码(self-modifying code),即在运行时会修改自身指令的代码,那么在重定位过程中需要特别处理,确保这些代码修改后的指令仍然能够正确执行。

  5. 执行重定位
    最后,执行实际的重定位操作,将 U-Boot 代码段和数据段移动到正确的内存地址上,并更新相关的指针和数据结构。

relocate() 函数的实现通常是高度依赖于具体的硬件平台和 U-Boot 的版本的。在阅读或修改 relocate() 函数时,需要特别注意硬件的内存映射方式以及 U-Boot 的代码结构,以确保正确理解和处理地址重定位过程中的各种细节和特殊情况。

2.4 代码段自拷贝的源代码

三、关键步骤2:什么是重定位

3.1 程序代码寻址的两种方法:相对寻址与绝对寻址

程序代码寻址的两种方法是相对寻址和绝对寻址:

  1. 相对寻址: 相对寻址是指根据当前指令的位置来计算目标地址的方法。在相对寻址中,指令中包含了一个偏移量或者相对地址,该偏移量表示了指令执行时目标地址相对于当前指令位置的偏移。当指令执行时,处理器会使用当前指令的地址加上该相对地址来计算目标地址。相对寻址通常用于相对较短的跳转或分支指令,它使得指令更加紧凑,并且在代码重定位时更加方便。以当前程序计数器pc的内容为基址,加上指令给出的一字节补码数(偏移量)形成新的pc值的寻址方式称为相对寻址。隐含引用的专用寄存器是程序计数器(PC),即EA=A+(PC),它是当前PC的内容加上指令字段中A的值。一般来说,地址字段的值在这种操作下被看成2的补码数的值。因此有效地址是对当前指令地址的一个上下范围的偏移,他基于程序的局部性原理。使用相对寻址可节省指令中的地址位数,也便于程序在内存中成块搬动。

  2. 绝对寻址: 绝对寻址是指直接指定目标地址的方法。在绝对寻址中,指令中包含了目标地址的绝对值。当指令执行时,处理器会直接使用指令中指定的地址作为目标地址。绝对寻址通常用于跳转到固定位置的代码或数据,它的主要优势是可以直接指定目标地址,因此适用于较大的代码空间。

        这两种寻址方法各有优劣,并且在不同的情况下有不同的应用场景。相对寻址通常用于控制流程中的短跳转或条件分支,而绝对寻址则更适用于需要直接访问特定位置的数据或代码的情况。在实际编程中,程序员需要根据具体需求选择合适的寻址方法。

3.2 地址重定位的方法

在 U-Boot 中进行地址重定位的方法通常包括以下步骤:

  1. 配置链接地址:

    • 在 U-Boot 的配置文件中,通过设置 CONFIG_SYS_TEXT_BASE 宏来指定链接地址,告诉编译器将代码链接到哪个地址。
  2. 重定位代码:

    • U-Boot 包含专门用于地址重定位的代码,在启动过程中执行。这些代码负责将 U-Boot 程序中的地址映射到实际的内存地址上
  3. 设置链接地址实际硬件地址的映射关系:

    • 根据硬件的实际情况,设置链接地址与实际硬件地址之间的映射关系,确保 U-Boot 中的地址能够正确地映射到内存地址上。
  4. 初始化内存控制器:

    • 在进行地址重定位之前,需要确保内存控制器已经正确初始化,以确保 U-Boot 能够正常地访问内存。
  5. 编写板级初始化代码:

    • 针对特定的硬件平台,可能需要编写板级初始化代码,完成特定的地址重定位操作,例如将外设地址映射到正确的内存地址上。
  6. 测试与调试:

    • 完成地址重定位后,需要进行测试与调试,确保 U-Boot 能够正确执行,并且能够顺利启动操作系统。

通过以上步骤,可以确保 U-Boot 能够在系统启动时正确加载并执行,并顺利启动操作系统。

3.3 uboot拷贝后的地址重定向:所有的链接地址+新的偏移量

通过汇编语言所有所有的所有的链接地址+新的偏移量。

四、跳转到新的uboot地址继续执行

  1. 在跳转到新的位置的地址之前,先无效icache
  2. 根据uboot在RAM中的新的位置,设置向量表入口地址
  3. 在uboot新的位置,继续执行uboot的后续程序:_board_init_r()函数。
  4. 重新使能icache

五、异常向量表定义

start开始:

b reset  =》直接跳转到reset异常处理函数

ldr pc, _undefined_instruction  =》把异常处理函数加载到pc指针

ldr pc,  _software_interrupt =》软中断处理程序加载到pc指针

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/462969.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpingBoot集成Rabbitmq及Docker部署

文章目录 介绍RabbitMQ的特点Rabbitmq术语消息发布接收流程 Docker部署管理界面说明Overview: 这个页面显示了RabbitMQ服务器的一般信息,例如集群节点的名字、状态、运行时间等。Connections: 在这里,可以查看、管理和关闭当前所有的TCP连接。Channels: …

安装snap再安装flutter再安装localsend@Ubuntu(FreeBSD下未成功)

Localsend介绍 localsend是一个跨平台的文件传送软件,可以在Windows、MacOS、Linux、Android和IOS下互相传送文件,只要在同一个局域网即可。 localsend官网:LocalSend 尝试安装localsend,发现需要使用flutter, 安装f…

旋转花键的制造工艺

旋转花键的制造工艺是一门精细的技术,涉及多个步骤和精细的操作,以确保最终产品的质量和性能,下面简单介绍下旋转花键的制造工艺。 1、原材料准备:制造旋转花键的核心是选择合适的材料,根据花键的规格和性能要求&#…

R语言实现中介分析(1)

中介分析,也称为介导分析,是统计学中的一种方法,它用于评估一个或多个中介变量(也称为中间变量)在自变量和因变量之间关系中所起的作用。换句话说,中介分析用于探索自变量如何通过中介变量影响因变量的机制…

相机拍照与摄影学基础

1.相机拍照 相机可能形状和大小不同,但基本功能相同,包括快门速度、光圈和感光度,这些是摄影的通用概念。即使是一次性相机也是基于这三个理念工作的。不同类型相机在这三个概念上的唯一区别是你可以控制这些功能的程度。这三个参数被称为相…

python入门(二)

python的安装很方便,我们这里就不再进行讲解,大家可以自己去搜索视频。下面分享一下Python的入门知识点。 执行命令的方式 在安装好python后,有两种方式可以执行命令: 命令行程序文件,后缀名为.py 对于命令行&…

设计模式在芯片验证中的应用——装饰器

一、装饰器模式 装饰器模式(Decorator)是一种结构化软件设计模式,它提供了一种通过向类对象添加行为来修改类对象的方法,而不会影响同一类的其它对象行为。该模式允许在不修改抽象类的情况下添加类功能。它从本质上允许基类代码对不可预见的修改具有前瞻…

大衍数列-蓝桥杯?-Lua 中文代码解题第2题

大衍数列-蓝桥杯?-Lua 中文代码解题第2题 中国古代文献中,曾记载过“大衍数列”, 主要用于解释中国传统文化中的太极衍生原理。 它的前几项是:0、2、4、8、12、18、24、32、40、50 … 其规律是:对偶数项,是序号平方再除…

如何重置iPhone的网络设置?这里提供详细步骤

前言 本文介绍如何重置iPhone上的网络设置。该信息适用于iPhone 12到iPhone 6以及iOS 14到iOS 8。 如何在iPhone上重置网络设置 采取以下步骤重置iPhone上的网络设置: 1、在iPhone上,打开设置应用程序。 2、单击通用。 3、滚动到屏幕底部&#xff…

SQLiteC/C++接口详细介绍之sqlite3类(十五)

返回目录:SQLite—免费开源数据库系列文章目录 上一篇:SQLiteC/C接口详细介绍之sqlite3类(十四) 下一篇:SQLiteC/C接口详细介绍之sqlite3类(十六) 47.sqlite3_set_authorizer 用法&#xff…

html5使用Websocket

html5使用Websocket 前言1、html5中的websocket2、创建一个 WebSocket 对象3、监听 WebSocket 连接事件4、监听 WebSocket 收到消息事件5、监听 WebSocket 关闭事件6、 监听 WebSocket 出错事件7、发送消息8、整体代码 前言 在即时通讯的交互方式中websocket是一个很使用的方式…

初出茅庐的小李博客之串口屏开发一个音乐控制器UI

串口屏介绍 串口屏通常指的是一种带有串口接口的显示屏,可以通过串口与其他设备进行通信和控制。这种屏幕通常具有独立的控制器和显示功能,可以直接接入主控系统,实现信息的显示和交互。 开发步骤 准备UI素材 准备了100张音量的图标&#x…

麒麟系统Redis7.2哨兵集群部署

redis哨兵集群部署 1、原理 Redis 哨兵模式是指在 Redis 集群中,有一组专门的进程(即哨兵进程)负责监控主节点和从节点的状态,并在发现故障时自动进行故障转移,以保证 Redis 集群的高可用性。 Redis 提供了哨兵的命令,哨兵命令是一个独立的进程,哨兵进程会周期性地向主…

数据结构与算法第八套试卷

1.建立一个长度为n的有序单链表的时间复杂度 0(n^2) 2.哈希算法 key%p:p最好为质数 如果两个关键字的值不等但哈希函数值相等,则称这两个关键字为同义词(正确); 3.二分查找 注意: 二分查找是向下查询…

【蓝桥杯单片机】十四届省赛“重难点”解析(附源码)

【蓝桥杯单片机】十四届省赛“重难点”解析 一、题目难点解析二、易出错点提示三、完整代码链接 笔记包括:①题目难点解析、②易出错点提示、③完整代码链接 注:本文提供的所有代码都是使用第十四届竞赛包完成 ⭐----------系列文章链接----------⭐ 【蓝…

C# 当录入错误的时候,右下角弹窗提示错误信息

做一个textbox录入数字的判断,当录入不是数字的时候右下角弹窗提示 右下角弹窗提示 主要代码如下:判断是否为数字的代码: private void textBox1_KeyPress(object sender, KeyPressEventArgs e) { if(e.KeyChar13) …

计算机网络——物理层(编码与调制)

计算机网络——编码与调制 基带信号和宽带信号编码与调制数字数据编码为数字信号非归零编码归零编码反向不归零编码曼彻斯特编码差分曼彻斯特编码4B/5B编码 数字数据调制为模拟信号模拟数据编码为数字信号模拟数据调制为模拟信号 我们之前讲了物理层的一些基础知识和两个准则&a…

音频的录制及播放

在终端安装好pip install pyaudio,在pycharm中敲入录音的代码,然后点击运行可以在10s内进行录音,录音后的音频会保存在与录音代码同一路径项目中,然后再新建项目敲入播放的代码,点击运行,会把录入的录音进行…

关于UE的相机震动CameraShake

创建CameraShake资源 CameraShake配置是个蓝图类,我们选择创建BlueprintClass,父类选择CameraShakeBase即可。 参数调整 目前主要用到了 LocationAmplitudeMultiplier 1 LocationFrequencyMultiplier 10 RotationAmplitudeMultiplier 1 Rotation…

嵌入式系统和物联网常见的开发板介绍

嵌入式系统和物联网(IoT)领域,开发板是工程师和开发者进行原型设计和项目开发的重要工具。开发板通常集成了微控制器或处理器、内存、输入/输出接口和外设,以便于快速实现功能验证和产品原型。在本教程中,我们将讨论一…