ARM架构-SRAM的深度理解

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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梅尔文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值