找回密码
 立即注册

使用微信账号登录

只需一步,快速开始

查看: 15|回复: 0

[Nordic] DMA(Direct Memory Access)的具体原理和实现方法是什么

[复制链接]
连续签到天数:1天
签到总天数:5天
签到总奖励:23金币
发表于 8 小时前 | 显示全部楼层 |阅读模式

马上注册,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册  

×
1. DMA 是什么(在 Zephyr / Nordic 里的抽象)
Zephyr 把 DMA(Direct Memory Access)抽象成一个“DMA 控制器 + 多个通道”的驱动接口,用来在内存与内存、内存与外设、外设与外设之间搬运数据,而不需要 CPU 逐字节读写,从而节省 CPU 时间和功耗。[DMA 概述]
接口中定义了传输方向枚举 dma_channel_direction,包括:[dma_channel_direction]
  • MEMORY_TO_MEMORY
  • MEMORY_TO_PERIPHERAL
  • PERIPHERAL_TO_MEMORY
  • PERIPHERAL_TO_PERIPHERAL
  • HOST_TO_MEMORY
  • MEMORY_TO_HOST

以及地址是否递增/不变的枚举 dma_addr_adj:DMA_ADDR_ADJ_INCREMENT、DMA_ADDR_ADJ_DECREMENT、DMA_ADDR_ADJ_NO_CHANGE。[dma_addr_adj]
在 Nordic SoC 上,很多外设(如 SPIM、SAADC 等)通过 EasyDMA 访问 RAM,本质上就是一种专用 DMA 机制,用来让外设直接读写内存而不占用 CPU。[EasyDMA 说明; EasyDMA 讨论]
2. DMA 的软件实现流程(Zephyr API 视角)
Zephyr 提供了一套统一的 DMA API,典型使用步骤如下:[DMA API 函数; DMA 结构体]
  • 准备配置结构体
    • struct dma_block_config:描述一次传输块(源地址、目的地址、长度、地址是否递增等)。
    • struct dma_config:描述通道整体配置(方向、回调函数、优先级、是否循环等)。


  • 配置通道
    int dma_config(const struct device *dev,               uint32_t channel,               struct dma_config *config);

    这一步会把你的配置写入底层 DMA 控制器的寄存器。[dma_config 函数]

  • 启动传输
    int dma_start(const struct device *dev, uint32_t channel);

    调用后,DMA 控制器开始按照配置在后台搬运数据。[dma_start]

  • 在回调中获知完成状态
    通过 dma_callback_t 回调函数获取 DMA_STATUS_COMPLETE、DMA_STATUS_BLOCK、DMA_STATUS_HALF_COMPLETE 等状态。[dma_callback_t 与状态宏]

  • 可选操作
    • dma_reload():在同一通道上重新装载新的 src/dst/size。[dma_reload]
    • dma_suspend() / dma_resume():暂停/恢复传输。[dma_suspend/resume]
    • dma_stop():停止并关闭通道。[dma_stop]



在某些 SoC(如 SF32LB)上,还提供了基于 devicetree 的辅助函数 sf32lb_dma_config_dt()、sf32lb_dma_start_dt() 等,用来从 DT 描述中直接初始化和启动 DMA。[SF32LB DMA 辅助函数]
3. DMA 在具体外设中的应用示例思路
知识源里没有完整代码示例,但给出了几个典型场景:
  • UART 异步 API 使用 DMA:Zephyr 的 UART 异步模式就是通过 DMA 在后台搬运收发缓冲区数据,实现“通信在后台进行,CPU 做别的事”。[UART 异步 API 说明]
  • PCIe 端点使用系统 DMA:pcie_ep_dma_xfer() 用系统 DMA 在“映射的主机内存”和本地设备内存之间搬运数据,本质上也是配置 DMA 源地址、目的地址和方向,然后启动传输。[pcie_ep_dma_xfer]
  • Nordic EasyDMA 外设:如 SPIM/SAADC 驱动内部会配置 EasyDMA 的源/目的地址寄存器,让外设自动从 RAM 读写数据,用户在 Zephyr 层只看到 SPI/ADC API,不需要直接操作 DMA。[EasyDMA 说明; EasyDMA 讨论]

4. 底层“原理”在当前资料中的缺失
当前知识源没有详细描述 DMA 控制器内部是如何通过总线仲裁、突发传输等机制访问内存的,也没有给出 nRF54L15 或 nRF52/53 系列 DMA 寄存器级手册。因此:
  • 关于“DMA 硬件内部如何实现、总线协议细节”等问题,这里无法给出更底层的解释;
  • 能提供的主要是:在 Zephyr / Nordic SDK 中如何通过统一 API 使用 DMA / EasyDMA 的方法。


楼主热帖
积分商城 - 让您的金币更有价值!||官方Q群 - 让您的沟通更加及时!
您需要登录后才可以回帖 登录 | 立即注册  

本版积分规则

小黑屋|手机版|我爱蓝牙网 - 52Bluetooth

GMT+8, 2026-2-12 18:50 , Processed in 0.541264 second(s), 10 queries , Gzip On, MemCached On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表