ESP32-S3 的 GDMA 与 SPI 主机驱动:如何用链式描述符实现零拷贝高速采集

· 2 浏览

回答(4)

如果只是采集,建议直接用 SPI slave + GDMA 从机模式,主机侧用 ESP32-S3 做从机接收,省去主机轮询开销。
FPGA转嵌入式 · 2026-09-25
注意 ESP32-S3 的 GDMA 有独立通道,SPI2/SPI3 各绑定固定通道,别和 LCD/CAM 的 DMA 冲突,否则会丢数据。
硬件小刘 · 2026-09-25
补充一点:ESP-IDF v5.x 的 spi_master 已支持 spi_device_queue_trans 异步模式,配合 DMA 描述符可减少 CPU 干预,但链表仍需手动管理。
嵌入式老张 · 2026-09-25
在 ESP32-S3 上,SPI 主机驱动(spi_master)本身已基于 GDMA,但默认的 spi_device_transmit 是阻塞式且会做数据拷贝。要实现零拷贝高速采集,核心是绕过高层 API,直接操作 SPI 外设的 DMA 链表。步骤:1) 用 heap_caps_malloc(size, MALLOC_CAP_DMA) 分配对齐的接收缓冲区,避免 PSRAM 非 DMA 可达问题;2) 调用 spi_bus_add_device 后,通过 spi_device_get_transaction 或直接配置 SPI_DMA_IN_LINK 寄存器,构建 dma_descriptor_t 链,每个描述符指向一块缓冲区,用 owner/eof 位串联;3) 将描述符链首地址写入 SPI_DMA_IN_LINK_ADDR,设置 SPI_DMA_IN_SUC_EOF_ENA,启动 SPI 传输;4) 传输完成由 DMA 中断触发,在 ISR 中只更新链表尾指针,实现乒乓缓冲。注意:描述符必须 4 字节对齐,缓冲区大小建议 4KB 以内以降低中断延迟;若用 PSRAM,需确认 GDMA 可访问且开启 cache 一致性维护。实测在 40MHz SPI 下可稳定达到 5MB/s 以上零拷贝吞吐。
mcuku 阿沐 · 2026-09-25