一、 DMA使用基本步骤
1. 申请DMA从通道
struct dma_chan *chan = dma_request_chan(dev, "name");
通过设备树、ACPI或板级文件映射表获取指定设备的DMA通道
通道是独占的,直到调用dma_release_channel()释放
2. 配置从设备参数
struct dma_slave_config config = { .direction = DMA_MEM_TO_DEV, .dst_addr = peripheral_addr, // 其他配置...};dmaengine_slave_config(chan, &config);
配置DMA方向、地址、总线宽度、突发长度等
3. 获取传输描述符
根据传输类型选择相应的准备函数:
散列表传输(scatter-gather)
struct dma_async_tx_descriptor *desc;desc = dmaengine_prep_slave_sg(chan, sgl, sg_len, direction, flags);
循环传输(cyclic)
desc=dmaengine_prep_dma_cyclic(chan, buf_addr, buf_len, period_len, direction);
交错传输(interleaved)
desc=dmaengine_prep_interleaved_dma(chan, &xt, flags);
重要注意事项:
对于slave_sg,必须先映射散列表再调用准备函数
准备完成后可添加回调函数
准备和提交操作应紧密配对(中间可能有锁)
4. 可选:附加元数据
根据需求选择元数据模式:
客户端模式(DESC_METADATA_CLIENT)
// 准备数据并附加dmaengine_desc_attach_metadata(desc, metadata_buf, len);
引擎模式(DESC_METADATA_ENGINE)
// 获取引擎的元数据缓冲区void *meta = dmaengine_desc_get_metadata_ptr(desc, &payload, &max_len);// 设置数据长度dmaengine_desc_set_metadata_len(desc, len);
5. 提交传输
dma_cookie_t cookie=dmaengine_submit(desc);
将描述符加入待处理队列
注意:提交后描述符指针归DMA引擎所有,客户端不应再使用
6. 启动传输
dma_async_issue_pending(chan);
激活待处理队列中的传输
传输完成后通过回调函数(如有设置)通知客户端
二 其他重要API:
终止传输
// 异步终止(可从原子上下文调用)dmaengine_terminate_async(chan);// 然后同步等待dmaengine_synchronize(chan);// 同步终止(不可从原子上下文调用)dmaengine_terminate_sync(chan);
暂停/恢复
dmaengine_pause(chan); // 暂停传输dmaengine_resume(chan); // 恢复传输
检查完成状态
dma_async_is_tx_complete(chan, cookie, &last, &used);
以下是使用DMA引擎API进行数据传输的流程总结和流程图:
三、数据传输流程总结
主要步骤:
申请DMA通道-dma_request_chan()
配置从设备参数-dmaengine_slave_config()
准备传输描述符- 根据传输类型选择:
可选:设置元数据- 根据需要选择元数据模式
提交传输-dmaengine_submit()
启动传输并等待完成-dma_async_issue_pending()
关键注意事项:
传输描述符在dmaengine_submit()后会转移到DMA引擎,客户端不应再使用该指针
在准备slave_sg传输前需要先映射散射列表
异步传输的完成通过回调函数通知
提供多种传输终止方式,需根据上下文选择
四、数据传输流程图 带元数据
五、主要API函数说明
| 步骤 | API函数 | 作用 |
|---|
| 通道申请 | dma_request_chan() | 申请独占的DMA通道 |
| 参数配置 | dmaengine_slave_config() | 配置DMA传输参数 |
| 描述符准备 | dmaengine_prep_slave_sg() | 准备散列表传输描述符 |
| dmaengine_prep_dma_cyclic() | 准备循环传输描述符 |
| dmaengine_prep_interleaved_dma() | 准备交错传输描述符 |
| 元数据操作 | dmaengine_desc_attach_metadata() | 附加客户端元数据 |
| dmaengine_desc_get_metadata_ptr() | 获取引擎元数据指针 |
| 提交传输 | dmaengine_submit() | 提交传输到挂起队列 |
| 启动传输 | dma_async_issue_pending() | 启动挂起的传输 |
| 终止传输 | dmaengine_terminate_sync() | 同步终止传输 |
| dmaengine_terminate_async() | 异步终止传输 |
六、时序图概览
以下是DMA客户端(使用者)与DMA引擎框架的完整交互时序图,展示了从初始化到传输完成的完整流程:
七、流程图概览
以下是更详细的时序流程图,包括多个传输场景和错误处理: