1)实验平台:正点原子STM32MP157开发板
2)购买链接:https://item.taobao.com/item.htm?&id=629270721801
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-318813-1-1.html
4)正点原子官方B站:https://space.bilibili.com/394620890
5)正点原子STM32MP157技术交流群:691905614
在上一章已经学会了如何搭建STM32MP157芯片的开发环境,为了方便书写,本教程把STM32MP157简称为MP1。在这个嵌入式的高速发展时代,智能设备在各个领域扮演重要的角色,大量的嵌入式设备使用都是ARM为核心的芯片,为了保证安全ARM推出了Arm Trusted Firmware的可信固件,简称TF-A。它是一个开源的软件,最早是用在Armv8-A,ST也在MP1里面使用到了TF-A。它的作用就是隔离硬件,为硬件提供一个安全环境并且提供安全服务,本章我们先来体验一下TF-A。
6.1 你好TF-A
时至今日,智能手机、物联网飞速发展,智能手机里面保存了我们的指纹、Face ID(3D人脸信息)、虹膜、银行卡密码等重要信息。而物联网更是与我们的生活息息相关,比如家用智能摄像头,一旦安全防线被突破,那么我们的生活就会毫无遮拦的暴露给整个世界。因此智能设备的安全问题就成了半导体行业亟待解决的问题,ARM为此提供了TrustZone解决方案,TrustZone将CPU的工作状态分为了Secure World(安全世界)和Normal World(非安全世界),涉及到安全相关的内容运行在安全世界,比如指纹、密码等,其他的操作都在非安全世界运行,比如应用程序。TrustZone是一种硬件解决方案,这里就不深究了(TrustZone相关的安全知识本身就是一门课程)。
6.1.1 系统源码获取
与之对应的,我们需要一套软件来配合TrustZone,TF-A应运而生,TF-A全称是Arm Trusted Firmware,有些资料也叫做ATF,一般中文资料叫做ARM可信固件。MP1内部集成了TrustZone,因此ST也提供了TF-A相关源码,TF-A会先初始化DDR等外设,把Uboot从Flash(NAND、NOR FLASH、SD、MMC 等)拷贝到 DDR 中。我们不可能直接去官方网站下载TF-A的源码,这样的开发难度太大,半导体厂商都会从TF-A官网下载源码,然后修改适配自己的芯片,把自家的芯片加进去。我们在实际项目开发中直接使用半导体原厂给提供的TF-A即可。ST官方TF-A、uboot、kernel等源码下载链接为:https://my.st.com/content/my_st_com/en/products/embedded-software/mcu-mpu-embedded-software/stm32-embedded-software/stm32-mpu-openstlinux-distribution/stm32mp1dev.html,打开以后如图6.1.1.1所示:
图6.1.1.1 MP1系统源码下载
图6.1.1.1中的STM32MP1Dev就是官方的源码包,里面包括TF-A,uboot,kernel等源码,点击“Get Software”下载整个系统源码。这里我们已经下载下来并放到了开发板光盘中,路径为:开发板光盘1、程序源码5、ST官方原版Linux源码en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz。
在Ubuntu中创建一个目录存放源码,然后将ST官方系统源码发送到Ubuntu中。这里我在前面创建的“linux”目录下新建一个名为“atk-mp1”的目录存放所有源码,命令如下:
cd linux/ //进入linux目录
mkdir atk-mp1 //创建atk-mp1目录
用FileZilla把将ST官方源码压缩包en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz拷贝到“atk-mp1”目录下。拷贝结果如图.1.1.2所示:
图6.1.1.2 拷贝官方的SDK
解压图6.1.1.2中的压缩包,命令如下:
tar -xvf en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz
解压完成以后会得到一个名为“stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24”的文件夹,结果如图6.1.1.3所示:
图6.1.1.3 解压官方的SDK包结果
进入stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi目录下,里面就是uboot、optee、tf-a、kernel源码,如图6.1.4所示:
图6.1.1.4 系统源码
图6.1.1.4中这5个源码文件夹的含义如表6.1.1.1所示:
文件夹 描述
u-boot-stm32mp-2020.01-r0 uboot源码,版本号为2020.01
linux-stm32mp-5.4.31-r0 linux源码,版本号为5.4.31
tf-a-stm32mp-2.2.r1-r0 tf-a源码,版本号为2.2,我们用到的
tf-a-stm32mp-ssp-2.2.r1-r0 tf-a源码,ssp全称为secure secret provisioning, 安全相关的内容,本教程用不到。
optee-os-stm32mp-3.9.0.r1-r0 optee系统源码,版本为3.9.0,本教程用不到
表6.1.1.1 系统源码
表6.1.1.1中共有5个源码,本教程就用到前三个:u-boot-stm32mp-2020.01-r0、linux-stm32mp-5.4.31-r0和tf-a-stm32mp-2.2.r1-r0。也就是TF-A、Uboot和Linux Kernel。传统的linux学习中不需要TF-A的,只需要uboot和Linux Kernel,但是MP1带有安全硬件,因此加入了TF-A,加入的TF-A对于linux学习极其不利。为此我们建议过ST修改系统源码,允许客户不使用TF-A,就像传统的嵌入式linux一样,只用uboot和linux kernel。不过在编写本教程的时候并未看到ST提供这样的源码,所以我们还是要移植TF-A到开发板上的。
首先TF-A并不是ST自己做的,TF-A有自己的官方组织,ST只是将自己的MP1芯片移植到了TF-A上,表6.1.1.1中的tf-a-stm32mp-2.2.r1-r0就是ST自己修改后的TF-A源码,我们作为MP1芯片的使用者,直接使用ST修改后的TF-A源码即可,包括uboot、linux kernel都是这样的。
tf-a-stm32mp-2.2.r1-r0支持ST所有的MP1芯片,也支持各种启动方式,例如:EMMC、NAND、NOR FLASH 等等。tf-a-stm32mp-2.2.r1-r0里面包含了ST自家所有的MP1评估板,正点原子的STM32MP157开发板参考了ST官方的STM32MP157C-EV1开发板,因此,后续的移植都是以STM32MP157C-EV1开发板为蓝本,在此基础上进行修改。
tf-a-stm32mp-2.2.r1-r0目录文件如图6.1.1.5所示:
图6.1.1.5 tf-a源码
图6.1.1.5中一共有5个文件,这五个文件的含义如表6.1.1.2所示:
文件/文件夹 描述
0001-st-update-v2.2-r2.0.0.patch TF-a补丁文件。
Makefile.sdk 编译TF-A用的Makefile
README.HOW_TO.txt ST官方TF-A的编译文档,编译方法看此文档即可。
series 存放补丁名字的文件
tf-a-stm32mp-2.2.r1-r0.tar.gz TF-A的源码压缩包
表6.1.1.2 tf-a源码文件含义
6.1.2 TF-A源码打补丁
图6.1.1.5中的TF-A源码还不能直接使用,需要对其打补丁。前面我们说了,ST也是在TF-A官方的源码上将自己的MP1系列芯片添加进去的,因此必然涉及到对官方TF-A源码的修改,修改的部分就是“补丁”,补丁文件后缀为.patch,表6.1.1.2中的0001-st-update-v2.2-r2.0.0.patch就是ST为TF-A官方源码做的补丁文件,补丁文件里面描述了修改源码中的哪些文件,应该添加或删除哪些代码或文件,打完补丁后的TF-A才是我们真正需要的。因此,打补丁需要两个文件:
①、补丁文件,在此处就是0001-st-update-v2.2-r2.0.0.patch。
②、需要打补丁的源文件,在此处就是tf-a-stm32mp-2.2.r1-r0.tar.gz。
我们需要先解压tf-a-stm32mp-2.2.r1-r0.tar.gz,如图如下命令:
tar -vxf tf-a-stm32mp-2.2.r1-r0.tar.gz
解压完就是会在当前目录下生成“tf-a-stm32mp-2.2.r1”目录,如图6.1.2.1所示:
图6.1.2.1 解压TF-A的官方源码
接下来就是给TF-A源码打补丁,在解压好的TF-A的目录下运行以下命令:
cd tf-a-stm32mp-2.2.r1 //进入TF-A源码
for p in ls -1 ../*.patch
; do patch -p1 < $p; done //打补丁
上面这条命令的意思是把上一层目录下的所有“.patch”后缀的文件都通过patch命令打补丁到TF-A的源码目录,在这里就是将001-st-update-v2.2-r2.0.0.patch这个补丁打入到TF-A源码里面,过程如图6.1.2.2所示:
图6.1.2.2 TF-A的源码打补丁
由于ST官方源码目录太长,为了方便调试,在atk-mp1目录下创建一个名为“tf-a”的子目录,然后就打完补丁后的tf-a-stm32mp-2.2.r1-r0目录下的所有文件都拷贝到tf-a下,命令如下:
cd tf-a-stm32mp-2.2.r1-r0/
cp * /home/zuozhongkai/linux/atk-mp1/tf-a/ -rf
拷贝完成以后的tf-a目录如图6.1.2.3所示:
图6.1.2.3 tf-a目录
图6.1.2.3中的tf-a-stm32mp-2.2.r1就是我们后面要使用的,打完补丁后的TF-A源码。
6.1.3 创建VSCode工程
为了方便阅读TF-A源码,我们可以创建一个VSCode工程,然后打开VSCode,点击:文件->打开文件夹,选中图6.1.2.3中打完补丁后的tf-a-stm32mp-2.2.r1-r0文件夹,打开以后的VSCode如图6.1.3.1所示:
图6.1.3.1 TF-A的VSCode工程
图6.1.3.1中左侧的资源管理器就是TF-A的工程目录结构。最后我们保存一下工作区,点击:文件->将工作区另存为…”,打开保存工作区对话框,将工作区保存到 TF-A 源码根目录下,设置文件名为“tf-a”,如图6.1.3.2所示:
图6.1.3.2 TF-A源码工作区创建
保存以后就会在TF-A源码根目录下多出一个名为“tf-a.code-workspace”的文件,这样一个完整的VSCode工程就建立起来了。
6.2 编译和烧录TF-A
6.1小节我们得到的TF-A源码是ST提供的,这个TF-A肯定是不能直接在正点原子的STM32MP157开发板上运行的,需要移植和修改。但是在正式移植TF-A之前我们要先体验一下如何编译TF-A,并烧写到正点原子的STM32MP157开发板上,这里我们直接编译正点原子已经修改好的TF-A。
6.2.1 stm32wrapper4dbg工具安装
我们在编译TF-A或者Uboot的时候需要用到stm32wrapper4dbg这个工具,否则编译会报错。ST提供了这个工具的源码,我们需要在Ubuntu下编译并安装这个源码,源码的下载地址为:https://github.com/STMicroelectronics/stm32wrapper4dbg,这个我们已经下载下来并放到了开发板光盘中,路径为:开发板光盘5、开发工具 stm32wrapper4dbg-master.zip。将源码压缩包拷贝到Ubuntu下,然后进行解压,命令如下:
unzip stm32wrapper4dbg-master.zip //解压
解压完成以后就会得到一个名为“stm32wrapper4dbg-master”的文件夹,进入到此文件夹里面,然后编译并安装,命令如下:
cd stm32wrapper4dbg-master //进入到此文件夹
make //编译
编译完成以后就会得到一个名为“stm32wrapper4dbg”的工具,如图6.2.1.1所示:
图6.2.1.1 编译得到的工具
图6.2.1.1中的“stm32wrapper4dbg”就是我们要的工具,将图6.2.1.1中编译出来的stm32wrapper4dbg工具拷贝到Ubuntu的/usr/bin目录下,命令如下:
sudo cp stm32wrapper4dbg /usr/bin
拷贝完成以后就可以直接在终端中使用stm32wrapper4dbg这个工具了,输入如下命令查看帮助信息:
stm32wrapper4dbg -s
如果输出如图6.2.1.2所示内容就说明stm32wrapper4dbg工具安装成功:
图6.2.1.2 stm32wrapper4dbg帮助信息
6.2.2 编译正点原子官方的TF-A
1、准备正点原子出厂TF-A源码
首先安装设备树编译相关命令,输入如下命令:
sudo apt-get install device-tree-compiler
在Ubuntu的atk-mp1目录下新建一个名为“alientek_tf-a”的子目录,然后把正点原子修改好TF-A源码拷贝到alientek_tf-a这个目录下。正点原子修改好的TF-A源码已经放到了开发板光盘中,路径为:开发板光盘1、程序源码 1、正点原子Linux出厂系统源码 tf-a-stm32mp-2.2.r1-g463d4d8-v1.0.tar.bz2。拷贝完成以后解压,输入如下命令:
tar -xvf tf-a-stm32mp-2.2.r1-g463d4d8-v1.0.tar.bz2
解压完成以后 alientek_tf-a文件夹内容如图6.2.1.1示:
图6.2.1.1 解压好的TF-A
图6.2.1.1中的‘tf-a-stm32mp-2.2.r1’就是正点原子针对自己的STM32MP157开发板修改过的TF-A源码,Makefile.sdk是一会编译TF-A要用到的Makefile。
2、修改Makefile.sdk
首先我们要知道,TF-A是有自己的Makefile文件的,而且真正编译的时候也是要用TF-A自己的Makefile。Makefile.sdk是ST自己编写的,也是我们一会编译TF-A的时候要用到的,Makefile.sdk里面主要定义了一些编译属性,比如要使用的交叉编译器、编译的一些选项等等,Makefile.sdk最终会调用TF-A内部的Makefile来编译TF-A。默认情况下Makefile.sdk里面使用的是ST官方的交叉编译器(arm-ostl-linux-gnueabi-gcc),但是我们本教程用的是通用交叉编译器arm-none-linux-gnueabihf-gcc,因此我们需要Makefile.sdk,将交叉编译器改为我们目前所使用的。打开Makefile.sdk,然后找到CROSS_COMPILE,将其改为“arm-none-linux-gnueabihf-”,如图6.2.1.2所示:
图6.2.1.2 修改后的Makefile.sdk
3、编译TF-A
准备工作都就绪以后就可以编译正点原子出厂TF-A了,进入到图6.2.1.1中的tf-a-stm32mp-2.2.r1目录里面,然后运行执行如下命令编译TF-A:
cd tf-a-stm32mp-2.2.r1/ //进入到正点原子出厂TF-A的源码目录
make -f …/Makefile.sdk all //编译TF-A
‘-f’的意思是重新指定Makefile,在这里就是指定图6.2.1.1中的Makefile.sdk,编译成功会出现如图6.2.1.3所示:
图6.2.1.3 TF-A编译成功
编译完成以后会在上一层目录,也就是alientek_tf-a下生成一个名为“build”的目录,如图6.2.1.4所示:
图6.2.1.4 build目录
进入到图6.2.1.4中的build目录下,一共有三个子目录:optee、serialboot和trusted,如图6.2.1.5所示:
图6.2.1.5 build子目录
我们只关注trusted目录下的文件,此目录下就保存了MP1所有型号的TF-A固件,包括正点原子开发板所使用的tf-a-stm32mp157d-atk-trusted.stm32,如图6.2.1.6所示:
图6.2.1.6 编译得到的正点原子157开发板所使用的TF-A固件
6.2.3 TF-A烧录到EMMC
使用STM32CubeProgrammer将TF-A烧写到开发板里面,STM32CubeProgrammer支持通过UART、USB、STLINK来烧写系统,本教程全部采用USB烧写,也就是通过开发板上的USB_OTG口来烧写系统。
1、准备烧写的材料
我们在Windows下通过STM32CubeProgrammer来烧写TF-A,新建一个目录来存放烧写镜像文件,比如我这里创建一个名为“images”的目录。然后将开发板光盘里面的这两个文件先拷贝到images目录下:
①、tf-a-stm32mp157d-atk-serialboot.stm32,由正点原子提供。路径:开发板光盘8、系统镜像2、出厂系统镜像 1、STM32CubeProg烧录固件包tf-a tf-a-stm32mp157d-atk-serialboot.stm32。
②、u-boot.stm32,由正点原子提供。路径:开发板光盘8、系统镜像2、出厂系统镜像 1、STM32CubeProg烧录固件包ubootu-boot.stm32拷贝到images文件夹里。
拷贝完成以后images如图6.2.3.1所示:
图6.2.3.1 拷贝文件到images
最后就是前面编译出来,真正要烧写的tf-a-stm32mp157d-atk-trusted.stm32,通过FileZilla将Ubuntu里面的tf-a-stm32mp157d-atk-trusted.stm32发送到images目录下,完成以后结果如图6.2.3.2所示:
图6.2.3.2 最终的材料
大家可能会有疑问,tf-a-stm32mp157d-atk-trusted.stm32是我们编译出来的TF-A,这个没啥说的,但是,另外两个是干啥的呢?这个就和STM32CubeProgrammer这个软件的设计以及烧写过程有关了。以下内容为作者实际测试研究发现的,ST并没有给出真正的解释,可能存在错误:
tf-a-stm32mp157d-atk-serialboot.stm32中间有个“serialboot”,也就是串行BOOT,说明是和启动有关的。此固件用来初始化USB、DDR等外设,DDR初始化了以后就可以运行uboot了,为什么要运行uboot呢?因为uboot里面会初始化EMMC、NAND等外设,而且uboot会提供很强大的EMMC操作指令。也就是说,启动uboot的目的就是为了操作EMMC、NAND,这样就可以在uboot里面通过相关的命令将tf-a-stm32mp157d-atk-trusted.stm32写到EMMC或者NAND里面。这就是需要tf-a-stm32mp157d-atk-serialboot.stm32和u-boot.stm32的原因,这两个文件存在的目的就是为了将tf-a-stm32mp157d-atk-trusted.stm32烧写到EMMC、NAND、SD卡里面。
2、准备FlashLayout
图6.2.3.2中有三个文件,STM32CubeProgrammer如何使用这三个文件,应该放到哪个地方,如果烧写的话要烧写到EMMC的哪个地址区域。这些都要通过STM32CubeProgrammer脚本文件来定义,STM32CubeProgrammer脚本文件后缀为.tsv,ST官方也叫做FlashLayout。这里我们直接在正点原子提供的tsv文件基础上修改,将开发板光盘8、系统镜像2、出厂系统镜像1、STM32CubeProg烧录固件包flashlayoutatk_emmc-stm32mp157d-atk-qt.tsv拷贝到前面的images前目录下,然后将其重命名为“tf-a.tsv”,完成以后images目录如图6.2.3.3所示:
图6.2.3.3 最终的images目录
.tsv是文本格式的,很容易阅读,关于.tsv语法的详细讲解,请参考:https://wiki.st.com/stm32mpu/wiki/STM32CubeProgrammer_flashlayout。用Notepad++软件(没有的话自行安装,这是个免费软件,安装很简单)打开图6.2.3.3中的tf-a.tsv,打开以后默认如图6.2.3.4所示:
图6.2.3.4 tf-a.tsv内容
tsv对格式有要求,直接看图6.2.3.4是看不出来啥的,必须要设置一下Notepad++软件,点击视图显示符号显示空格与制表符, 设置好以后的tf-a.tsv如图6.2.3.5所示:
图6.2.3.5 显示空格与制表符
从图6.2.3.5中可以看出, tf-a.tsv文件就会发现多了黄色的箭头,这些箭头代表是TAB键, TAB键越多黄色箭头就越长,如果用空格键的话就会显示‘.’。tsv语法要求只能用TAB键,不能用空格!以‘#’开头为注释,所以图6.2.3.5中第一行为注释。
我们把tf-a.tsv文件内容修改成如图6.2.3.6所示:
图6.2.3.6 修改后的tf-a.tsv文件
图6.2.3.6中一共有5行,第1行为注释,一共9列,这9列的含义如表6.2.3.1所示:
域 作用
Opt 选项字段,可以设置为“-”、“P”、“D”或“E”
Id 会根据这个id来决定烧写分区
Name 分区名字
Type 制定烧写的类型,仅uboot使用。
Device 指定烧写的设备类型与编号,比如emmc0、emmc1、nand0等,如果opt为‘-’,那么此字段就为none
Offset 分区的起始位置,如果为“boot1”表示EMMC的第一个分区,如果为“boot2”就表示EMMC第二个分区。如果是数字就表示需要偏移的字节数。
Binary 要烧录的文件
表6.2.3.1 tf-a.tsv的配置解析
接下来详细讲解一下表6.2.3.1中的这7个配置:
①、Opt域
Opt是第一个项,此选项通过‘-’、‘P’、‘D’和‘E’这四个字符定义操作方法,首选的是‘-’和‘P’。
· ‘-’:none,也就是空选项,分区或者设备无需修改,如果Device域为none,那么Opt强制为‘-’。
· ‘P’:向分区或者设备烧写固件。
STM32CubeProgrammer本质是通过uboot来烧写系统的,也就是先把uboot加载到板子的DDR里面并运行,然后使用uboot来烧写系统。uboot会请求需要烧写的二进制文件,然后将其烧写到指定的分区或者Falsh设备里面。
针对‘P’选项,还有另外两个可以搭配使用的小伙伴:
· ‘E’:空分区或设备,表示对应的分区或设备不更新,相关的Id项会被跳过。
· ‘D’:删除分区或设备。
允许的组合选项如下所示:
· ‘-’:空选型。
· ‘P’:更新分区或设备,也就是向分区或设备烧写固件。
· ‘PE’:不更新,也就是指定某个分区或者设备不需要烧写固件,这样我们就可以单独只更新tf-a、uboot、kernel或者rootfs。
· ‘PD’:删除并更新,也可以写作DP。
· ‘PDE’:删除并且保持为空,也可以写作PED/DPE/DEP/EPD/EDP。
②、Id域
STM32CubeProgrammer通过Id域来确定烧写方法,会通过Id域来识别下一个要烧写到设备里面的二进制文件:
· ROM或者FSBL:二进制文件要加载到RAM中
· SSBL(uboot):二进制文件要烧写到Flash中。
FlashLayout支持的Id范围如表6.2.3.2所示:
范围 分区
0x01~0x0F 带有STM32头部信息的Boot分区,如SSBL、FSBL、其他(TEE或M4固件)
0x10~0xF0 不带头部的用户编程分区,如uiamge、dtb、rootfs、vendorfs、userfs
表6.2.3.2 FlashLayout支持的Id范围
其中0X01和0X03这两个ID是给FSBL和SSBL留着的,它们会被加载到RAM中。一些默认的Id含义如表6.2.3.3所示:
Id 分区
0x00 内部使用,用户不能使用此ID!
0x01 FSBL(第一阶段拷贝),ROM代码使用,会加载到RAM中
0x03 SSBL,FSBL使用,加载到RAM中
0xF1~0xFD 虚拟分区,内部使用
0xF1 命令获取阶段。
0xF2 OTP
0xF3 SSP
0xF4 PMIC NVM
0xFE 操作结束
0xFF 复位
表6.2.3.3 默认Id含义
③、Name域
Name域为一段字符串,也就是目标内存段的名字。
④、Type域
Type域仅仅用于uboot,用来选择需要更新的Flash区域:
· SD卡或者EMMC设备对应GPT分区。
· 原始的 Flash设备,如NAND、NOR等对应MTD分区。
SD/EMMC和NAND/NOR所支持的Type类型如表6.2.3.4所示:
Type GPT MTD
SD EMMC NAND NOR RAM
Binary × × × × ×
Binary(N) ssbl
FileSystem × × × × dtb
System × × UBI UBI kernel
Rawimage × user data × ×
表6.2.3.4 Type域
注:×表示支持。
正点原子STM32MP157开发板为EMMC类型,所以我们只EMMC下的Type域含义:
· Binary:原始的二进制文件。
· FileSystem:linux文件系统,为ext2/ext4/fat格式。
· System:Linux内核。
⑤、Device域
Device域指定Uboot 设备树定义的设备和索引(从0开始),不同的设备其设备名字和索引不同:
· mmc+索引:如mmc0、mmc1、mmc2等,对应SD卡或EMMC。比如SD卡和EMMC分别接到MP1的SDMMC1和SDMMC2接口上,那么SD卡和EMMC分别为mmc0和mmc1。
· nor+索引:如nor0,对应 NOR或者QUADSPI Flash。
· mmc+索引:如nand0,对应连接到FMC总线上的并行NAND Flash。
· spi-nand+索引:如spi-nand0,对应连接到QSPI上的串行NAND Flash。
· none:RAM,也就是将固件加载到RAM里面,仅允许启动阶段使用,而且Type域要为Binary,Offset域要为0,Opt域为‘-’。
· ram+索引:如ram0,烧写服务讲固件加载到RAM中运行。
⑥、Offset域
Offset就是偏移,支持的值如下:
· boot1:EMMC的第一个启动区域分区。
· boot2:EMMC的第二个启动区域分区。
· 数字:具体的偏移值,单位为字节。
⑦、Binary域
STM32CubeProgrammer软件要使用的二进制文件。
关于STM32CubeProgrammer的FlashLayout文件语法就讲解到这里,接下来就是将TF-A烧写到开发板的EMMC里面。
3、通过USB烧写TF-A
首先设置开发板拨码开关,设置为000,也就是从USB启动,然后复位开发板!
一切准备就绪,现在可以通过STM32CubeProgrammer将TF-A源码烧写到EMMC里面了,首先通过USB Type-C线将开发板的USB_OTG和USB_TTL连接到电脑上,如图6.2.3.7所示:
图6.2.3.7 USB串口与USB OTG连接
按照图6.2.3.7将板子的USB串口与USB OTG连接到电脑以后还要检查一下连接是否成功,打开电脑的设备管理器,查看CH340和DFU模式是否存在,如图6.2.3.8所示:
图6.2.3.8 USB串口与USB OTG
连接没问题的话就可以使用STM32CubeProgrammer来烧写TF-A了,打开STM32CubeProgrammer,选择USB连接方式,Port选择USB1,如图6.2.3.9所示:
图6.2.3.9 USB连接设置
USB设置好以后点击图6.2.3.9右上角的“Connect”来连接开发板,连接成功以后左下角的log区域就会输出一些信息,右侧中间的数据区域也会显示开发板默认的分区情况,右下角会显示目标板信息,如图6.2.3.10所示:
图6.2.3.10 软件连接信息
STM32CubeProgrammer要使用FlashLayout文件来烧写系统,也就是前面我们创建的tf-a.tsv。点击图6.2.3.10中的“Open File”,打开tf-a.tsv,打开以后如图6.2.3.11所示:
图6.2.3.11 加载tf-a.tsv文件
注意,如果大家没有看到图6.2.3.11中的“Browse”和“Download”这两个按钮的话,请把STM32CubeProgrammer界面托大一点,尤其是左右托大,因为软件默认界面会把这两个按钮挡住!
一切准备就绪以后就可以点击图6.2.3.11中的“Download”按钮开始下载,下方的log区域就会显示烧写过程,烧写完成以后就会有如图6.2.3.12所示提示:
图6.2.3.12 烧写成功
6.2.4 TF-A的运行
我们自己编译的TF-A已经烧写到了开发板中,接下来就是测试一下看能不能运行,打开 MobaXterm软件,设置好与开发板连接的串口,波特率选择115200。
设置开发板拨码开关为010,也就是从EMMC启动,然后复位开发板!
注意,由于我们开发板默认已经烧写了整套Linux系统,所以直接启动的话会启动整个系统,包括我们刚刚烧写的自己编译的TF-A,原有的uboot、Linux系统等。TF-A是最先启动的,也就是最前的就是我们自己编译的TF-A,如图6.2.4.1所示:
图6.2.4.1 TF-A启动log信息
TF-A启动的时候会打印出编译时间,我们可以通过编译时间来判断是否为我们自己编译的TF-A。比如图6.2.4.1中TF-A的编译时间为2020年11月11号10:53:02,这个时间正是笔者写教程编译的时间,说明目前正在运行的TF-A就是笔者自行编译的正点原子出厂TF-A,也就是tf-a-stm32mp157d-atk-trusted.stm32。