1. STM32多核架构概览:M7与M4如何“双人舞”
各位同学,咱们直接进入正题。STM32H7系列这颗双核芯片,说白了就是一颗芯片里塞了两个“大脑”:一个Cortex-M7,一个Cortex-M4。M7是主将,主频高、性能强,适合跑主算法、复杂控制;M4是副手,功耗低、够灵活,适合做数据采集、外设管理、低功耗后台任务。
我刚开始接触H7时,第一反应是:“这不就是两个单片机连一起吗?”后来发现,事情远没那么简单。两个核怎么分工?怎么通信?怎么不打架?这些才是真正的坑。
1.1 M7与M4的分工哲学
先看一张我手绘的架构图,帮你快速建立整体认知:
从图上你能看到,两个核通过共享RAM交换数据,通过HSEM和MAILBOX传递控制信号。说白了,共享RAM是“黑板”,两个核都在上面写东西;HSEM是“粉笔”,谁拿到粉笔谁才能写;MAILBOX是“传纸条”,一个核写完通知另一个核来看。
1.2 双核通信机制:HSEM与MAILBOX
这里我重点讲两个最常用的通信机制。你想想看,两个核同时往一个变量里写数据,会发生什么?数据错乱、死锁、系统崩溃——我在项目中就吃过这个亏。
HSEM(硬件信号量)
HSEM说白了就是一个硬件锁。M7想访问共享资源时,先“申请”一个信号量;申请成功才能操作,操作完“释放”。M4同理。硬件级别的原子操作,比软件锁可靠得多。
关键点:HSEM是非阻塞的。申请失败立即返回,不会死等。你需要自己决定是重试还是做别的事。
MAILBOX(消息邮箱)
MAILBOX更像一个“门铃”。一个核往邮箱里写消息,然后触发中断通知另一个核。另一个核在中断里读取消息并处理。这种方式适合传递控制命令、状态变化等小数据量信息。
我的习惯:大块数据走共享RAM,控制信号走MAILBOX,同步保护走HSEM。三者配合,基本能覆盖90%的双核通信场景。
1.3 内存架构与共享RAM区域划分
STM32H7的内存布局有点复杂。我把它简化成三个域:
| 域 | 包含 | 谁可以访问 | 典型用途 |
|---|---|---|---|
| D1域 | ITCM、DTCM、AXI SRAM | 仅M7 | M7的代码、紧耦合数据 |
| D2域 | SRAM1、SRAM2、SRAM3 | M7 + M4 + DMA | 双核共享数据、通信缓冲区 |
| D3域 | SRAM4、备份SRAM | M7 + M4 + 低功耗外设 | 低功耗保持数据、唤醒源 |
嗯,这里要注意:D2域是双核通信的主战场。我建议你把共享数据、环形缓冲区、命令队列都放在D2域的SRAM1里。为什么?因为SRAM1支持双核同时访问,且延迟最低。
我曾经踩过的坑:把共享变量定义在D1域,结果M4死活读不到数据。后来才发现D1域默认只对M7开放。记住:共享数据必须放在D2域,且要使用__attribute__((section(".sram1")))指定段。
1.4 双核启动流程
双核启动顺序也有讲究。默认情况下:
- M7先启动,执行SystemInit、初始化时钟、配置外设。
- M7加载M4的代码到D2域(M4的向量表必须放在D2域)。
- M7释放M4的复位,M4开始执行。
- M4初始化自己的外设,然后通过MAILBOX通知M7“我准备好了”。
这个顺序不能乱。我见过有人让M4先跑,结果M4访问的外设时钟还没开,直接HardFault。
1.5 一个简单的双核通信示例
下面是一个M7往共享缓冲区写数据,M4读取的伪代码框架:
// M7端代码
#define SHARED_BUF_ADDR 0x30000000 // SRAM1起始地址
#define BUF_SIZE 256
// 申请HSEM信号量(假设使用HSEM0)
while (HSEM->CR[0] != 0) {
// 等待或做其他事
}
// 写共享数据
uint32_t *buf = (uint32_t *)SHARED_BUF_ADDR;
buf[0] = sensor_value;
// 释放HSEM
HSEM->CR[0] = 0;
// 通过MAILBOX通知M4
MAILBOX->M4_MSG = 0x01;
// M4端代码(在MAILBOX中断中)
void MAILBOX_IRQHandler(void) {
uint32_t msg = MAILBOX->M4_MSG;
if (msg == 0x01) {
// 申请HSEM
while (HSEM->CR[0] != 0);
// 读取共享数据
uint32_t *buf = (uint32_t *)SHARED_BUF_ADDR;
process_data(buf[0]);
// 释放HSEM
HSEM->CR[0] = 0;
}
}
避坑指南:HSEM的申请和释放必须成对出现。我曾经在某个中断里申请了HSEM但忘记释放,结果另一个核永远拿不到锁,整个系统卡死。调试了整整一天才找到原因。
1.6 小结
这一章我们理清了STM32H7双核架构的骨架:M7主控、M4辅助,通过共享RAM交换数据,通过HSEM保证互斥,通过MAILBOX传递事件。内存方面,D2域是双核通信的核心区域,所有共享数据必须放在这里。