4. 核间通信硬件基础
在STM32MP系列异构多核系统中,Cortex-A核运行Linux,Cortex-M核运行裸机或RTOS,两者之间要交换数据、传递事件、协调对共享资源的访问。如果只靠软件轮询或自定义协议,不仅CPU开销大,还容易出现竞态和丢事件。STM32MP1/MP2在芯片内部集成了三套硬件机制来支撑核间通信:IPCC负责跨核中断与消息通知,共享内存SRAM提供物理数据缓冲区,HSEM提供硬件信号量实现互斥。理解这三者的分工与配合,是设计可靠核间通信链路的前提。
一、IPCC:跨核中断与消息控制器
IPCC(Inter-Processor Communication Controller)是核间通信的“事件通道”。它并不搬运数据,而是负责在A核与M核之间产生和接收中断,并携带一个32位消息字。IPCC内部按“处理器—通道”组织:每个处理器(CPU1对应A7/A35,CPU2对应M4/M33)拥有若干通信通道,每个通道可独立配置为发送或接收方向,并绑定到对应的中断线。
以STM32MP157为例,IPCC提供6个双向通道,每个通道包含:一个发送寄存器(TX)用于写入要传递的消息,一个接收寄存器(RX)用于读取对端发来的消息,以及状态位(如TXF空、RXF满)。当CPU1向通道1的TX写入数据后,硬件自动置位CPU2侧通道1的RXF标志,并触发CPU2的IPCC接收中断。M核在中断服务程序中读取RX寄存器,即完成一次“带消息的中断通知”。
实际配置中,通常把IPCC通道按用途划分:通道1用于命令/控制字传递,通道2用于数据就绪通知,通道3用于应答。消息字本身只有32位,因此它一般承载“命令码+长度+共享内存偏移”这类元信息,真正的数据体放在共享内存中。这种“IPCC传信令、SRAM传数据”的分工是STM32MP核间通信的典型模式。
二、共享内存SRAM布局
STM32MP1内部有一块MCU SRAM(如STM32MP157为384KB,分为SRAM1/2/3/4),它同时映射到A核和M核的地址空间,是双方都能访问的物理内存。核间通信的共享缓冲区就建立在这里。关键问题是:A核和M核看到的地址不同,必须通过地址转换表建立对应关系。
典型布局如下:在MCU SRAM中划分出控制区与数据区。控制区放置共享描述符结构,例如环形缓冲区的读写指针、缓冲区状态、消息计数;数据区则按固定大小的槽位(如256字节/槽)组织,形成多个数据块。A核侧通过/dev/mmcblk之外的rpmsg或自定义字符设备映射该区域,M核侧直接用链接脚本把缓冲区定位到MCU SRAM的固定地址。
/* M核链接脚本片段:将共享区定位到MCU SRAM */
MEMORY
{
MCU_SRAM (rwx) : ORIGIN = 0x10000000, LENGTH = 256K
}
.shared_region (NOLOAD) :
{
. = ALIGN(4);
_shared_start = .;
*(.ipc_ctrl) /* 控制描述符 */
*(.ipc_data) /* 数据槽位 */
_shared_end = .;
} > MCU_SRAM
地址对应关系需要显式定义。例如M核看到共享区起始地址为0x10000000,而A核通过mmap映射后得到虚拟地址0x3F000000,则双方在描述符中记录的指针必须统一使用“M核视角地址”或“偏移量”,避免直接传递各自虚拟地址。实践中更稳妥的做法是:描述符中只存相对于共享区基址的偏移,双方各自加上自己的基址后再访问。
三、HSEM:硬件信号量
共享内存是双方都能读写的,若A核正在写一个槽位而M核同时读取,就会读到半新半旧的数据。HSEM(Hardware Semaphore)就是为解决这类互斥问题而设计的。STM32MP1提供32个硬件信号量,每个信号量有独立的锁定/解锁逻辑,且支持“谁锁定谁解锁”的归属检查。
HSEM的典型用法是:访问共享描述符或某个数据槽前,先尝试锁定对应信号量。锁定操作是原子的,若已被对方占用,则返回失败或等待。以HAL库为例:
/* M核尝试锁定信号量5,超时1000ms */
if (HAL_HSEM_FastTake(HSEM_ID_5) == HAL_OK) {
/* 进入临界区:读写共享槽位 */
write_shared_slot(&slot, data, len);
HAL_HSEM_Release(HSEM_ID_5, 0); /* 释放 */
} else {
/* 信号量被A核占用,稍后重试或走异常处理 */
}
需要注意,HSEM只保证“同一时刻只有一个核进入临界区”,它不负责数据搬运,也不产生中断。因此HSEM通常与IPCC配合:先通过HSEM获得访问权,写入共享内存,再通过IPCC发送通知中断,对端收到中断后同样先取HSEM,再读取数据。
四、中断触发机制与协同流程
IPCC的中断触发有两种模式:发送触发和接收触发。发送方写TX寄存器后,硬件自动向接收方产生中断;接收方读取RX寄存器后,RXF标志清除,中断条件解除。若接收方未及时读取,新消息可能覆盖旧消息,因此协议层通常要求“读走即处理”或使用多通道分流。
完整的协同流程可以概括为:发送方锁定HSEM → 写入共享内存数据槽 → 更新描述符指针 → 释放HSEM → 写IPCC TX寄存器触发中断;接收方收到IPCC中断 → 锁定HSEM → 读取描述符与数据 → 释放HSEM → 处理数据并可选地通过另一通道回送应答。整个过程中,HSEM保护共享内存的一致性,IPCC负责事件通知,SRAM承载实际数据。
五、配置要点与常见问题
在设备树中,IPCC和HSEM节点需要正确声明。A核侧通过mbox框架引用IPCC通道,M核侧通过HAL_IPCC_ActivateNotification注册回调。HSEM的分配要避免冲突:建议在项目初期就固定“信号量编号—保护对象”的映射表,例如HSEM0保护控制描述符,HSEM1保护数据槽A,HSEM2保护数据槽B。
常见问题包括:一是地址映射不一致,A核用虚拟地址、M核用物理地址,导致描述符指针错乱;二是忘记在中断中清除RXF标志,造成中断反复触发;三是HSEM锁定后异常路径未释放,形成死锁。排查时可以先确认IPCC通道的TXF/RXF状态位,再检查HSEM的锁定归属寄存器,最后核对共享内存的地址转换表。
总结来看,IPCC、HSEM、共享SRAM三者各司其职:IPCC解决“什么时候通知”,HSEM解决“谁能访问”,SRAM解决“数据放哪里”。只有把三者的配置和时序配合好,才能构建出低延迟、无丢包、无竞态的核间通信链路。