我正在使用SoC将数据从可编程逻辑侧(PL)DMA到处理器侧(PS)。我的整体方案是将两个单独的dma缓冲区和乒乓数据分配给这些缓冲区,以便用户空间应用程序可以访问数据而不会发生冲突。我已经在循环(在kthread中)中使用单个dma事务成功完成了此操作,每个事务在第一个或第二个缓冲区上。我能够通知第一个或第二个缓冲区的poll()方法。
现在我想研究分散 - 聚集和/或循环DMA。
struct scatterlist sg[2]
struct dma_async_tx_descriptor *chan_desc;
struct dma_slave_config config;
sg_init_table(sg, ARRAY_SIZE(sg));
addr_0 = (unsigned int *)dma_alloc_coherent(NULL, dma_size, &handle_0, GFP_KERNEL);
addr_1 = (unsigned int *)dma_alloc_coherent(NULL, dma_size, &handle_1, GFP_KERNEL);
sg_dma_address(&sg[0]) = handle_0;
sg_dma_len(&sg[0]) = dma_size;
sg_dma_address(&sg[1]) = handle_1;
sg_dma_len(&sg[1]) = dma_size;
memset(&config, 0, sizeof(config));
config.direction = DMA_DEV_TO_MEM;
config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
config.src_maxburst = DMA_MAX_BURST_SIZE / DMA_SLAVE_BUSWIDTH_4_BYTES;
dmaengine_slave_config(dma_dev->chan, &config);
chan_desc = dmaengine_prep_slave_sg(dma_dev->chan, &sg[0], 2, DMA_DEV_TO_MEM, DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
chan_desc->callback = sync_callback;
chan_desc->callback_param = dma_dev->cmp;
init_completion(dma_dev->cmp);
dmaengine_submit(chan_desc);
dma_async_issue_pending(dma_dev->chan);
dma_free_coherent(NULL, dma_size, addr_0, handle_0);
dma_free_coherent(NULL, dma_size, addr_1, handle_1);
这适用于通过scatterlist的单次运行,然后在sync_callback中调用call_back。我的想法是将循环列表链接在循环中,但我不会得到回调。
是否有办法为散点列表中的每个描述符进行回调?我想知道我是否可以使用 dmaengine_prep_slave_cyclic (在每次事务后调用回调),但在审查dmaengine.h时,我认为这是针对单个缓冲区的。看DMA Engine API Guide看起来有另一个选项 dmaengine_prep_interleaved_dma 使用 dma_interleaved_template 听起来很有趣但很难找到相关的信息。
最后,我只想以某种方式向用户空间发出关于准备好缓冲区的信号。