DMA330 内存到内存搬运代码
时间: 2024-03-23 19:19:01 浏览: 13
下面是一个简单的DMA330内存到内存搬运代码示例,假设源地址为src_addr,目标地址为dst_addr,搬运大小为size:
```
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#define DMA_BUF_SIZE 4096
void dma_memcpy(void *dst_addr, void *src_addr, size_t size)
{
struct dma_chan *chan;
struct scatterlist sg_src, sg_dst;
dma_addr_t src_dma_addr, dst_dma_addr;
void *dma_buf;
int ret;
dma_buf = dma_alloc_coherent(NULL, DMA_BUF_SIZE, &src_dma_addr, GFP_KERNEL);
if (!dma_buf) {
pr_err("Failed to allocate DMA buffer\n");
return;
}
chan = dma_request_chan(NULL, "dma0");
if (IS_ERR(chan)) {
pr_err("Failed to request DMA channel\n");
dma_free_coherent(NULL, DMA_BUF_SIZE, dma_buf, src_dma_addr);
return;
}
sg_init_table(&sg_src, 1);
sg_set_buf(&sg_src, src_addr, size);
sg_init_table(&sg_dst, 1);
sg_set_buf(&sg_dst, dma_buf, size);
ret = dma_map_sg(chan->device->dev, &sg_src, 1, DMA_TO_DEVICE);
if (ret != 1) {
pr_err("Failed to map SG list for source\n");
dma_release_channel(chan);
dma_free_coherent(NULL, DMA_BUF_SIZE, dma_buf, src_dma_addr);
return;
}
ret = dma_map_sg(chan->device->dev, &sg_dst, 1, DMA_FROM_DEVICE);
if (ret != 1) {
pr_err("Failed to map SG list for destination\n");
dma_unmap_sg(chan->device->dev, &sg_src, 1, DMA_TO_DEVICE);
dma_release_channel(chan);
dma_free_coherent(NULL, DMA_BUF_SIZE, dma_buf, src_dma_addr);
return;
}
ret = dmaengine_prep_dma_memcpy(chan, dst_dma_addr, src_dma_addr, size, DMA_PREP_INTERRUPT);
if (ret) {
pr_err("Failed to prepare DMA transfer\n");
dma_unmap_sg(chan->device->dev, &sg_src, 1, DMA_TO_DEVICE);
dma_unmap_sg(chan->device->dev, &sg_dst, 1, DMA_FROM_DEVICE);
dma_release_channel(chan);
dma_free_coherent(NULL, DMA_BUF_SIZE, dma_buf, src_dma_addr);
return;
}
ret = dmaengine_submit(chan);
if (ret) {
pr_err("Failed to submit DMA transfer\n");
dma_unmap_sg(chan->device->dev, &sg_src, 1, DMA_TO_DEVICE);
dma_unmap_sg(chan->device->dev, &sg_dst, 1, DMA_FROM_DEVICE);
dma_release_channel(chan);
dma_free_coherent(NULL, DMA_BUF_SIZE, dma_buf, src_dma_addr);
return;
}
dma_async_issue_pending(chan);
ret = dma_sync_sg_for_device(chan->device->dev, &sg_src, 1, DMA_TO_DEVICE);
if (ret != 1) {
pr_err("Failed to sync SG list for source\n");
}
ret = dma_sync_sg_for_cpu(chan->device->dev, &sg_dst, 1, DMA_FROM_DEVICE);
if (ret != 1) {
pr_err("Failed to sync SG list for destination\n");
}
memcpy(dst_addr, dma_buf, size);
dma_unmap_sg(chan->device->dev, &sg_src, 1, DMA_TO_DEVICE);
dma_unmap_sg(chan->device->dev, &sg_dst, 1, DMA_FROM_DEVICE);
dma_release_channel(chan);
dma_free_coherent(NULL, DMA_BUF_SIZE, dma_buf, src_dma_addr);
}
```
该示例中,首先通过dma_alloc_coherent()函数分配DMA缓冲区,然后通过dma_request_chan()函数请求DMA通道,接着通过sg_init_table()和sg_set_buf()函数初始化源和目标scatterlist。然后通过dma_map_sg()函数将scatterlist映射到DMA地址空间中。接下来,通过dmaengine_prep_dma_memcpy()函数准备DMA传输,并通过dmaengine_submit()函数提交传输。最后,通过dma_async_issue_pending()函数发出异步传输请求,并通过dma_sync_sg_for_device()和dma_sync_sg_for_cpu()函数同步scatterlist。最终,通过memcpy()函数将DMA缓冲区中的数据复制到目标地址中,最后释放DMA资源。