文章目录
- [1 源码获取及准备工作](#1 源码获取及准备工作)
-
- [1.1 源码获取](#1.1 源码获取)
- [1.2 TF-A源码打补丁](#1.2 TF-A源码打补丁)
- [1.3 stm32wrapper4dbg工具安装](#1.3 stm32wrapper4dbg工具安装)
- [1.4 安装设备树编译工具](#1.4 安装设备树编译工具)
- [1.5 修改Makefile.sdk](#1.5 修改Makefile.sdk)
- [2 TF-A移植](#2 TF-A移植)
-
- [2.1 新建自己开发板对应的设备树](#2.1 新建自己开发板对应的设备树)
-
- [2.1.1 创建.dts文件](#2.1.1 创建.dts文件)
- [2.1.2 创建.dtsi文件](#2.1.2 创建.dtsi文件)
- [2.2 修改设备树电源管理](#2.2 修改设备树电源管理)
- [2.3 修改TF卡和EMMC设备树](#2.3 修改TF卡和EMMC设备树)
- [2.4 修改USB_OTG设备树](#2.4 修改USB_OTG设备树)
- [3 FlashLayout](#3 FlashLayout)
-
- [3.1 tsv七大域](#3.1 tsv七大域)
-
- [3.1.1 Opt域](#3.1.1 Opt域)
- [3.1.2 Id域](#3.1.2 Id域)
- [3.1.3 Name域](#3.1.3 Name域)
- [3.1.4 Type域](#3.1.4 Type域)
- [3.1.5 Device域](#3.1.5 Device域)
- [3.1.6 Offset域](#3.1.6 Offset域)
- [3.1.7 Binary域](#3.1.7 Binary域)
- [4 TF-A编译](#4 TF-A编译)
-
- [4.1 编译`tf-a-stm32mp157d-da-trusted.stm32`](#4.1 编译
tf-a-stm32mp157d-da-trusted.stm32) - [4.2 单独编译`tf-a-stm32mp157d-da-serialboot.stm32`](#4.2 单独编译
tf-a-stm32mp157d-da-serialboot.stm32)
- [4.1 编译`tf-a-stm32mp157d-da-trusted.stm32`](#4.1 编译
- [5 TF-A烧录到EMMC](#5 TF-A烧录到EMMC)
-
- [5.1 编译文件准备](#5.1 编译文件准备)
- [5.2 通过USB烧写TF-A](#5.2 通过USB烧写TF-A)
- [6 TF-A运行](#6 TF-A运行)
- [7 TF-A移植结果](#7 TF-A移植结果)
说明:文档涉及到的en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz源码文件,和最终烧录的文件夹da-images,均以资源形式上传至CSDN资源。
1 源码获取及准备工作
1.1 源码获取
使用正点原子提供的en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz。
使用如下命令解压文件:
bash
tar -xvf en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz
目录下包含了如下文件夹:
| 文件夹 | 描述 |
|---|---|
| linux-stm32mp-5.4.31-r0 | linux源码,版本号为5.4.31 |
| optee-os-stm32mp-3.9.0.r1-r0 | optee系统源码,版本为3.9.0 |
| tf-a-stm32mp-2.2.r1-r0 | tf-a源码,版本号为2.2 |
| tf-a-stm32mp-ssp-2.2.r1-r0 | tf-a源码,ssp全称为secure secert provisioning,安全相关的内容 |
| u-boot-stm32mp-2020.01-r0 | uboot源码,版本号为2020.01 |
tf-a相关使用tf-a-stm32mp-2.2.r1-r0文件夹内容。
1.2 TF-A源码打补丁
将tf-a-stm32mp-2.2.r1-r0文件夹内容重新拷贝到一个新的文件夹中,例如/home/alientek/linux/da-mp1/da/tf-a,在新的文件夹中使用如下命令打补丁:
bash
# 在/home/alientek/linux/da-mp1/da/tf-a 文件夹下打开一个终端,执行如下命令:
tar -vxf tf-a-stm32mp-2.2.r1-r0.tar.gz
cd tf-a-stm32mp-2.2.r1-r0
for p in `ls -1 ../*.patch`; do patch -p1 < $p; done # 打补丁
1.3 stm32wrapper4dbg工具安装
在编译TF-A或Uboot时需要使用stm32wrapper4dbg工具,ST提供了这个工具的源码,在Ubunntu中编译。获取压缩文件后,放入提前计划好的文件夹,经过以下命令安装。
bash
unzip stm32wrapper4dbg-master.zip
cd stm32wrapper4dbg-master
make
sudo cp stm32wrapper4dbg /usr/bin
# 验证是否安装成功
stm32wrapper4dbg -s
# 若输出 stm32wrapper4dbg 的用法说明安装成功
1.4 安装设备树编译工具
bash
sudo apt install device-tree-compiler
# 验证 device-tree-compiler 是否安装成功
dtc -v
# 若输出 版本信息 说明安装成功
1.5 修改Makefile.sdk
主要是指定编译时使用的交叉编译工具链和编译自定以的设备树文件。
- 指定交叉编译器,
EXTRA_OEMAKE,编译时使用指定的交叉编译工具链; - 修改编译列表,
TFA_DEVICETREE,指定生成的编译文件,不编译多余的; - 修改串口配置,
EXTRA_OEMAKE_SERIAL,生成tf-a-stm32mp157d-da-serialboot.stm32的必须配置。
修改前(部分,只提取了需要修改的部分):
makefile
#remove default variable
LDFLAGS=
CFLAGS=
CPPFLAGS=
CC=
CPP=
AS=
AR=
LD=
NM=
LOCAL_PATH=$(PWD)
EXTRA_OEMAKE=CROSS_COMPILE=arm-ostl-linux-gnueabi- DEBUG=1 LOG_LEVEL=40 PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_SPI_NOR=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1
EXTRA_OEMAKE_SERIAL= STM32MP_UART_PROGRAMMER=1 STM32MP_USB_PROGRAMMER=1
# Set default config
ELF_DEBUG_ENABLE ?= 1
TF_A_CONFIG ?= trusted optee serialboot
# Set specific OEMAKE config
TF_A_CONFIG_OEMAKE = trusted,"AARCH32_SP=sp_min" optee,"AARCH32_SP=optee" serialboot,"AARCH32_SP=sp_min"
# Set default TFA_DEVICETREE
TFA_DEVICETREE ?= stm32mp157a-dk1 stm32mp157d-dk1 stm32mp157c-dk2 stm32mp157f-dk2 stm32mp157c-ed1 stm32mp157f-ed1 stm32mp157a-ev1 stm32mp157c-ev1 stm32mp157d-ev1 stm32mp157f-ev1
修改后(部分,只提取了修改的部分):
makefile
#remove default variable
LDFLAGS=
CFLAGS=
CPPFLAGS=
CC=
CPP=
AS=
AR=
LD=
NM=
LOCAL_PATH=$(PWD)
EXTRA_OEMAKE=CROSS_COMPILE=arm-none-linux-gnueabihf- DEBUG=1 LOG_LEVEL=40 PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_SPI_NOR=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1
#EXTRA_OEMAKE_SERIAL= STM32MP_UART_PROGRAMMER=1 STM32MP_USB_PROGRAMMER=1
EXTRA_OEMAKE_SERIAL=$(filter-out STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_SPI_NOR=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1,$(EXTRA_OEMAKE)) STM32MP_UART_PROGRAMMER=1 STM32MP_USB_PROGRAMMER=1
# Set default config
ELF_DEBUG_ENABLE ?= 1
TF_A_CONFIG ?= trusted optee serialboot
# Set specific OEMAKE config
TF_A_CONFIG_OEMAKE = trusted,"AARCH32_SP=sp_min" optee,"AARCH32_SP=optee" serialboot,"AARCH32_SP=sp_min"
# Set default TFA_DEVICETREE
TFA_DEVICETREE ?= stm32mp157d-da
2 TF-A移植
移植就是让半导体官方提供的软件在自己的硬件平台上运行起来,准确的说应该是将自己的硬件添加到官方软件包。TF-A是ARM官方出品的一个软件包,半导体厂商会从ARM官方下载这个最正宗的TF-A软件包,然后将自己公司的SOC芯片添加进去,最终打包好提供给SOC用户,这个就是所谓的SDK包。
2.1 新建自己开发板对应的设备树
设备树英文名字叫做Device tree,用来描述板子硬件信息的,比如你的板子上的CPU有几个核、每个CPU核主频是多少,IIC、SPI这些外设的寄存器范围是多少,IIC接口下都挂了哪些设备等等。设备树文件是一种文本格式的文件,方便阅读与修改,文件后缀为.dts,设备树也有头文件,头文件后缀为.dtsi。和C语言一样.dts可以引用头文件.dtsi,.dts经过编译以后生成.dtb文件,.dtb就是开发板要使用的。类似于将C语言的.c文件编译为.bin文件,然后在开发板上运行,将dts编译为dtb的工具叫做DTC,并不是日常使用的gcc编译器。
打开tf-a-stm32mp-2.2.r1\fdts目录,fdts目录下保存的就是所有开发板的设备树文件,其中就包括了STM32MP1系列的。以stm32mp157d-ed1.dts为蓝本,添加正点原子STM32MP157开发板对应的设备树文件。
2.1.1 创建.dts文件
bash
cd tf-a-stm32mp-2.2.r1/
cd fdts/
cp stm32mp157d-ed1.dts stm32mp157d-da.dts
打开stm32mp157d-da.dts,内容如下:
d
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
* Copyright (C) STMicroelectronics 2019 - All Rights Reserved
* Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
*/
/dts-v1/;
#include "stm32mp157.dtsi"
#include "stm32mp15xd.dtsi"
#include "stm32mp15-pinctrl.dtsi"
#include "stm32mp15xxaa-pinctrl.dtsi"
#include "stm32mp15xx-edx.dtsi"
#include <dt-bindings/soc/st,stm32-etzpc.h>
/ {
model = "STMicroelectronics STM32MP157D eval daughter";
compatible = "st,stm32mp157d-ed1", "st,stm32mp157";
chosen {
stdout-path = "serial0:115200n8";
};
aliases {
serial0 = &uart4;
};
};
&cpu1 {
cpu-supply = <&vddcore>;
};
&etzpc {
st,decprot = <
DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)
DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)
DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)
>;
};
stm32mp157d-da.dts文件分析:
#inlcude头文件引用,其中引用STM32MP15X芯片相关的dtsi头文件,这些全部保留即可;#include "stm32mp15xx-edx.dtsi"非常重要,"stm32mp15xx-edx.dtsi",是edx系列开发板的通用头文件,适合具体板子有关的,很明显,板子不同其对应的板子头文件也不同。需要以stm32mp15xx-edx.dtsi为蓝本,创建正点原子开发板对应的板子头文件;stdout-path表示标准输出,也就是设置TF-A信息输出路径,这里设置为serial0也就是串行接口0(注意,不是STM32MP157的串口0),波特率为115200;serial0 = &uart4;设置serial0对应STM32MP157的串口4,所以TF-A会使用STM32MP157的串口4作为信息输出接口。
2.1.2 创建.dtsi文件
bash
cd tf-a-stm32mp-2.2.r1/
cd fdts/
cp stm32mp15xx-edx.dtsi stm32mp157d-da.dtsi
在stm32mp157d-da.dts文件中包含stm32mp157d-da.dtsi文件,在stm32mp157d-da.dts修改#include "stm32mp15xx-edx.dtsi"为#include "stm32mp157d-da.dtsi"
2.2 修改设备树电源管理
ST官方STM32MP157开发板用到了一颗PMIC芯片,型号为STPMIC1A。PMIC全称为Power Management IC,也就是集成电源管理芯片。在用单片机的时候,只需要给一个3.3V或5V电源即可,使用起来很方便。但是随着芯片性能的提升,SOC对电源的要求越来越多,比如Cortex-A系列芯片主电源一般要求3.3V,但是芯片内核电压可能需要1.2V,而外扩的DDR3L芯片工作电压是1.35V,DDR3L芯片的端接电压要求0.65V,USB工作电压又要求5V等等,也就是说随着SOC功能越来越强大,所需要的的电源要求也越来越高,最直观的就是电源种类很多。另外,这些电源的上电顺序也是有要求的,也就是说,哪些电源先启动,那些后启动等。
为此,SOC厂商为了简化硬件设计,都会针对自家的SOC芯片推出专用的PMIC芯片,PMIC芯片就是一个单进多出的电源芯片,比如输入5V,然后可以输出很多路电源,输出的这些电源可以配置输出电压。STPMIC1A就是ST专门为STM32MP1系列设计的专用PMIC,此PMIC芯片性能非常强大:
- 输入电压2.8V~5.5V。
- 4路可调的通用LDO输出。
- 1路DDR3端接LDO电源。
- 1路USBPHY所使用的LDO电源。
- 1路DDR参考电压LDO电源。
- 4路可调的BUCK开关电源。
- 1路5.2V/1.1A的BOOST开关电源。
- 1路500mA的USBOTG电源。
- 1路500mA/1000mA的通用电源。
- 此芯片有一个IIC接口,主控通过IIC接口来配置电源芯片,设置每一路输出电源的输出电压,开启时间等。
正点原子为成本考虑,并没有使用PMIC芯片,而是采用分离电源设计来实现电源设计。因此就需要修改设备树文件。
按照如下步骤修改设备树文件:
- 打开
stm32mp157d-da.dtsi,删除i2c4节点下的pmic节点; - 删除
/节点下的vin节点; - 在
/节点下添加电源信息节点,分别为vddcore、v3v3、vdd、vdd_usb;
修改相关内容后的stm32mp157d-da.dtsi文件内容如下(只粘贴了修改部分的,非全部):
d
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include <dt-bindings/power/stm32mp1-power.h>
#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi"
/ {
memory@c0000000 {
device_type = "memory";
reg = <0xC0000000 0x40000000>;
};
vddcore: regulator-vddcore {
compatible = "regulator-fixed";
regulator-name = "vddcore";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1350000>;
regulator-off-in-suspend;
regulator-always-on;
};
v3v3: regulator-3p3v {
compatible = "regulator-fixed";
regulator-name = "v3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-off-in-suspend;
regulator-always-on;
};
vdd: regulator-vdd {
compatible = "regulator-fixed";
regulator-name = "vdd";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-off-in-suspend;
regulator-always-on;
};
vdd_usb: regulator-vdd-usb {
compatible = "regulator-fixed";
regulator-name = "vdd_usb";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-off-in-suspend;
regulator-always-on;
};
};
&bsec {
board_id: board_id@ec {
reg = <0xec 0x4>;
st,non-secure-otp;
};
};
&clk_hse {
st,digbypass;
};
&cpu0{
cpu-supply = <&vddcore>;
};
&hash1 {
status = "okay";
};
&i2c4 {
pinctrl-names = "default";
pinctrl-0 = <&i2c4_pins_a>;
i2c-scl-rising-time-ns = <185>;
i2c-scl-falling-time-ns = <20>;
clock-frequency = <400000>;
status = "okay";
secure-status = "okay";
};
2.3 修改TF卡和EMMC设备树
按照如下步骤继续修改stm32mp157d-da.dtsi文件:
- 修改
sdmmc1和sdmmc2节点。
修改相关内容后的stm32mp157d-da.dtsi文件内容如下(只粘贴了修改部分的,非全部):
d
&sdmmc1 {
pinctrl-names = "default";
pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
st,neg-edge;
broken-cd;
bus-width = <4>;
vmmc-supply = <&v3v3>;
status = "okay";
};
&sdmmc2 {
pinctrl-names = "default";
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
non-removable;
st,neg-edge;
bus-width = <8>;
vmmc-supply = <&v3v3>;
vqmmc-supply = <&v3v3>;
status = "okay";
};
2.4 修改USB_OTG设备树
按照如下步骤继续修改stm32mp157d-da.dtsi文件:
- 修改
usbotg_hs节点; - 添加
usbphyc节点。
修改相关内容后的stm32mp157d-da.dtsi文件内容如下(只粘贴了修改部分的,非全部):
d
&usbotg_hs {
phys = <&usbphyc_port1 0>;
phy-names = "usb2-phy";
usb-role-switch;
status = "okay";
};
&usbphyc {
status = "okay";
};
3 FlashLayout
在烧录过程中需要烧录多个文件,多个文件应该放到哪个地方,要烧写到EMMC的哪个地址区域,这些都要通过STM32CubeProgrammer脚本文件来定义,STM32CubeProgrammer脚本文件后缀为.tsv,ST官方也叫做FlashLayout。
.tsv是文本格式的,很容易阅读,关于.tsv语法的详细讲解,请参考:tsv语法。用Notepad++软件(没有的话自行安装,这是个免费软件,安装很简单)打开.tsv格式的文件。因为.tsv文件有严格的格式要求。tsv语法要求只能用TAB键,不能用空格!以''#'开头为注释。
Notepad++设置:点击视图 -> 显示符号 -> 显示空格与制表符。
.tsv格式的文件有7列,这7列含义如下表所示:
| 域 | 作用 |
|---|---|
| Opt | 选项字段,可以设置为"-"、"P"、"D"或"E" |
| Id | 会根据这个id来决定烧写分区 |
| Name | 分区名字 |
| Type | 指定烧写的类型,仅供uboot使用 |
| Device | 指定烧写的设备类型与编号,比如emmc0、emmc1、nand0等,如果opt为''-'',那么此字段就为none |
| Offset | 分区的起始位置,如果为boot1"表示EMMC的第一个分区,如果为boot2"就表示EMMC第二个分区。如果是数字就表示需要偏移的字节数。 |
| Binary | 要烧录的文件 |
3.1 tsv七大域
3.1.1 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。
3.1.2 Id域
STM32CubeProgrammer通过Id域来确定烧写方法,会通过Id域来识别下一个要烧写到设备里面的二进制文件:
- ROM或者FSBL:二进制文件要加载到RAM中;
- SSBL(uboot):二进制文件要烧写到Flash中。
FlashLayout支持的Id范围如表所示:
| 范围 | 分区 |
|---|---|
| 0x01~0x0F | 带有STM32头部信息的Boot分区,如SSBL、FSBL、其他(TEE或M4固件) |
| 0x10~0xF0 | 不带头部的用户编程分区,如uimge、dtb、rootfs、vendorfs、userfs |
其中0X01和0X03这两个ID是给FSBL和SSBL留着的,它们会被加载到RAM中。一些默认的Id含义如表所示:
| Id | 分区 |
|---|---|
| 0x00 | 内部使用,用户不能使用此ID |
| 0x01 | FSBL,ROM代码使用,会加载到RAM中 |
| 0x03 | SSBL,FSBL使用,加载到RAM中 |
| 0xF1 - 0xFD | 虚拟分区,内部使用 |
| 0xF1 | 命令获取阶段 |
| 0xF2 | OTP |
| 0xF3 | SSP |
| 0xF4 | PMIC NVM |
| 0xFE | 操作结束 |
| 0xFF | 复位 |
3.1.3 Name域
Name域为一段字符串,也就是目标内存段的名字。
3.1.4 Type域
Type域仅仅用于uboot,用来选择需要更新的Flash区域:
- SD卡或者EMMC设备对应GPT分区;
- 原始的Flash设备,如NAND、NOR等对应MTD分区;
SD/EMMC和NAND/NOR所支持的Type类型如表所示(X:表示支持):

正点原子STM32MP157开发板为EMMC类型,所以只需要知道EMMC下的Type域含义:
- Binary原始的二进制文件;
- FileSystem:linux文件系统,为ext2/ext4/fat格式;
- System:Linux内核。
3.1.5 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中运行。
3.1.6 Offset域
Offset就是偏移,支持的值如下:
- boot1 EMMC的第一个启动区域分区;
- boot2 EMMC的第二个启动区域分区;
- 数字具体的偏移值,单位为字节。
3.1.7 Binary域
STM32CubeProgrammer软件要使用的二进制文件。
4 TF-A编译
4.1 编译tf-a-stm32mp157d-da-trusted.stm32
使用如下命令编译tf-a-stm32mp157d-da-trusted.stm32
bash
# 进入 tf-a 源码目录
cd tf-a-stm32mp-2.2.r1
# 使用 8线程编译,参数可以通过nproc命令查询
make -f ../Makefile.sdk -j8 all
cd ../serialboot/
ls -l tf-a-stm32mp157d-da-serialboot.stm32
将此阶段生成的tf-a-stm32mp-2.2.r1/../build/trusted/tf-a-stm32mp157d-da-trusted.stm32文件传输至Windows系统中。
4.2 单独编译tf-a-stm32mp157d-da-serialboot.stm32
使用如下命令编译tf-a-stm32mp157d-da-serialboot.stm32:
bash
# 进入 tf-a 源码目录
cd tf-a-stm32mp-2.2.r1
make -f ../Makefile.sdk clean # 清除之前的编译文件,必须
make -f ../Makefile.sdk TFA_DEVICETREE=stm32mp157d-da TF_A_CONFIG=serialboot ELF_DEBUG_ENABLE='1' all
将此阶段生成的tf-a-stm32mp-2.2.r1/../build/serialboot/tf-a-stm32mp157d-da-serialboot.stm32文件传输至Windows系统中。
注意,经过此步骤../build/optee和../build/trusted目录就没有了,也就是说此步骤单独编译了tf-a-stm32mp157d-da-serialboot.stm32。此后tf-a-stm32mp157d-da-serialboot.stm32可以不用修改,如果需要重新编译tf-a-stm32mp157d-da-trusted.stm32并,使用上一小章节重新编译,不需要修改Makefile.sdk文件。
5 TF-A烧录到EMMC
5.1 编译文件准备
将编译生成的tf-a-stm32mp157d-da-trusted.stm32和单独编译生成的tf-a-stm32mp157d-da-serialboot.stm32文件,以及u-boot.stm32文件(u-boot.stm32使用编译好的)统一放入文件夹中,例如:da-images文件夹。在da-images文件夹中添加da.tsv文件;文件内容如下所示:
tex
#Opt Id Name Type Device Offset Binary
- 0x01 fsbl1-boot Binary none 0x0 tf-a-stm32mp157d-da-serialboot.stm32
- 0x03 ssbl-boot Binary none 0x0 u-boot.stm32
P 0x04 fsbl1 Binary mmc1 boot1 tf-a-stm32mp157d-da-trusted.stm32
P 0x05 fsbl2 Binary mmc1 boot2 tf-a-stm32mp157d-da-trusted.stm32
文件内容格式要严格遵循下图:

tsv语法要求只能用TAB键,不能用空格!以#开头为注释。
最终da-images文件夹中的内容如下:

使用STM32CubeProgrammer采用USB的方式烧写至开发板中,也就是USB_OTG口来烧写系统。
5.2 通过USB烧写TF-A
通过USBType-C线将开发板的USB_OTG和USB_TTL连接到电脑上。

设置开发板拨码开关,设置为000,也就是从USB启动,然后复位开发板。
打开STM32CubeProgrammer,选择USB连接方式,Port选择USB1。

USB设置好以后点击右上角的"Connect"来连接开发板,连接成功以后左下角的log区域就会输出一些信息,右侧中间的数据区域也会显示开发板默认的分区情况,右下角会显示目标板信息,如图所示:

STM32CubeProgrammer要使用FlashLayout文件来烧写系统,也就是da-images文件夹下的da.tsv。点击界面上的"Open File",打开da.tsv,如下图所示:

烧写完成后会有如下提示:

6 TF-A运行
打开MobaXterm软件,设置好与开发板连接的串口,波特率选择115200。
设置开发板拨码开关为010,也就是从EMMC启动,然后复位开发板!
在串口中观察启动过程。
7 TF-A移植结果
根据如下图示进行判断:
