【正点原子STM32MP157 启动篇】(3) STM32MP1 二进制头部信息+Linux 系统启动过程

文章目录

  • [1 概要](#1 概要)
  • [2 STM32MP1 二进制头部信息](#2 STM32MP1 二进制头部信息)
  • [3 STM23MP1 Linux 系统启动过程](#3 STM23MP1 Linux 系统启动过程)
  • [4 总结](#4 总结)
  • [5 其余章节](#5 其余章节)

1 概要

STM32 单片机是直接将程序下载到内部 Flash 中,上电以后直接运行内部Flash 中的程序。STM32MP157 内部没有供用户使用的 Flash,系统都是存放在外部 Flash 里面的,比如 EMMC、NAND等,因此STM32MP157上电以后需要从外部Flash加载程序到内存中。而且STM32MP157支持多种启动方式,这些启动方式都是怎么运行的,这都涉及到 STM32MP1 的启动方式,本章我们就来详细讲解一下 STM32MP1 的启动过程。

本章节将会分为以下5个部分

(1) STM32MP1启动模式 + STM32MP1启动流程详解

(2) Flash设备启动要求

(3) STM32MP1二进制头部信息

(4) STM32MP1 Linux系统启动过程

2 STM32MP1 二进制头部信息

前面讲了 STM32MP1 内部的 ROM 代码会先读取 FSBL 代码,一般是 TF-A 或者 Uboot 的SPL,也可以是 A7 裸机代码。比如 TF-A 我们之间编译生成二进制 bin 文件,但是这个 bin 文件不能直接拿来用,需要在前面添加一段头部信息,这段头部信息也包含了鉴权内容。加入头部信息以后的 FSBL 代码结构如图 5.4.1 所示:

头部信息一共是 256 字节,这 256 个字节的头部信息具体含义如表 5.4.1 所示:

头部信息不需要我们自己手动添加,我们在编译 ST 官方提供的 TF-A 或者 Uboot 的时候会自动添加,因为 ST 提供了个名为"stm32image"的工具专门用于在 bin 文件前面添加头部信息。我们已经从 TF-A 源码中提取出来了 stm32image 并放到了开发板光盘中,路径为:开发板光盘→5、开发工具→2、ST 官方开发工具→stm32image→stm32image.c。在编写 A7 裸机的时候需要自己使用stm32image 工具在 bin 文件前面添加头部信息,stm32image 是在 Ubuntu 下运行的,所以需要先编译,将 stm32image.c 发送到 Ubuntu 下,然后输入如下命令编译:

c 复制代码
gcc stm32image.c -o stm32image

编译成功以后就会生成一个名为 stm32image 的可执行文件,如不 5.4.2 所示:

运行图 5.4.2 编译出来的 stm32image 工具,输入"-s"选项可以查看使用方法,如图 5.4.3所示:

图 5.4.3 可以看出,stm32image 在使用的时候需要搭配一系列的参数:

-s:指定源文件。

-d:生成的目标文件。

-l:加载地址。

-e:入口地址。

-m:主版本号。

-n:次版本号。

大家在开发板光盘里面找到正点原子出厂的 tf-a 固件,路径为:开发板光盘→8、系统镜像→2、出厂系统镜像→1、STM32CubeProg 烧录固件包→tf-a→tf-a-stm32mp157d-atk-trusted.stm32,这个就是加入了头部信息的 TF-A 可执行文件。使用 winhex 软件打开 tf-a-stm32mp157d-atk-trusted.stm32,winhex软件已经放到了开发板光盘中,路径为:开发板光盘→ 3、软件→ winhexv19.7.zip,大家自行安装即可。安装完成以后打开 winhex,然后点击:文件->打开,找到tf-a-stm32mp157d-atk-trusted.stm32 并打开,如图 5.4.4 所示:

图 5.4.4 就是 tf-a-stm32mp157d-atk-trusted.stm32 文件原始数据,其中前 256 个字节就是头部信息。这里我们根据图 5.4.4 中的内容,分析一下 tf-a 头部信息中几个比较重要的参数:

**Magic number:**起始偏移地址为 0,长度为 4 个字节,值依次为:0X53、0X54、0X4D、0X32,合起来就是 0X53544D32,这个就是表 5.4.1 中的魔术数,注意这四个字节的顺序是大端模式。

**Header Version:**起始偏移地址为 72,长度为 4 个字节,也就是图 5.4.4 中第 72~75 这 4 个字节的数据,分别为:0X00、0X00、0X01 和 0X00,此时有的朋友将这四个字节拼起来发现是0X00000100,发现并不是表 5.1.1 中的 0X00010000!这不是弄错了?肯定不是的,整个头部信息中,除了 Magic number 采用大端模式存储以外,其他都是小端模式存储,也就是低字节数据存放在底地址处,高字节数据存放在高字节处。因此 0X00、0X00、0X01 和 0X00 这四个字节的数据正确的拼出结果为 0X00010000。

**Image length:**起始偏移地址为 76,长度为 4 个字节,也就是图 76~79 这 4 个字节的数据,为:0X40、0XB0、0X03 和 0X00,按照小端模式拼起来就是 0X0003B040=241728≈236.1KB,说明此 TF-A 的 bin 镜像大小为 236.1KB。

**Image entry Point:**起始偏移地址为 80,长度为 4 个字节,也就是图 80~83 这 4 个字节的数据,为:0X00、0X60、0XFD 和 0X2F,按照小端模式拼起来就是 0X2FFD6000,说明入口地址为 0X2FFD6000。

**Load address:**起始偏移地址为 88,长度为 4 个字节,也就是图 88~91 这 4 个字节的数据,为:0X00、0X25、0XFC 和 0X2F,按照小端模式拼起来就是 0X2FFC2500,说明加载地址为0X2FFC2500,这个不正是我们前面在 5.2.2 小节中分析的 FSBL 镜像起始地址。 (即偏移了256个字节后的镜像地址,前256字节用于存放相关信息)

**Binary type:**起始偏移地址为 255,也就是最后一个字节,为 0X10,表示当前二进制文件是 TF-A。

3 STM23MP1 Linux 系统启动过程

前面已经对 STM32MP1 的启动流程做了详细的讲解,STM32MP1 是面向 Linux 领域的,因此所有的这些启动过程都是为了启动 Linux 内核。STM32MP1xil 启动 Linux 内核的流程如图5.5.1 所示:

从图 5.5.1 可以看出,STM32MP1 启动 linux 内核一共分为 5 个步骤,我们依次来看一下这五个步骤的内容:

① ROM 代码

前面说了很多次了,这是 ST 自己编写的代码,在 STM32MP1 出厂的时候就已经烧写进去的,不能被修改的。ROM 代码因为保存在 STM32 内部 ROM 里面,因此也就直接简单明了的叫做"ROM 代码"了。它是处理器上电以后首先执行的程序,ROM 代码的主要工作就是读取STM32MP1 的 BOOT 引脚电平,然后根据电平判断当前启动设备,最后从选定的启动设备里面读取 FSBL 代码,并将 FSBL 代码放到对应的 RAM 空间。 (这里的RAM空间是内部的 256KB RAM,因为DDR还没有初始化,所以不能用)

现在很多产品对设备上运行的应用都提出了安全要求,从图 5.5.1 中可以看出,STM32MP1启动Linux 内核的过程是一个链式结构:ROM Code→FSBL→SSBL→Linux kernel→rootfs,系统启动的过程中要保证整个链式结构都是安全的。ROM 代码作为第一链,首先要对 FSBL 代码进行鉴权,同样的,FSBL 以及后面的每一链都要对下一个阶段的镜像进行鉴权,直到设备系统正确启动。

② FSBL

FSBL 代码初始化时钟树、初始化外部 RAM 控制器,也就是 DDR。最终 FSBL 将 SSBL 加载到 DDR 里面并运行 SSBL 代码。

一般 FSBL 代码是 TF-A 或者 Uboot 的 SPL 代码,前面我们说了,也可以将 FSBL 换成我们自己编写的 STM32MP1 A7 内核裸机代码。

③ SSBL

由于 SSBL 代码运行在 DDR 里面,无需担心空间不够,因此 SSBL 代码的功能就可以做的很全面,比如使能 USB、网络、显示等等。这样我们就可以在 SSBL 中灵活的加载 linux 内核,比如从 Flash 设备上读取,或者通过网络下载下载等,用户使用起来也非常的友好。SSBL 一般是 Uboot,用来启动 Linux 内核。

④ Linux 内核

SSBL 部分的 Uboot 就一个使命,启动 Linux 内核,Uboot 会将 Linux 内核加载到 DDR 上并运行**(加载过程可以通过网络系统或者是其他方式,因为SSBL已经初始化了很多外设功能等)**。Linux 内核启动过程中会初始化板子上的各种外设。

⑤ Linux 用户空间

系统启动的时候会通过 init 进程切换到用户空间,在这个过程中会初始化根文件系统里面的各种框架以及服务。

4 总结

本章节介绍了STM32MP1 二进制头部信息+Linux 系统启动过程。

5 其余章节

【正点原子STM32MP157 启动篇】(1)启动模式 + 启动流程详解(含UART 启动)
【正点原子STM32MP157 启动篇】(2)Flash 设备启动要求
【正点原子STM32MP157 启动篇】(3) STM32MP1 二进制头部信息+Linux 系统启动过程

相关推荐
minji...1 小时前
Linux 进程控制(二) (进程等待wait/waitpid)
linux·运维·服务器·数据结构
IT 乔峰1 小时前
Apache工作原理详细说明
linux·apache
fufu03111 小时前
Linux环境下的C语言编程(三十六)
linux·c语言·开发语言·数据结构·算法
richxu202510011 小时前
嵌入式学习之路>单片机核心原理篇>(5)串口通信核心原理
单片机·嵌入式硬件·学习
小嘟嘟131 小时前
第2章 Shell 变量与参数传递:3 种定义方式 + 避坑指南
linux·运维·shell
小鱼儿电子1 小时前
56-基于LoRa的水质监测系统设计与实现
stm32·单片机·嵌入式硬件·lora·腾讯云平台
looking_for__1 小时前
【Linux】进程概念
linux
猫猫的小茶馆1 小时前
【ARM】eclipse 中创建汇编工程
c语言·汇编·arm开发·stm32·单片机·嵌入式硬件·eclipse
Eric.Lee20211 小时前
ubuntu系统在bashrc文件中对conda进行启用设置
linux·运维·python·ubuntu·conda