3、MCU内部DMA架构:常见MCU(STM32/ESP32)DMA通道分配、DMA请求映射表、DMA优先级管理

在驱动LCD TFT屏时,DMA(直接存储器访问)是提升帧率、降低CPU负载的核心硬件单元。不同MCU的DMA架构差异显著,直接影响通道分配策略、请求映射关系以及优先级仲裁逻辑。本章以STM32(F4/H7系列)和ESP32(双核Xtensa)为例,深入解析其内部DMA架构,为后续LCD传输优化奠定硬件基础。

3.1 STM32 DMA架构:多通道与请求映射

STM32采用多流多通道的DMA控制器设计,以STM32F4为例,包含2个DMA控制器(DMA1和DMA2),每个控制器拥有8个数据流(Stream),每个数据流可配置最多8个通道(Channel)。DMA2通常挂载在AHB总线上,专用于高带宽外设(如DCMI、LCD-TFT控制器)。

关键概念: STM32的“数据流”是独立的DMA传输引擎,每个数据流拥有自己的FIFO、仲裁器和传输状态机;“通道”则是外设请求的入口,通过软件配置将特定外设请求映射到指定数据流。

3.1.1 STM32F4 DMA通道分配与请求映射表

下表列出了STM32F4中与LCD驱动强相关的DMA请求映射关系(DMA2数据流0~3):

DMA控制器 数据流 通道 外设请求 LCD相关用途
DMA2 Stream 0 CH0 SPI1_TX / SPI2_TX / I2S2_ext SPI接口LCD数据发送
DMA2 Stream 1 CH0 SPI1_RX / SPI2_RX SPI接口LCD数据接收(读寄存器)
DMA2 Stream 3 CH5 LTDC_Layer1 / LTDC_Layer2 LTDC控制器图层数据搬运(F429/F469)
DMA2 Stream 5 CH3 DCMI 摄像头数据采集(间接用于LCD显示)
DMA2 Stream 6 CH1 SPI3_TX / I2S3_ext 备用SPI接口LCD数据发送
优化要点: 对于SPI接口的LCD,优先选择DMA2的Stream 0或Stream 6,因为它们挂载在AHB高速总线上,且支持8字节FIFO,可减少总线占用冲突。避免使用DMA1的Stream,因其挂载在APB桥接后,带宽受限。

3.1.2 STM32H7 DMA架构升级:MDMA与BDMA

STM32H7系列引入了更复杂的DMA层级:DMA1/DMA2(双AHB端口)、MDMA(主DMA)和BDMA(后备DMA)。对于LCD驱动,MDMA可直接在AXI SRAM与LTDC帧缓冲区之间进行64字节突发传输,极大提升带宽利用率。

避坑指南: H7的DMA请求映射表比F4复杂约3倍,每个数据流支持多达16个通道请求。配置时务必查阅参考手册的“DMA request mapping”章节,错误映射会导致传输无响应或数据错位。

3.2 ESP32 DMA架构:双核与GDMA

ESP32采用GDMA(通用DMA)架构,共有5个独立的DMA控制器(GDMA0~GDMA4),每个控制器支持4个通道。与STM32不同,ESP32的DMA通道直接与特定外设绑定,无需手动映射请求表,但通道数量有限,需合理分配。

3.2.1 ESP32 DMA通道分配表

GDMA控制器 通道 绑定外设 LCD驱动用途
GDMA0 CH0 SPI2(HSPI) 主SPI接口LCD数据发送(推荐)
GDMA0 CH1 SPI2(HSPI) SPI双线/四线模式数据收发
GDMA1 CH0 SPI3(VSPI) 备用SPI接口LCD数据发送
GDMA2 CH0 I2S0 I2S接口LCD(如ILI9488并行模式)
GDMA3 CH0 LCD_CAM(ESP32-S3特有) 8/16位并行LCD接口(S3专用)
ESP32特有机制: GDMA支持链表描述符(Linked List Descriptor),允许将多个不连续的内存缓冲区串联成一次DMA传输。对于LCD驱动,可将显存中的多个矩形区域(脏矩形)通过链表一次性发送,减少CPU中断次数。

3.3 DMA优先级管理:仲裁策略与实时性

DMA优先级管理直接影响LCD刷屏的实时性和稳定性。不同MCU的仲裁策略差异较大,需根据外设实时性需求合理配置。

3.3.1 STM32优先级管理:4级可编程 + 硬件轮询

STM32每个DMA数据流支持4级优先级(Very High / High / Medium / Low),同优先级下采用硬件轮询(Round-Robin)机制。对于LCD驱动,建议将LTDC或SPI TX的数据流设置为Very High,避免被其他外设(如UART、ADC)打断导致屏幕撕裂。

// STM32 HAL库DMA优先级配置示例
hdma_spi_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_spi_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
HAL_DMA_Init(&hdma_spi_tx);
优化技巧: 当同时使用SPI DMA和LTDC DMA时,将LTDC设置为Very High,SPI设置为High。LTDC需要严格的时序保证,任何延迟都会导致屏幕刷新不同步。

3.3.2 ESP32优先级管理:固定优先级 + 可配置权重

ESP32的GDMA采用固定优先级模式,通道0优先级最高,通道3最低。但ESP32-S3引入了权重轮询(Weighted Round-Robin),可通过寄存器配置每个通道的权重值(1~15),实现更精细的带宽分配。

MCU型号 优先级模式 LCD推荐配置 注意事项
STM32F4 4级可编程 + 轮询 Very High(LTDC/SPI TX) 同优先级下轮询,避免过多高优先级外设
STM32H7 8级可编程 + 轮询 Level 0(最高,MDMA) MDMA优先级高于DMA1/2,适合大块显存搬运
ESP32 固定优先级(0最高) GDMA0 CH0(SPI2) 避免将低优先级外设与LCD共用同一GDMA
ESP32-S3 权重轮询(1~15) 权重15(LCD_CAM) 权重值越大,占用带宽越高

3.4 DMA架构对比与LCD驱动选型建议

综合上述分析,下表总结了STM32与ESP32在LCD驱动场景下的DMA架构差异:

对比维度 STM32(F4/H7) ESP32(S3)
DMA控制器数量 2~3个(DMA1/2/MDMA) 5个(GDMA0~4)
通道/数据流数量 8数据流 × 8通道 4通道/控制器
请求映射方式 软件配置映射表 硬件绑定外设
链表传输 支持(双缓冲/循环模式) 支持(链表描述符)
优先级粒度 4~8级可编程 固定/权重轮询
LCD最佳匹配接口 LTDC + DMA2 / SPI + DMA2 SPI + GDMA0 / LCD_CAM + GDMA3
选型建议: 对于需要高帧率(>60fps)的LCD驱动,优先选择STM32H7的MDMA+LTDC组合,或ESP32-S3的LCD_CAM+GDMA3组合。对于低成本的SPI接口LCD,STM32F4的DMA2+SPI或ESP32的GDMA0+SPI2均可满足30fps的刷新需求。
STM32 vs ESP32 DMA架构对比(LCD驱动视角) STM32(F4/H7) DMA1 8 Stream × 8 Ch DMA2 8 Stream × 8 Ch MDMA(H7特有) AXI总线 · 64字节突发 SPI1/2/3 LTDC DCMI ESP32(S3) GDMA0~4 5个独立控制器 每控制器4通道 固定优先级/权重 SPI2(HSPI) SPI3(VSPI) I2S0 LCD_CAM(S3) 关键差异 • STM32:多数据流 + 可编程映射,配置灵活 • ESP32:硬件绑定 + 链表描述符,开发简便 • 优先级:STM32可编程 vs ESP32固定/权重

3.5 实际案例:STM32F4 SPI LCD的DMA通道配置流程

以下是一个完整的DMA通道配置流程,用于驱动320×240 SPI接口LCD(如ILI9341):

  1. 选择DMA控制器: 使用DMA2(AHB高速总线),数据流Stream 0,通道CH0(SPI1_TX)。
  2. 配置传输参数: 方向:内存到外设;数据宽度:8位(SPI数据寄存器为8位);突发模式:使能4字节突发。
  3. 设置优先级: Very High,确保刷屏不被其他中断打断。
  4. 使能FIFO: 设置FIFO阈值为Full(4字节),减少总线访问次数。
  5. 链接显存缓冲区: 使用双缓冲模式,交替填充显存,避免DMA传输间隙。
// 完整DMA初始化代码片段(基于STM32 HAL)
DMA_HandleTypeDef hdma_spi_tx;

void MX_DMA_Init(void)
{
    __HAL_RCC_DMA2_CLK_ENABLE();

    hdma_spi_tx.Instance = DMA2_Stream0;
    hdma_spi_tx.Init.Channel = DMA_CHANNEL_0;          // SPI1_TX
    hdma_spi_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi_tx.Init.Mode = DMA_NORMAL;                // 或DMA_CIRCULAR
    hdma_spi_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
    hdma_spi_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_spi_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_spi_tx.Init.MemBurst = DMA_MBURST_INC4;       // 4字节突发
    hdma_spi_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;

    HAL_DMA_Init(&hdma_spi_tx);

    // 将DMA句柄与SPI关联
    __HAL_LINKDMA(&hspi1, hdmatx, hdma_spi_tx);
}
验证方法: 配置完成后,使用逻辑分析仪抓取SPI时钟和数据线,观察DMA传输是否连续无间隔。若出现间隔,检查FIFO阈值和突发大小是否匹配外设FIFO深度。
STM32F4 SPI LCD DMA通道配置流程 选择DMA2 Stream 0 · CH0 配置传输参数 Mem→Periph · 8位 设置优先级 Very High 使能FIFO 阈值Full · 4B突发 链接显存缓冲区 双缓冲模式 传输启动 DMA自动搬运显存数据至SPI发送寄存器

3.6 常见问题与排查方法

  • DMA传输未启动: 检查外设请求是否使能(如SPI_CR2的TXDMAEN位),以及DMA通道映射是否正确。
  • 数据错位或丢失: 检查数据宽度是否匹配(外设寄存器宽度 vs 内存宽度),以及FIFO阈值是否设置合理。
  • 屏幕撕裂(Tearing): 在STM32中,将LTDC或SPI TX的DMA优先级提升至最高;在ESP32中,使用最高优先级通道并避免与其他高带宽外设共用GDMA。
  • DMA中断频繁: 使用双缓冲或循环模式,减少传输完成中断次数;或使用链表描述符(ESP32)合并多次传输。
本章小结: STM32的DMA架构以“多数据流+可编程映射”为特点,适合复杂外设组合场景;ESP32的GDMA以“硬件绑定+链表描述符”为优势,开发更简洁。优先级管理是LCD实时刷新的关键,务必根据外设带宽需求合理分配。下一章将深入DMA传输模式(单次/循环/双缓冲)对LCD刷屏性能的影响。