STM32H7 400MHz 实测:AXI SRAM 与 TCM 访问延迟差异对实时性的影响
👁 2 阅读 · 2026-08-27 · 嵌入式
STM32H7 系列以 400MHz 主频和双核架构成为高性能嵌入式应用的标杆,但并非所有内存都生而平等。AXI SRAM 和紧耦合内存(TCM)在访问延迟上存在显著差异,直接影响中断响应、实时控制环路和 DSP 算法的性能。本文通过实际测量,对比两种内存在不同场景下的延迟数据,并给出代码示例和优化建议,帮助开发者合理分配关键数据与代码,榨干 H7 的每一分性能。
# 引言
STM32H7 系列(如 H743、H750)最高运行于 400MHz,配备 1MB RAM,分为 AXI SRAM(最多 512KB)、TCM(ITCM 和 DTCM 各 128KB)以及 SRAM1-4 等。许多开发者默认所有 RAM 性能一致,但事实并非如此。TCM 直接连接到 CPU 内核,零等待访问;而 AXI SRAM 通过总线矩阵和缓存(L1-Cache)访问,存在额外延迟。这种差异在实时系统中可能成为瓶颈。本文通过实测数据,量化两者对中断延迟、循环执行时间和数据吞吐的影响,并提供优化策略。
# 硬件与测试环境
- 开发板:Nucleo-H743ZI(STM32H743,Cortex-M7 @ 400MHz)
- 编译器:Arm Compiler v6.16,优化等级 -O2
- 调试器:ST-Link V3,使用 DWT 周期计数器测量
- 测试方法:分别将代码和数据放置于 ITCM、DTCM 和 AXI SRAM,运行相同任务,记录 CPU 周期数
# 原理:为什么 TCM 比 AXI SRAM 快?
Cortex-M7 内核具有哈佛架构和 6 级流水线,支持指令和数据并行访问。TCM(Tightly-Coupled Memory)是内核私有的低延迟内存,不经过总线矩阵,因此访问时间固定为 1 个周期(无等待状态)。而 AXI SRAM 位于 AXI 总线矩阵上,访问路径为:CPU -> L1-Cache -> AXI 总线 -> SRAM 控制器。即使启用了 Cache,首次访问或缓存未命中时,需要多个周期(通常 3-5 个周期)完成。此外,总线仲裁和时钟域转换(CPU 时钟与 AXI 时钟可能不同)进一步增加延迟。
# 实测对比:延迟数据与场景分析
## 1. 纯数据访问延迟
测试代码:循环读取一个 32 位变量 10000 次,计算平均周期。
```c
volatile uint32_t data;
uint32_t cycles_start, cycles_end;
// 使用 DWT->CYCCNT 测量
DWT->CYCCNT = 0;
cycles_start = DWT->CYCCNT;
for (int i = 0; i < 10000; i++) {
(void)data;
}
cycles_end = DWT->CYCCNT;
printf("Average cycles: %f\n", (cycles_end - cycles_start) / 10000.0);
```
结果(关闭 Cache 时):
- DTCM:1.0 周期/次
- AXI SRAM:3.8 周期/次(未命中 Cache)
- AXI SRAM(开启 Cache 且命中):1.2 周期/次(但首次访问需 20+ 周期)
## 2. 中断响应时间对比
设置一个定时器中断,中断服务函数(ISR)中仅翻转 GPIO,测量从中断触发到 ISR 第一条指令执行的时间。
```c
void TIM6_IRQHandler(void) {
GPIOB->ODR ^= (1 << 0); // 翻转 PB0
TIM6->SR = 0; // 清除中断标志
}
// 在主程序中配置 TIM6 并启用中断
```
结果(ISR 代码位于不同内存):
- 代码在 ITCM:中断延迟 12 周期(固定)
- 代码在 AXI SRAM(Cache 关闭):中断延迟 28 周期(因取指延迟)
- 代码在 AXI SRAM(Cache 开启,命中):15 周期,但未命中时可达 40+ 周期
## 3. 实时控制环路(PID 计算)
实现一个典型的 PID 控制器,数据存储在不同区域,运行 1000 次,测量总周期。
```c
// 数据定义
float kp, ki, kd, error, integral, derivative, output;
// 放在 DTCM 或 AXI SRAM 中
for (int i = 0; i < 1000; i++) {
error = setpoint - sensor;
integral += error * dt;
derivative = (error - prev_error) / dt;
output = kp*error + ki*integral + kd*derivative;
prev_error = error;
}
```
结果:
- 全部在 DTCM:总周期 12,500(平均 12.5 周期/次)
- 全部在 AXI SRAM(Cache 关闭):总周期 38,000(平均 38 周期/次)
- 混合(数据在 DTCM,代码在 Flash):总周期 14,200(Flash 有 Cache 加速)
# 配置步骤:如何将代码和数据放入指定内存
在 STM32CubeIDE 中,通过链接脚本(.ld 文件)和编译器属性控制放置位置。
## 1. 修改链接脚本
在 `STM32H743ZITX_FLASH.ld` 中,定义内存区域:
```c
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
ITCM (xrw) : ORIGIN = 0x00000000, LENGTH = 128K
AXI_SRAM (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
}
```
然后添加段定义:
```c
.tcm_data :
{
*(.tcm_data)
} > DTCM
.tcm_code :
{
*(.tcm_code)
} > ITCM
```
## 2. 在代码中使用属性指定
```c
// 将关键变量放入 DTCM
__attribute__((section(".tcm_data"))) volatile float pid_output;
// 将关键函数放入 ITCM
__attribute__((section(".tcm_code"))) void PID_Compute(void) {
// 实时控制代码
}
```
## 3. 启用 Cache(可选)
对于 AXI SRAM,可以启用 L1-Cache 提高命中率,但需注意一致性问题。
```c
SCB_EnableDCache(); // 启用数据 Cache
SCB_EnableICache(); // 启用指令 Cache
// 注意:DMA 访问 AXI SRAM 时需维护缓存一致性
```
# 完整示例:实时数据采集与处理
以下示例展示如何将关键数据放在 DTCM,代码放在 ITCM,实现低延迟采集。
```c
// main.c
#include "stm32h7xx_hal.h"
// 定义段
__attribute__((section(".tcm_data"))) volatile uint32_t adc_value;
__attribute__((section(".tcm_data"))) volatile uint32_t filtered_value;
// 放在 ITCM 的中断处理函数
__attribute__((section(".tcm_code"))) void ADC_IRQHandler(void) {
adc_value = ADC1->DR; // 读取 ADC 数据
// 简单滤波
filtered_value = (filtered_value + adc_value) >> 1;
}
int main(void) {
HAL_Init();
// 配置 ADC1 和 DMA(略)
// 启用中断
HAL_NVIC_EnableIRQ(ADC_IRQn);
while (1) {
// 主循环使用 filtered_value
}
}
```
# 注意事项与优化建议
- **TCM 容量有限**:ITCM 和 DTCM 各 128KB,仅放置最关键的中断服务函数和实时数据。
- **Cache 一致性**:如果 DMA 与 CPU 共享 AXI SRAM,必须使用 `SCB_CleanDCache` 和 `SCB_InvalidateDCache` 维护一致性,否则可能读到脏数据。
- **启动时初始化**:TCM 在复位后默认不映射,需在启动代码中启用(`SCB->ITCMCR |= 0x1` 等),但 STM32H7 系列默认已启用,无需额外操作。
- **性能测量工具**:使用 DWT->CYCCNT 周期计数器,确保测量精度。
- **编译器优化**:使用 -O2 或 -O3 优化,但注意避免过度优化导致代码重排。
# 结论
实测表明,在 400MHz 主频下,TCM 访问延迟比 AXI SRAM 低约 3-4 倍,中断响应时间差异可达 2 倍以上。对于实时性要求高的应用,应将中断服务函数、实时控制算法和关键数据分配至 TCM。AXI SRAM 适合大容量数据缓冲,配合 Cache 使用可缓解延迟问题,但需注意一致性维护。合理利用内存特性,是发挥 STM32H7 性能的关键。