IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 聊聊SOC启动(一)armv8启动总体流程 -> 正文阅读

[嵌入式]聊聊SOC启动(一)armv8启动总体流程

1?为什么需要引导程序

????在遥远的单片机时代,嵌入式设备功能比较单一,每个设备只需要执行一件简单的任务,因此在系统初始化完成后,程序就运行在一个大循环中,此时,系统启动流程和功能代码并没有很严格的区分。
????随着CPU处理能力和芯片制造工艺的不断提升,高性能芯片逐渐演进成了SOC,单颗芯片上除了CPU外还会集成大量不同功能的IP核,如中断控制器、DSP、GPU、总线控制器、视频处理和编码模块、以及电源管理模块等。为了更好地管理这些软硬件资源,以及为上层用户提供统一的服务和接口,SOC上一般都需要运行操作系统。系统引导程序主要功能就是初始化系统的软硬件状态,为操作系统提供一个合适的软硬件环境,以及加载和启动操作系统映像。

2?软硬件假定

????为了更好地描述启动流程的细节,后面的章节我们将选取一种主流的硬件平台和软件框架做讨论。硬件平台选用qemu的virt machine平台,其主要硬件配置如下:
(1)cpu为armv8架构的cortex-a53核
(2)中断控制器为gicv3
(3)ROM空间128k
(4)SRAM空间384k
(5)DDR内存空间3G
(6)支持semihosting半主机模式
????选用qemu是因为其是一种硬件模拟器,可以通过软件模拟的方式实现不同硬件平台的功能,如可以在X86主机上模拟armv8架构的硬件,从而可以在不需要target硬件的情况下进行相关功能的调试。qemu调试环境的搭建可参考以下的链接:
从0开始搭建qemu调试环境
其软件架构如下:
(1)初始启动流程使用arm ATF
(2)内核启动流程使用uboot
(3)内核为linux

3?启动阶段

????Armv8的启动流程包含多个阶段,典型地有BL1、BL2、BL31、BL32、BL33,根据需求的不同,这些阶段可以适当地裁剪或添加。为了方便描述,后面我们的讨论将基于以上这些官方定义的标准阶段,它们的源码会被编译成独立的启动镜像,并被保存到特定的存储介质中。由于一般的存储介质(如spi flash、nand flash、emmc、ssd等)都不支持代码的直接执行,因此需要在启动时先将镜像加载到可直接执行代码的存储介质,如SRAM或DDR中,然后运行相关代码。其典型的加载流程如下:
在这里插入图片描述

  1. BL1是启动的第一阶段,该镜像必须要存储在可直接执行的介质中。若芯片支持XIP启动方式,其可被存储在片外可直接执行的介质中(如norflash)。若不支持XIP,则需要存储在芯片的片内ROM中,此时在芯片出厂后该部分代码就将被固化,后续再也不能被修改和升级。若芯片要支持安全启动,则需要将bootrom作为启动时的信任根,此时除调试阶段外,SOC必须禁用XIP。关于安全启动我们将在后面专门介绍
  2. BL2镜像由BL1加载,此时DDR还没有被初始化,因此它需要被加载到片内的SRAM中执行,一般在这个阶段会完成DDR的初始化,因此后面的镜像都可以被加载到DDR中。从上图可知,BL31、BL32和BL33都是由BL2加载的,其中BL31和BL32是可选的,若系统不支持TRUST OS,则可去掉BL32,若不支持EL3异常等级及secure monitor,则可去掉BL31
  3. BL33一般指uboot,一般通过它最终启动操作系统内核

Armv8架构典型的启动流程如下:
在这里插入图片描述
????以上流程中我们假定系统支持的最高异常等级为EL3,且支持secure monitor和TRUST OS,同时BL2运行在secure EL1,BL33运行在non secure EL1状态
(1)由于armv8架构规定,arm核复位后默认会进入当前系统支持的最高异常等级,因此BL1运行在EL3,它执行完成后会通过异常返回ERET的方式跳转到BL2
(2 - 3)BL2执行完成后需要跳转到BL31,由于BL31运行在EL3异常等级,而BL2根据需求不同可能运行于secure EL1或EL3。当BL2运行于EL3时可直接通过ERET方式跳转到BL31中,但若其运行在secure EL1时,则只能通过smc异常触发进入EL3异常等级。显然,此时BL31由于尚未设置其自身的smc异常处理程序而无法直接处理该异常,因此,为了完成跳转流程,BL1需要先代理该异常的处理。因此BL1在退出之前先设置smc异常处理函数,BL2触发smc启动BL31时,BL1捕获该异常并根据BL2传入的参数设置BL31的入口地址和系统初始状态,并通过ERET跳转到BL31的入口地址处执行
(4)BL32阶段会运行TRUST OS,它运行于secure EL1异常等级,BL31可根据其镜像加载信息设置入口地址以及其它状态,并完成跳转
(5 - 6)BL32加载完成后将通过SMC返回到BL31,然后由BL31跳转到non secure EL1以执行BL33

4?重要寄存器介绍

????除了硬件默认设置的寄存器值之外,其它寄存器都需要在系统启动时初始化,有些重要的寄存器在系统启动流程中会影响系统的运行行为,因此下面对它们做一简单介绍。由于armv8很多寄存器都为不同异常等级提供了对应的bank定义,而其含义比较类似,为了方便介绍,后面介绍中我们都以EL3等级下的定义为例

4.1?SCTLR_EL3寄存器

????该寄存器是系统控制寄存器,用于提供系统顶级的状态控制信息,其定义如下图:
在这里插入图片描述
其每个bit的含义可参考armv8参考手册,下面简单介绍一些该寄存器的重要控制位:
(1)M[0]:用于设置系统是否使能EL3下的MMU,若其为1使能MMU,否则禁止MMU
(2)A[1]:用于设置是否使能El3下的对齐检查,若其为1使能对齐检查,否则进制对齐检查
(3)C[2]:用于设置EL3下的数据cache,若其为1使能数据cache,否则禁止数据cache
(4)I[12]:用于设置EL3下的指令cache,若其为1使能指令cache,否则禁止指令cache
(5)WXN[19]:用于设置EL3下写权限内存是否不可执行,若其为1则含有写权限的内存不具有执行权限,否则没有副作用
(6)EE[25]:用于设置EL3的大小端,若其为0数据为小端格式,否则为大端格式

4.2?SCR_EL3寄存器

????该寄存器用于设置secure相关的属性,且在其它异常等级下不存在bank值,而是用于控制全局状态的。因此在不同异常等级切换之前,需要先将该寄存器的值设置为目标异常等级所需的值,如从EL3切换到non secure EL1,则需要将其设置为non secure EL1相关的配置。寄存器的定义如下:
在这里插入图片描述
其重要的bit位如下:
(1)NS[0]:设置EL0- EL2的secure状态,若其为0表示secure状态,为1表示nonsecure状态
(2)IRQ[1]:用于设置irq中断路由,当其为1时,irq中断都被路由到EL3处理,当其为0时,若当前运行在EL3下irq中断不触发,否则irq中断路由到当前运行的异常等级,而不路由到EL3
(3)FIQ[2]:用于设置fiq中断路由,当其为1时,fiq中断都被路由到EL3处理,当其为0时,若当前运行在EL3下fiq中断不触发,否则fiq中断路由到当前运行的异常等级,而不路由到EL3
(4)EA[3]:用于设置外部abort和serror路由,当其为1时,外部abort和serror都被路由到EL3处理,当其为0时,若当前运行在EL3下serror不触发,外部abort路由到EL3,否则外部abort和seeror都路由到当前运行的异常等级,而不路由到EL3
(5)SMD[7]:用于设置是否禁用smc异常,若其为1禁用smc,否则使能smc
(6)HCE[8]:用于设置是否禁用hvc异常,若其为1使能hvc,否则禁用hvc
(7)ST[11]:用于设置secureEL1是否将counter的securetimer寄存器访问路由到EL3。若其为1,secureEL1访问counter的securetimer寄存器将会路由到EL3,否则该bit被忽略
(8)TWI[12]:用于设置EL0 – EL2执行WFI时是否陷入EL3。若其为1则任何WFI操作都会陷入EL3,否则该bit被忽略
(9)TWE[13]:用于设置EL0 – EL2执行WFE时是否陷入EL3。若其为1则任何WFE操作都会陷入EL3,否则该bit被忽略

4.3?SP_EL0和SP_EL3寄存器

????Armv8包含SP_EL0和SP_ELx两种栈指针寄存器,其中SP_ELx包含SP_EL1 – SP_EL3三个bank寄存器。SP_ELx寄存器为异常栈指针寄存器,即cpu进入异常后将会切到捕获该异常对应EL的SP_ELx寄存器,如陷入smc异常时栈指针寄存器将会切换到SP_ELx。SP_EL0可以被任何异常等级使用,因此在EL1 – EL3中除了异常处理流程外,执行其它代码逻辑时一般都会切换为SP_EL0栈指针。

4.4?SPSR_EL3和ELR_EL3寄存器

????通过中断或异常陷入EL3时,陷入异常之前的PSTATE寄存器将会被保存到SPSR_EL3寄存器中,当异常处理完成后通过ERET指令返回断点处继续执行之前,将用该寄存器的值恢复PSTATE的值。ELR_EL3与SPSR_EL3类似,指示在异常陷入之前该寄存器将用于保存返回地址,异常处理完成后则将该返回地址恢复到PC中。

5?镜像跳转方式

????前面我们聊到镜像跳转时可能需要使用到ERET或SMC指令,下面我们再看下跳转时的细节

5.1?Smc异常处理流程

????smc是armv8支持的异常跳转指令,它用于程序从EL1或EL2跳转到EL3异常等级。其跳转流程如下:
在这里插入图片描述
????以atf的BL1 smc处理流程为例,EL1调用者通过smc指令陷入到EL3异常,此后CPU将跳转到EL3异常向量表的vector_entry SynchronousExceptionA64入口处,该函数解析esr_el3寄存器的异常原因,若其为smc异常,就跳转到smc处理函数smc_handler64中。smc_handler64解析通过x0 – x7寄存器传入的参数获取smc命令类型,执行特定的命令处理函数,并通过寄存器x0 – x4返回处理结果。对于异常向量表跳转入口选择原则可参考以下博文:
Armv8中断路由机制

5.2?ERET跳转流程

????ERET指令用于从异常处理流程中返回,在介绍异常返回流程之前,我们先看一下armv8异常跳转的流程。Armv8触发异常或中断后硬件将会执行以下操作:
(1)将PSTATE寄存器的内容保存到SPSR_ELx中,其中x表示异常进入的异常等级,如smc异常将会陷入EL3,因此相应的寄存器就为SPSR_EL3
(2)将异常处理完成后需要返回的地址保存在ELR_ELx中
(3)设置中断和异常掩码DAIF,以关闭所有中断和异常
(4)若异常是同步异常或SError中断,异常状态信息将被保存在ESR_ELx中,该信息可用于分析异常发生的原因
(5)若异常为指令异常、数据异常或对齐错误等,则触发异常对应的内存地址将被保存到FAR_ELx寄存器中
(6)栈指针切换为目标异常等级的栈指针寄存器SP_ELx
(7)程序跳转到对应的异常处理入口,执行异常处理程序
????在异常执行完成后,可通过ERET指令返回被异常中断程序的断点处继续执行,该指令将使硬件执行以下操作:
(1)用SPSR_ELx寄存器的内容恢复PSTATE寄存器
(2)用ELR_ELx寄存器的内容恢复PC值
????从以上流程可以看到,执行ERET指令后程序的执行流将由SPSR_ELx和ELR_ELx决定。因此,我们在执行镜像之间的跳转,只要在ERET之前将ELR_ELx设置为待跳转镜像的入口地址,并设置正确的SPSR_ELx即可完成

6?内存规划

6.1?内存规划原则

????嵌入式系统的内存一般包含ROM、SRAM和DDR,其中ROM和SRAM位于SOC片内,DDR位于芯片外部。它们的特点如下:
(1)ROM中的内容断电后不会消失,不仅可用于代码执行,还可以用于镜像存储,但其只有只读权限
(2)SRAM和DDR中的内容在断电后都会消失,因此只能被用于代码的动态执行,而不能用于镜像存储
(3)ROM和SRAM都是直接连接总线上,系统上电后即可直接执行。而DDR需要通过DDR phy和DDR controller连接到总线上,因此使用之前必须要先对其执行初始化操作
????根据上述各种内存的特点和前面镜像加载启动流程的需求,在内存规划中我们需要考虑以下几个问题:
(1)由于BL1需要固化到ROM中,且是系统最先执行的,因此ROM地址需要被映射到cpu的重启地址处
(2)由于ROM是只读的,BL1镜像除了代码段和只读数据段之外还包含可读写数据段,这部分数据在BL1启动时需要从ROM重定位到SRAM中
(3)由于BL1被固化在ROM中,芯片出产后就不能更改,因此DDR初始化代码不能集成到BL1中。故BL2需要被加载到SRAM中执行,且在BL2中执行DDR初始化流程
(4)BL2之后的其它镜像既可以运行于SRAM中,也可以运行于DDR中
(5)从前面的镜像启动流程可知,若BL2运行于secure EL1下,当其执行完成后,需要通过smc再次陷入BL1去执行BL31流程,因此BL2和BL1的地址不能有重叠
(6)BL31除了执行启动流程外,在系统运行过程中还会以secure monitor的方式驻留,为normal空间的smc异常提供服务历程,以及为normal os和trust os之间提供消息转发、中断路由转发等功能。因此,BL31镜像需要永久驻留内存,在系统启动完成后不能被回收
(7)与BL31类似,BL32在启动后需要驻留内存为系统提供安全相关服务,因此为其所分配的内存也不能被回收
(8)除此之外,BL1、BL2和BL33(一般为uboot)的内存在系统启动完成后都可以被释放给操作系统使用

6.2?qemu virt平台内存规划示例

根据以上内存规划原则,qemu virt machine各启动阶段的内存规划如下:

类型起始地址结束地址长度是否secure内存作用
ROM0x000000000x00020000128kYesBL1(bootrom)
SRAM0x0e04e0000x0e06000072kYesBl1(rwdata)
SRAM0x0e0000000x0e0010004kYesSharedram
SRAM0x0e01b0000x0e040000148kYesBL2
SRAM0x0e0400000x0e060000128kYesBL31
SRAM0x0e0010000x0e040000252kYESBL32
DDR0x600000000x1000000002.5GNOBL33
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-18 17:49:03  更:2022-05-18 17:49:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:45:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码