3. 开发环境搭建与交叉编译工具链

STM32MP 系列属于异构多核处理器:Cortex-A7 运行 Linux,Cortex-M4 运行实时固件。这种结构决定了开发环境不是单一 IDE 就能覆盖的,而是由“配置工具 + 集成开发环境 + 交叉编译工具链 + 烧录与调试通道”四部分共同组成。本节围绕 STM32CubeMX、STM32CubeIDE、OpenSTLinux SDK 的安装与配合使用展开,并给出交叉编译、镜像烧录和串口调试的完整操作路径。

一、工具链分工与整体关系

先明确各工具的职责边界,避免混用:

  • STM32CubeMX:图形化完成引脚分配、时钟树配置、外设初始化,并生成设备树片段(.dtsi)、TF-A/U-Boot 配置以及 M4 侧工程骨架。它解决的是“硬件资源怎么分配”。
  • STM32CubeIDE:基于 Eclipse 的集成环境,内置 GCC 交叉编译器,主要用于 Cortex-M4 固件开发、编译、下载与 SWD 调试,也可用于 A7 侧裸机或小规模工程。它解决的是“M4 代码怎么写、怎么调”。
  • OpenSTLinux SDK:ST 官方提供的 Yocto 交叉编译环境,包含 arm-ostl-linux-gnueabi 工具链、sysroot 和内核头文件,用于编译 A7 侧 Linux 应用、内核模块和驱动。它解决的是“Linux 用户态/内核态程序怎么编”。

三者关系可以用下面的信号与数据流图表示:CubeMX 输出的配置同时喂给 CubeIDE 和 OpenSTLinux 构建系统,最终由 CubeProgrammer 把 TF-A、U-Boot、内核、根文件系统烧入 eMMC/SD 卡,串口则贯穿整个启动与调试过程。

STM32MP 开发环境工具链与数据流 STM32CubeMX 引脚/时钟/外设配置 生成 .dtsi / 工程骨架 STM32CubeIDE M4 固件编译/下载 SWD 在线调试 OpenSTLinux SDK arm-ostl-linux-gnueabi sysroot + 内核头文件 M4 配置 设备树/启动配置 M4 固件 .elf/.bin 经 CubeIDE 编译 A7 应用/驱动 .ko 经 SDK 交叉编译 启动镜像集合 TF-A / U-Boot / 内核 根文件系统 STM32CubeProgrammer USB DFU / UART / SD 卡烧录 STM32MP 目标板(eMMC / SD) 串口调试终端 115200 8N1

二、安装与版本匹配

安装顺序建议为:先装 STM32CubeMX,再装 STM32CubeIDE,最后安装 OpenSTLinux SDK。原因是 CubeMX 生成的工程需要被 CubeIDE 直接导入,而 SDK 的安装脚本会检查主机依赖(如 Python3、git、chrpath、diffstat 等)。

版本匹配是常见踩坑点。以 STM32MP157 为例,若使用 OpenSTLinux 5.0 发行版,应选择对应的 STM32CubeMX 6.11 及以上版本,并确保 CubeIDE 版本不低于 1.15。版本错配最典型的表现是:CubeMX 生成的设备树节点名称与 SDK 中内核源码的绑定文档不一致,编译时出现 undefined node label 或 no matching binding 错误。

SDK 安装的核心命令如下(以 Linux 主机为例):

# 1. 解压 SDK 安装包
tar xf en.SDK-x86_64-stm32mp1-openstlinux-6.1-yocto-mickledore-x86_64-toolchain-5.0.sh.tar.gz

# 2. 执行安装,指定安装目录
./en.SDK-x86_64-stm32mp1-openstlinux-6.1-yocto-mickledore-x86_64-toolchain-5.0.sh -d /opt/st/stm32mp1/5.0

# 3. 激活环境(每次新开终端都要执行)
source /opt/st/stm32mp1/5.0/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

# 4. 验证工具链
arm-ostl-linux-gnueabi-gcc --version
echo $SDKTARGETSYSROOT

第 4 步中 $SDKTARGETSYSROOT 应输出类似 /opt/st/stm32mp1/5.0/sysroots/cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi 的路径。若为空,说明环境脚本未正确 source,后续交叉编译会退化为主机本地编译,生成 x86 可执行文件,烧到板子上必然报 Exec format error。

三、交叉编译实操

交叉编译的本质是:在 x86_64 主机上,用目标架构的编译器生成 ARM 指令。以编译一个简单的 GPIO 控制程序为例:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(void) {
    int fd = open("/sys/class/gpio/gpio14/value", O_WRONLY);
    if (fd < 0) { perror("open gpio"); return 1; }
    write(fd, "1", 1);
    close(fd);
    printf("GPIO14 set high\n");
    return 0;
}

编译命令使用 SDK 提供的 $CC 变量,它已包含 --sysroot 和 -march=armv7-a 等参数:

$CC gpio_test.c -o gpio_test
file gpio_test
# 输出应包含:ELF 32-bit LSB executable, ARM, EABI5

若 file 显示为 x86-64,说明 $CC 未生效,需重新 source 环境脚本。编译内核模块时则需额外指定内核构建目录:

make -C $KERNEL_SRC M=$PWD modules ARCH=arm CROSS_COMPILE=arm-ostl-linux-gnueabi-

四、镜像烧录与串口调试

STM32MP157 支持三种启动介质:SD 卡、eMMC、NOR Flash。开发阶段推荐先用 SD 卡启动,因为烧录失败不会锁死板载 eMMC,恢复成本低。烧录方式有两种:

  • SD 卡直接写入:用 dd 把 .img 写入卡设备,适合首次部署。
  • STM32CubeProgrammer + USB DFU:把 BOOT 拨码切到 DFU 模式,通过 USB 烧写 eMMC,适合量产或恢复。

串口调试是贯穿始终的观察窗口。STM32MP157 的 Cortex-A7 调试串口通常为 UART4,参数 115200-8-N-1。上电后应依次看到 TF-A、U-Boot、内核、systemd 的日志。判断启动是否成功的三个关键标志:

  1. U-Boot 阶段出现 Hit any key to stop autoboot,说明 TF-A 和 U-Boot 正常。
  2. 内核阶段出现 Kernel command line 和 mmc0: new high speed SDHC card,说明存储识别正常。
  3. 用户态出现 stm32mp1 login:,说明根文件系统挂载成功。
若串口无任何输出,先检查 TX/RX 是否交叉、GND 是否共地、波特率是否为 115200。若只有乱码,通常是波特率或时钟配置不匹配,可尝试 9600 或检查 CubeMX 中 UART4 的时钟源。
烧录 eMMC 前务必确认 BOOT 拨码位置。若在 eMMC 启动模式下执行 DFU 烧录,可能因分区表被覆盖导致无法再次进入 DFU,需要拆机短接或使用 SD 卡救援。

五、环境验证清单

完成上述步骤后,建议按以下清单逐项确认,避免把环境问题带入后续开发:

检查项验证命令/现象合格标准
CubeMX 版本Help → About与 SDK 发行版匹配
CubeIDE 编译器Project → Build无 toolchain not found
SDK 环境变量echo $SDKTARGETSYSROOT输出非空且路径存在
交叉编译产物file gpio_testARM 32-bit ELF
串口连接上电观察日志出现 login 提示符
网络连通ping 主机 IP可互通,便于 NFS 调试

这套环境一旦跑通,后续的驱动开发、应用部署和现场集成才有稳定的基础。建议把 SDK 环境激活命令写入 ~/.bashrc 或独立脚本,减少重复操作带来的版本漂移风险。