STM32H753 的存储系统分为三个域:
D1 Domain:高性能域,直接连接 Cortex-M7 内核,包含 AXI 总线、Flash 和部分 SRAM(ITCM、DTCM、AXI)。
- AXI SRAM:可被 Cache 缓存(需通过 MPU 配置为可缓存,建议开启)。可作为系统内存,用于堆栈全局变量的使用。
- ITCM(Instruction):存放实时任务代码(一般是中断服务程序)。
- DTCM(Data):存放实时任务数据(对时间敏感,如 PID 控制参数)。
- 参考 STM32H743XIHX_FLASH.ld 文件
D2 Domain:外设域,连接大部分外设和 DMA,包含 SRAM1~SRAM3。
- SRAM:访问延迟较高,不建议用Cache,支持 DMA 直接访问,用于外设 DMA 缓冲区,如 UART 接收缓存、ADC 采样数组。
- DMA 控制器的归属:DMA1/DMA2 只能访问 D2 域的 SRAM1~3,无法直接访问 D1 域的 SRAM(如 AXI SRAM),若外设 DMA 直接操作 D1 SRAM,会导致总线带宽被抢占,影响实时任务。外设 DMA 操作 D2 SRAM 时,不会干扰 D1 域的高性能计算。
- 传输到 D1 域的 SRAM场景:ADC 采样数据需实时进行 FFT 运算(FFT 库依赖 AXI SRAM 的高带宽),电机控制算法需要零延迟访问传感器数据。
- 举例验证:
传感器通过 SPI 的 DMA1 将数据存入 SRAM1(D2 域)。
使用 CPU 或 MDMA 将关键数据从 SRAM1 复制到 DTCM-RAM(D1 域)。
实时控制代码直接从 DTCM-RAM 读取数据(零延迟)。
/*----------------------- 内存定义 -----------------------*/
// 定义在D2域SRAM1中的缓冲区(Non-Cacheable)
__attribute__((section(".sram1")))
volatile uint8_t sensorRawData[256]; // SPI接收缓冲区
// 定义在D1域DTCM-RAM中的实时数据(Zero Latency)
__attribute__((section(".dtcm")))
volatile SensorData realtimeSensorData;
/*------------------- 内存域配置说明 -------------------*/
/*
1. SRAM1 (D2域):
- 地址范围: 0x30000000~0x3001FFFF
- 使用DMA1进行数据传输
- 必须声明为volatile防止编译器优化
2. DTCM-RAM (D1域):
- 地址范围: 0x20000000~0x2001FFFF
- 零延迟访问,无Cache一致性问题
- 关键控制变量必须存放于此
3. 使用MDMA跨域传输:
- MDMA是唯一能访问所有存储域的总线主控
- 传输路径:D2→D1(SRAM1→DTCM)
- 比CPU搬运快5倍(实测约2.1GB/s带宽)
*/
/*--------------------- 硬件初始化 ----------------------*/
void System_Init(void) {
// 1. 时钟配置(确保D1/D2域时钟使能)
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; // 使能DMA1(D2域)
RCC->AHB1ENR |= RCC_AHB1ENR_MDMAEN; // 使能MDMA(D1域)
// 2. SPI1初始化(连接传感器)
SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_SPE // 主机模式,SPI使能
| SPI_CR1_BR_0; // 波特率分频
SPI1->CR2 = SPI_CR2_RXDMAEN; // 使能RX DMA
// 3. DMA1初始化(SPI接收→SRAM1)
DMA1_Stream0->CR = DMA_SxCR_CHSEL_0 // Channel 0
| DMA_SxCR_MINC // 内存地址递增
| DMA_SxCR_TCIE // 传输完成中断
| DMA_SxCR_DIR_0; // 外设到内存
DMA1_Stream0->PAR = (uint32_t)&SPI1->DR; // 外设地址
DMA1_Stream0->M0AR = (uint32_t)sensorRawData; // 内存地址(SRAM1)
DMA1_Stream0->NDTR = 256; // 传输数据量
DMA1_Stream0->CR |= DMA_SxCR_EN; // 使能DMA
// 4. MDMA初始化(SRAM1→DTCM-RAM)
MDMA_Channel0->CCR = MDMA_CCR_SINC // 源地址递增
| MDMA_CCR_DINC // 目标地址递增
| MDMA_CCR_TCIE; // 传输完成中断
MDMA_Channel0->CTCR = MDMA_CTCR_SSIZE_0 // 源数据宽度8位
| MDMA_CTCR_DSIZE_0;// 目标数据宽度8位
MDMA_Channel0->CBNDTR = sizeof(SensorData); // 传输长度
MDMA_Channel0->CSAR = (uint32_t)sensorRawData; // 源地址(SRAM1)
MDMA_Channel0->CDAR = (uint32_t)&realtimeSensorData; // 目标地址(DTCM)
}
/*--------------------- 中断服务程序 ---------------------*/
// DMA1传输完成中断(SPI数据已存入SRAM1)
void DMA1_Stream0_IRQHandler(void) {
if (DMA1->LISR & DMA_LISR_TCIF0) {
DMA1->LIFCR = DMA_LIFCR_CTCIF0; // 清除中断标志
// 触发MDMA启动传输(SRAM1→DTCM)
MDMA_Channel0->CCR |= MDMA_CCR_EN; // 使能MDMA传输
}
}
// MDMA传输完成中断(数据已到达DTCM-RAM)
void MDMA_IRQHandler(void) {
if (MDMA->GISR & MDMA_GISR_TCIF0) {
MDMA->GIFCR = MDMA_GIFCR_CTCIF0; // 清除中断标志
// 此处可置标志位通知实时控制循环
realtimeDataReady = 1;
}
}
/*--------------------- 实时控制循环 ---------------------*/
// 在D1域最高优先级执行(禁止中断抢占)
void RealTime_ControlTask(void) {
while (1) {
if (realtimeDataReady) {
// 零延迟读取DTCM数据
float speed = realtimeSensorData.speed;
float position = realtimeSensorData.position;
// 执行控制算法(例如FOC计算)
Motor_ControlAlgorithm(speed, position);
realtimeDataReady = 0;
}
__DSB(); // 确保内存操作完成
}
}
D3 Domain:低功耗域,用于低功耗模式下的数据保持,包含 SRAM4 和 Backup SRAM。