## 引言 随着物联网与边缘计算的发展,单核 MCU 在复杂任务处理与低功耗要求之间常陷入两难。STM32H7 系列(如 STM32H745/755)采用 Cortex-M4(主核,高性能)与 Cortex-M0+(从核,低功耗)的双核架构,通过高效的通信机制实现任务分工。本文将聚焦于双核通信的核心——IPC(Inter-Processor Communication),从硬件原理到代码实现,助你快速上手。 ## 一、双核架构概览 STM32H7 双核 MCU 内部集成两个独立内核: - **Cortex-M4**:主核,运行复杂算法(如 AI、DSP),主频可达 480MHz。 - **Cortex-M0+**:从核,处理低功耗任务(如传感器采集、通信协议),主频 240MHz。 两核共享外设(如 GPIO、ADC)和内存(SRAM),但各自拥有独立的中断控制器(NVIC)。协同工作的核心在于**通信机制**,主要包括: - **硬件邮箱(Mailbox)**:用于发送短消息和中断触发。 - **共享内存(Shared SRAM)**:用于大数据交换。 - **信号量(Semaphore)**:通过硬件互斥保证数据一致性。 ## 二、通信机制原理 ### 1. 硬件邮箱(HSEM) 硬件信号量(HSEM)模块提供 32 个互斥信号量,用于保护共享资源。每个信号量可被任一核获取/释放,支持中断通知。 ### 2. 共享内存 双核通过 AHB 总线矩阵访问共享 SRAM(如 D1 域 SRAM)。为避免冲突,需使用 HSEM 进行互斥访问。 ### 3. 核间中断(IPCC) IPCC(Inter-Processor Communication Controller)提供双向通道,每个通道有发送/接收寄存器,可触发对方核的中断,实现事件同步。 ## 三、配置步骤(以 STM32H745 为例) ### 1. 硬件连接 - 使用 STM32H745 开发板,两核均连接调试器(SWD 多核调试)。 - 确保电源稳定,共享 SRAM 区域在链接脚本中分配。 ### 2. 软件初始化流程 1. **使能时钟**:RCC 中使能 HSEM 和 IPCC 时钟。 2. **配置共享内存**:在链接脚本中定义共享 SRAM 段(如 `SHARED_SRAM`)。 3. **初始化 HSEM**:设置信号量初始值。 4. **配置 IPCC**:使能通道,注册中断回调。 5. **启动双核**:主核通过 `HAL_HSEM_FastTake` 控制从核启动。 ## 四、完整代码示例 以下代码演示主核(M4)与从核(M0+)通过共享内存和 HSEM 交换数据,并通过 IPCC 触发中断。 ### 主核代码(M4) ```c /* main.c - M4 内核 */ #include "stm32h7xx_hal.h" /* 共享内存区域,定义在链接脚本中 */ #define SHARED_ADDR 0x30040000 volatile uint32_t *shared_data = (uint32_t *)SHARED_ADDR; void IPCC_IRQHandler(void) { HAL_IPCC_IRQHandler(); // 处理从核发来的数据 uint32_t val = *shared_data; // 释放信号量 HAL_HSEM_Release(HSEM_ID_0, 0); } int main(void) { HAL_Init(); __HAL_RCC_HSEM_CLK_ENABLE(); __HAL_RCC_IPCC_CLK_ENABLE(); // 初始化 HSEM HAL_HSEM_Init(); // 获取信号量,保护共享内存 HAL_HSEM_FastTake(HSEM_ID_0); *shared_data = 0x1234; HAL_HSEM_Release(HSEM_ID_0, 0); // 配置 IPCC 通道 HAL_IPCC_Init(); HAL_IPCC_ActivateNotification(IPCC_CHANNEL_1, IPCC_FLAG_RX); HAL_NVIC_EnableIRQ(IPCC_IRQn); // 启动从核(通过 HSEM 触发) HAL_HSEM_FastTake(HSEM_ID_1); // 从核复位释放 HAL_RCC_EnableCSS(); // 示例,实际使用复位控制 while(1) { // 主循环 } } ``` ### 从核代码(M0+) ```c /* main.c - M0+ 内核 */ #include "stm32h7xx_hal.h" #define SHARED_ADDR 0x30040000 volatile uint32_t *shared_data = (uint32_t *)SHARED_ADDR; void IPCC_IRQHandler(void) { HAL_IPCC_IRQHandler(); // 读取共享数据 uint32_t val = *shared_data; // 处理数据... // 发送响应 *shared_data = val + 1; // 触发主核中断 HAL_IPCC_Notify(IPCC_CHANNEL_1); } int main(void) { HAL_Init(); __HAL_RCC_HSEM_CLK_ENABLE(); __HAL_RCC_IPCC_CLK_ENABLE(); HAL_HSEM_Init(); HAL_IPCC_Init(); HAL_IPCC_ActivateNotification(IPCC_CHANNEL_1, IPCC_FLAG_RX); HAL_NVIC_EnableIRQ(IPCC_IRQn); while(1) { // 低功耗任务 __WFI(); } } ``` ### 链接脚本片段(共享内存) ```c /* 在 .ld 文件中添加 */ SHARED_SRAM (xrw) : ORIGIN = 0x30040000, LENGTH = 16K ``` ## 五、注意事项 - **内存一致性**:双核访问共享内存时,需使用 HSEM 互斥,避免数据竞争。 - **中断优先级**:IPCC 中断优先级应合理设置,避免死锁。 - **启动顺序**:主核必须确保从核复位释放后再通信,否则可能崩溃。 - **调试技巧**:使用多核调试器(如 ST-Link 的 multi-core 支持)分别观察两核状态。 - **功耗优化**:从核在空闲时进入 WFI,由 IPCC 唤醒,降低功耗。 ## 六、总结 STM32 双核架构通过 HSEM、共享内存和 IPCC 实现了高效、安全的核间通信。开发者需理解硬件机制,并合理设计数据流与同步策略。本文提供的示例可作为基础模板,实际项目中可根据需求扩展为消息队列或环形缓冲区。掌握双核协同,将显著提升系统性能与灵活性。