2. 开发环境搭建与交叉工具链

STM32MP1 系列(如 STM32MP157)内部集成双核 Cortex-A7 与单核 Cortex-M4,二者运行在完全不同的软件栈上:Cortex-A7 运行 Linux,使用 OpenSTLinux 发行版;Cortex-M4 运行裸机或 RTOS 固件,使用 STM32CubeMP1 固件包。因此开发环境不是"一个 IDE 装完就够",而是由三套相互配合的工具组成:负责 A7 侧 Linux 应用与内核开发的 OpenSTLinux SDK、负责 M4 侧固件开发的 STM32CubeIDE 与 STM32CubeMP1 包,以及负责把两侧镜像打包成可启动介质的 CubeProgrammer。理解这三者的分工与衔接关系,是后续双核协同开发的前提。

三套工具的分工与衔接

OpenSTLinux SDK 是一个交叉编译工具链集合,核心是 arm-ostl-linux-gnueabi 系列 GCC,用于在 x86 主机上编译出能在 Cortex-A7 上运行的 Linux 可执行文件、内核模块和设备树。它通过安装脚本生成一个自包含的 SDK 目录,执行 source 环境脚本后,主机 shell 中就会出现交叉编译器、sysroot 和 CMake 工具链文件。

STM32CubeIDE 基于 Eclipse,内置 arm-none-eabi-gcc,用于开发 Cortex-M4 固件。它本身不负责 A7 侧 Linux 编译,但通过 STM32CubeMP1 固件包提供 M4 的 HAL 库、启动代码、链接脚本和示例工程。STM32CubeMP1 包通常以压缩包形式提供,解压后包含 Drivers、Projects 等目录,其中 Projects/STM32MP157C-DK2/Examples 下有针对不同开发板的示例。

两侧编译产物最终需要合并:A7 侧生成的是 Linux 镜像(如 st-image-core 或自定义 rootfs),M4 侧生成的是 .elf 或 .bin 固件。STM32CubeProgrammer 通过 Flashlayout 文件把两者按分区写入 SD 卡或 eMMC,使上电后 U-Boot 能加载 Linux,同时通过 remoteproc 框架把 M4 固件加载到指定内存地址。

STM32MP1 双核开发环境组成与镜像合并流程 主机(x86_64 Linux / Windows + WSL) OpenSTLinux SDK arm-ostl-linux-gnueabi-gcc sysroot + CMake 工具链文件 编译 A7 侧应用 / 内核模块 source environment-setup-* STM32CubeIDE arm-none-eabi-gcc STM32CubeMP1 固件包 编译 M4 侧 .elf / .bin HAL + 启动代码 + 链接脚本 STM32CubeProgrammer Flashlayout .tsv 文件 写入 SD 卡 / eMMC 分区:fsbl / fip / rootfs USB DFU / UART 模式 编译产物 A7 侧:Linux 镜像 st-image-core / 自定义 rootfs M4 侧:固件 .elf / .bin(remoteproc 加载) Flashlayout .tsv 描述分区与镜像对应关系 SD 卡 / eMMC 启动介质 U-Boot → Linux(A7) + remoteproc 加载 M4 固件 双核协同运行 A7: Linux | M4: 实时固件

安装 OpenSTLinux SDK

SDK 安装包通常命名为 st-image-weston-openstlinux-weston-stm32mp1-x86_64-toolchain-*.sh。在主机上执行安装脚本时,需要指定安装目录,例如:

./st-image-weston-openstlinux-weston-stm32mp1-x86_64-toolchain-4.1-openstlinux-6.1-yocto-mickledore-x86_64-toolchain-4.1.sh -d /opt/st/stm32mp1/4.1-openstlinux-6.1

安装完成后,进入 SDK 目录并执行环境脚本:

cd /opt/st/stm32mp1/4.1-openstlinux-6.1
source environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

此时 $CC 变量应指向交叉编译器。可用 echo $CC 和 $CC --version 验证。若输出中包含 arm-ostl-linux-gnueabi 且版本号与 SDK 一致,说明环境生效。注意每次新开终端都需要重新 source,建议写入 shell 配置文件或使用独立脚本封装。

安装 STM32CubeIDE 与 STM32CubeMP1 固件包

STM32CubeIDE 从 ST 官网下载对应主机平台的安装包,Linux 下解压后运行 st-stm32cubeide_*.sh 即可。安装完成后首次启动会要求选择工作空间目录。STM32CubeMP1 固件包可以单独下载,也可以在 CubeIDE 中通过 Help → Manage Embedded Software Packages 在线安装。若离线安装,解压后得到类似 STM32Cube_FW_MP1_V1.6.0 的目录,其中关键路径为:

  • Drivers/STM32MP1xx_HAL_Driver:M4 侧 HAL 驱动源码;
  • Projects/STM32MP157C-DK2/Examples:针对 DK2 开发板的示例工程;
  • Projects/STM32MP157C-DK2/Templates:空白工程模板,适合作为双核工程起点。

在 CubeIDE 中导入 M4 工程时,选择 File → Import → Existing Projects into Workspace,指向 Templates 下的 STM32MP157C-DK2 目录。导入后需要检查链接脚本中的内存地址是否与 A7 侧 Linux 设备树中 reserved-memory 节点一致。典型配置中,M4 固件加载到 0x10000000 起始的 MCU SRAM 区域,大小约 384 KB,具体以实际设备树为准。

双核工程创建流程

双核工程不是把两个工程放在同一个工作空间就自动协同,而是需要明确三件事:M4 固件的加载地址、A7 侧 remoteproc 的设备树配置、以及两侧的通信通道(如 OpenAMP 的 rpmsg)。创建流程可以按以下顺序推进:

  1. 在 CubeIDE 中基于 Templates 创建 M4 工程,选择目标芯片 STM32MP157C,配置时钟树使 M4 运行在 209 MHz(典型值),使能需要的 HAL 模块。
  2. 在工程属性中确认链接脚本 STM32MP157Cxx_CM4.ld 的 ROM/RAM 区域与设备树 reserved-memory 一致。
  3. 编译生成 .elf,再用 arm-none-eabi-objcopy -O binary 生成 .bin,便于 remoteproc 加载。
  4. 在 A7 侧 Linux 中确认 /sys/class/remoteproc/remoteproc0 存在,通过 echo firmware_name > /sys/class/remoteproc/remoteproc0/firmware 指定固件,再 echo start > .../state 启动 M4。
  5. 若使用 OpenAMP,需在设备树中使能 m4_rproc 节点并配置 vdev 缓冲区地址,两侧共享内存区域不能与 Linux 已用内存冲突。
验证 M4 是否成功启动,可观察 dmesg | grep remoteproc 输出。若出现 "remoteproc0: remote processor is now up",说明固件加载成功;若报 "failed to load firmware",优先检查固件路径、文件名和 reserved-memory 地址是否匹配。

常见问题与判断依据

环境搭建阶段最容易出现三类问题。第一类是 SDK 环境未生效,表现为 arm-ostl-linux-gnueabi-gcc: command not found,解决方法是重新 source 环境脚本并确认 $CC 已导出。第二类是 M4 固件加载地址与设备树不一致,表现为 remoteproc 启动后立即崩溃或 Linux 内核报 "invalid resource",此时应对比链接脚本与设备树中的 reg 属性。第三类是 Flashlayout 分区与镜像不匹配,表现为上电后 U-Boot 找不到内核,需要检查 .tsv 文件中每个分区的偏移和镜像文件名是否与实际产物一致。