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控制器)。
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数据发送 |
3.1.2 STM32H7 DMA架构升级:MDMA与BDMA
STM32H7系列引入了更复杂的DMA层级:DMA1/DMA2(双AHB端口)、MDMA(主DMA)和BDMA(后备DMA)。对于LCD驱动,MDMA可直接在AXI SRAM与LTDC帧缓冲区之间进行64字节突发传输,极大提升带宽利用率。
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专用) |
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);
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 |
3.5 实际案例:STM32F4 SPI LCD的DMA通道配置流程
以下是一个完整的DMA通道配置流程,用于驱动320×240 SPI接口LCD(如ILI9341):
- 选择DMA控制器: 使用DMA2(AHB高速总线),数据流Stream 0,通道CH0(SPI1_TX)。
- 配置传输参数: 方向:内存到外设;数据宽度:8位(SPI数据寄存器为8位);突发模式:使能4字节突发。
- 设置优先级: Very High,确保刷屏不被其他中断打断。
- 使能FIFO: 设置FIFO阈值为Full(4字节),减少总线访问次数。
- 链接显存缓冲区: 使用双缓冲模式,交替填充显存,避免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);
}
3.6 常见问题与排查方法
- DMA传输未启动: 检查外设请求是否使能(如SPI_CR2的TXDMAEN位),以及DMA通道映射是否正确。
- 数据错位或丢失: 检查数据宽度是否匹配(外设寄存器宽度 vs 内存宽度),以及FIFO阈值是否设置合理。
- 屏幕撕裂(Tearing): 在STM32中,将LTDC或SPI TX的DMA优先级提升至最高;在ESP32中,使用最高优先级通道并避免与其他高带宽外设共用GDMA。
- DMA中断频繁: 使用双缓冲或循环模式,减少传输完成中断次数;或使用链表描述符(ESP32)合并多次传输。