我从互联网上找到了这段代码,用于 DMA 从内存传输到内存 这段代码工作正常
#include <linux/module.h>
#include <linux/init.h>
#include <linux/completion.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
void my_dma_transfer_completed(void *param)
{
struct completion *cmp=(struct completion *)param;
complete(cmp);
printk("dma transfer completed callback\n");
}
static int __init dma_init (void)
{
struct dma_device *dma_dev;
dma_cap_mask_t mask;
struct dma_chan *chan;
struct dma_async_tx_descriptor *chan_desc;
dma_cookie_t cookie;
dma_addr_t src_addr,dst_addr;
u8 *src_buf, *dst_buf;
struct completion cmp;
int status;
printk(KERN_INFO "Loading module \n");
dma_cap_zero(mask);
dma_cap_set(DMA_MEMCPY,mask);
chan=dma_request_channel(mask,NULL,NULL);
if(!chan)
{
printk("chan request error\n");
return ENODEV;
}
dma_dev = chan->device;
src_buf=dma_alloc_coherent(chan->device->dev,1024,&src_addr,GFP_KERNEL);
dst_buf=dma_alloc_coherent(chan->device->dev,1024,&dst_addr,GFP_KERNEL);
memset(src_buf,0x12,1024);
memset(dst_buf,0x00,1024);
printk("Before %x\n",src_buf[0]);
printk("Before %x\n",dst_buf[0]);
chan_desc=dma_dev->device_prep_dma_memcpy(chan,dst_addr,src_addr,1024,DMA_MEM_TO_MEM);
if(!chan_desc)
{
printk("chan desc request error\n");
status=-1;
goto free;
}
init_completion(&cmp);
chan_desc->callback=my_dma_transfer_completed;
chan_desc->callback_param=&cmp;
cookie=dmaengine_submit(chan_desc);
dma_async_issue_pending(chan);
if(wait_for_completion_timeout(&cmp,msecs_to_jiffies(3000)) <= 0)
{
printk("timout\n");
status=-1;
}
status=dma_async_is_tx_complete(chan,cookie,NULL,NULL);
if(status==DMA_SUCCESS)
{
printk("complete %d\n",status);
status=0;
printk("After %x\n",src_buf[0]);
printk("After %x\n",dst_buf[0]);
}
else
{
printk("transfer error\n");
}
dmaengine_terminate_all(chan);
free:
dma_free_coherent(chan->device->dev,1024,src_buf,src_addr);
dma_free_coherent(chan->device->dev,1024,dst_buf,dst_addr);
dma_release_channel(chan);
return 0;
}
static void __exit dma_exit (void)
{
printk(KERN_INFO "Exitingg module \n");
}
module_init(dma_init);
module_exit(dma_exit);
MODULE_AUTHOR("Saeed Setareh");
MODULE_DESCRIPTION("DMA");
MODULE_LICENSE("GPL");
但是我需要将数据从内存传输到设备(spi,uart,...)或设备到内存的代码 如何修改上面的代码以将数据从内存传输到设备(spi,uart,...)或设备到内存? linux版本是3.4.113,Orange Pi One板
我没有找到任何将数据从内存传输到设备(spi,uart,...)或设备到内存的代码
没有独立于设备、一刀切的 DMA 引擎代码,原因很简单,DMA 传输的设置和管理方式特定于每个设备。某些设备只能在较小的 DMA 窗口上运行。其他的能够在整个总线地址空间上进行分散/聚集操作。一些设备的 DMA 引擎配置有绝对总线地址,其他设备则使用页面大小移位、页面偏移和页面索引的组合。有些设备的 DMA 描述符存储在本地,其他设备将通过辅助收集操作从主机内存等获取 DMA 描述符。
底线是,没有办法熟悉所讨论的特定目标设备,如何在硬件级别配置其 DMA 引擎,然后 - 如果您打算使用 Linux DMA 引擎 - 编写胶水代码来带来这些一起。
您引用的代码是如何使用某些 CPU 上的内存到内存 DMA 引擎的示例。基本上这个东西的作用与
memcpy
相同,但不使用 CPU 周期,并且完全在总线地址上操作,而不是虚拟地址空间。