1. STM32MP异构多核架构总览

STM32MP系列(如STM32MP157、STM32MP135)是ST推出的异构多核微处理器,其核心设计思想是在一颗芯片内同时集成应用处理器(Cortex-A)与实时微控制器(Cortex-M),让两类任务各得其所。理解这套架构,关键不是记住“有几个核”,而是搞清楚:两个核各自拥有什么、共享什么、如何互相通知、以及什么任务该放在哪一侧。

一、双核定位:不是主从,而是分工

Cortex-A核(如Cortex-A7,主频650MHz~800MHz)运行Linux等富操作系统,负责图形界面、网络协议栈、文件系统、复杂应用逻辑。它拥有MMU(内存管理单元),支持虚拟内存,适合处理非确定性、高吞吐的任务。Cortex-M核(如Cortex-M4,主频209MHz)不带MMU,运行裸机或RTOS(如FreeRTOS),中断响应延迟通常在数十纳秒级,适合电机控制、传感器采样、安全监控等硬实时任务。

两者并非主从关系。A核不能直接“调用”M核的函数,M核也不能直接访问A核的进程内存。它们通过硬件级通信通道协作,各自独立运行。

二、硬件资源划分

芯片内部资源按“专属”与“共享”两类划分:

  • A核专属:DDR控制器(外接DDR3/DDR3L)、LCD-TFT控制器、GPU(部分型号)、以太网MAC、USB HS、SDMMC等。
  • M核专属:MCU SRAM(如STM32MP157中M核可用的384KB)、部分定时器(TIM)、ADC、DAC、低功耗UART等。
  • 共享外设:GPIO、I2C、SPI、UART、定时器等可通过ETZPC(Extended TrustZone Protection Controller)和RCC(复位与时钟控制器)分配给某一核,分配后由该核独占访问。

实际项目中,分配原则是:实时性要求高的外设(如PWM驱动电机)划给M核;需要Linux驱动栈的外设(如Wi-Fi模块)划给A核。分配通过设备树(Device Tree)和ETZPC配置完成,不是运行时动态切换。

三、内存映射:两个核看到的世界不同

这是最容易混淆的部分。A核运行Linux,使用MMU将物理地址映射为虚拟地址,应用程序看到的是虚拟地址空间。M核直接使用物理地址,没有MMU。两者共享同一块物理DDR和SRAM,但访问路径和可见范围不同。

以STM32MP157为例,关键地址区域如下(示例值,具体以参考手册为准):

区域物理地址范围A核可见M核可见用途
DDR0xC0000000~0xFFFFFFFF是(经MMU)是(需配置)Linux系统内存、共享缓冲区
MCU SRAM0x30000000~0x3005FFFF是是M核代码/数据、共享内存
RETRAM0x38000000~0x3800FFFF是是低功耗保持、M核启动
A核外设0x40000000~0x5FFFFFFF是部分LCD、USB、以太网等
M核外设0x40000000~0x5FFFFFFF部分是TIM、ADC、UART等

共享内存通常放在MCU SRAM或DDR的保留区域。A核通过/dev/mem或mmap映射物理地址,M核直接读写同一物理地址。双方必须约定好数据结构、对齐方式和缓存策略。A核侧若使用DDR共享区,需注意Cache一致性——通常将该区域配置为non-cacheable或使用dma_alloc_coherent。

四、中断路由:谁处理哪个中断

STM32MP的中断路由由EXTI(外部中断控制器)和GIC(通用中断控制器)共同管理。每个外设中断可被配置为路由到A核的GIC或M核的NVIC。配置通过ETZPC和中断路由寄存器完成,通常在启动阶段由A核的Linux或M核的固件设定。

典型场景:按键中断路由到M核,M核在中断服务程序中完成去抖和状态更新,再通过IPCC通知A核刷新界面。这样A核不必频繁被短中断打断,M核也能保证响应确定性。

STM32MP 异构多核架构与通信路径 Cortex-A7 (Linux) MMU · 虚拟内存 · 650MHz 应用/网络/文件系统 LCD/以太网/USB驱动 DDR控制器 · GIC中断控制器 /dev/mem · mmap · rpmsg Cortex-M4 (RTOS/裸机) 无MMU · 物理地址 · 209MHz 电机PWM/ADC采样 安全监控/低功耗 NVIC中断控制器 · 定时器 IPCC · 共享SRAM 共享资源 MCU SRAM (384KB) DDR保留区 · IPCC寄存器 核间通信机制 IPCC硬件中断 共享内存+Mailbox RPMsg/VirtIO OpenAMP框架

五、核间通信:IPCC与共享内存

两个核之间最直接的通信硬件是IPCC(Inter-Processor Communication Controller)。IPCC提供多个通道,每个通道可配置为向对方核发送中断。典型用法:M核完成一次ADC采样后,写IPCC寄存器触发A核中断;A核在中断处理中读取共享内存中的采样数据。

软件层面,ST官方推荐使用OpenAMP框架。它基于RPMsg(Remote Processor Messaging)协议,在共享内存上建立虚拟队列,A核侧表现为/dev/rpmsg_ctrl0等字符设备,M核侧调用rpmsg_send()。这样双方可以像发消息一样通信,不必手动管理环形缓冲区。

一个实际配置示例:在设备树中为M核保留64KB DDR作为共享区,起始地址0xC2000000,A核通过reserved-memory节点声明,M核在链接脚本中将该区域定义为.shared_data段。双方约定结构体首字段为uint32_t magic,用于校验数据有效性。

六、典型应用场景

以下场景能直观体现异构分工的价值:

  • 工业电机控制:M核运行FOC算法,PWM频率20kHz,电流环周期50μs;A核运行HMI和Modbus TCP,通过共享内存读取转速、电流值。
  • 智能家居网关:A核跑Linux+Zigbee协议栈,M核处理按键、LED指示和看门狗,即使A核系统卡顿,M核仍能维持基本交互。
  • 安全监控:M核独立监控温度、电压,超阈值直接切断输出;A核负责日志记录和远程上报。M核不受Linux崩溃影响。
选型判断原则:任务周期小于1ms、抖动要求小于10μs、或需要在A核休眠时继续运行——放M核。需要文件系统、网络协议栈、图形界面、复杂算法——放A核。两者都需要时,用共享内存+IPCC拆分。

七、启动流程与资源分配时机

上电后,A核先启动ROM Code,加载FSBL(First Stage Boot Loader),随后加载SSBL(U-Boot)和Linux内核。M核的固件(如fw_cortex_m4.elf)通常由A核的Linux通过remoteproc框架加载,加载地址和入口点由设备树指定。M核启动后,双方通过IPCC握手,确认共享内存就绪,然后进入各自的主循环。

资源分配(ETZPC、中断路由、时钟)必须在M核启动前由A核完成配置,否则M核可能访问到未授权的区域而触发总线错误。这是实际调试中最常见的坑之一:M核代码在A核尚未配置ETZPC时就尝试访问外设,导致HardFault。