【发布时间】:2021-10-10 01:00:49
【问题描述】:
所以我试图在 imx6 上设置与 sai2 fifo 之间的循环传输,但我的 tx 和 rx 完成回调似乎只在传输之前被调用了两次,我的 sai2 寄存器配置和 dmaengine代码如下,任何提示将不胜感激:
Sai2 寄存器(为外部位时钟设置):
tcsr: 3491171329 tcr1:26 tcr2: 0 tcr3:65536 tcr4: 458801 tcr5:522133248 电话:4294967292 rcr2:1073741824 mclk: 0
Dmaengine 代码:
#define HARDWARE_BUFFER_BYTES 64*2 //* 2
#define HARDWARE_BUFFER_PERIOD_BYTES 32*2
static int imx_tx_pingdma_init(struct pi_dma *master, struct device *dev)
{
int err;
dma_addr_t pcm_hardware_reg_base;
const __be32 *addr;
addr = of_get_address(dev->of_node, 0, NULL, NULL);
if (!addr) {
dev_err(dev, "could not get pcm hardware register address\n");
}
pcm_hardware_reg_base = be32_to_cpup(addr);
master->dma_tx = dma_request_slave_channel(dev, "tx");
if (!master->dma_tx) {
dev_err(dev, "no tx-dma configuration found - not using dma mode\n");
tdm_dma_release(master);
return -1;
}
master->dma_rx = dma_request_slave_channel(dev, "rx");
if (!master->dma_rx) {
dev_err(dev, "no rx-dma configuration found - not using dma mode\n");
tdm_dma_release(master);
return -1;
}
/* configure DMAs */
master->tx_ping_buffer =
dma_alloc_coherent(master->dma_tx->device->dev,
HARDWARE_BUFFER_BYTES,
&master->tx_ping_buffer_dma,
GFP_KERNEL);
if (!master->tx_ping_buffer) {
dev_err(dev, "could not allocate dma address\n");
tdm_dma_release(master);
return -1;
}
memset(master->tx_ping_buffer, 0, HARDWARE_BUFFER_BYTES);
master->rx_ping_buffer =
dma_alloc_coherent(master->dma_rx->device->dev,
HARDWARE_BUFFER_BYTES,
&master->rx_ping_buffer_dma,
GFP_KERNEL);
if (!master->rx_ping_buffer) {
dev_err(dev, "could not allocate rx dma address\n");
tdm_dma_release(master);
return -1;
}
memset(master->rx_ping_buffer, 0, HARDWARE_BUFFER_BYTES);
master->dma_tx_slave_config.direction = DMA_MEM_TO_DEV;
master->dma_tx_slave_config.dst_addr = 0x202c000 + 0x20;
master->dma_tx_slave_config.dst_maxburst = 1;
master->dma_tx_slave_config.dst_addr_width = 4;
master->dma_tx_slave_config.src_addr = master->tx_ping_buffer_dma;
master->dma_tx_slave_config.src_maxburst = 1;
master->dma_tx_slave_config.src_addr_width = 4;
err = dmaengine_slave_config(master->dma_tx,
&master->dma_tx_slave_config);
if (err < 0) {
printk("could not setup slave_tx_config\n");
tdm_dma_release(master);
return err;
}
master->dma_rx_slave_config.direction = DMA_DEV_TO_MEM;
master->dma_rx_slave_config.dst_addr = master->rx_ping_buffer_dma;
master->dma_rx_slave_config.dst_maxburst = 1;
master->dma_rx_slave_config.dst_addr_width = 4;
master->dma_rx_slave_config.src_addr = 0x202c000 + 0xa0;
master->dma_rx_slave_config.src_maxburst = 1;
master->dma_rx_slave_config.src_addr_width = 4;
err = dmaengine_slave_config(master->dma_rx,
&master->dma_rx_slave_config);
if (err < 0) {
printk("could not setup slave_rx_config\n");
tdm_dma_release(master);
return err;
}
master->dma_tx_desc =
dmaengine_prep_dma_cyclic(master->dma_tx,
master->tx_ping_buffer_dma,
HARDWARE_BUFFER_BYTES,
HARDWARE_BUFFER_PERIOD_BYTES,
DMA_MEM_TO_DEV,
DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
if (!master->dma_tx_desc) {
printk("could not setup dma_tx_desc\n");
tdm_dma_release(master);
return -1;
}
master->dma_rx_desc =
dmaengine_prep_dma_cyclic(master->dma_rx,
master->rx_ping_buffer_dma,
HARDWARE_BUFFER_BYTES,
HARDWARE_BUFFER_PERIOD_BYTES,
DMA_DEV_TO_MEM,
DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
if (!master->dma_rx_desc) {
printk("could not setup dma_rx_desc\n");
tdm_dma_release(master);
return -1;
}
master->dma_tx_desc->callback = dma_tx_complete;
master->dma_tx_desc->callback_param = master;
master->dma_rx_desc->callback = dma_rx_complete;
master->dma_rx_desc->callback_param = master;
printk("DMA configured by success!\n");
return 0;
}
编辑:我已经尝试增加缓冲区大小,似乎循环 dma 只是在到达缓冲区末尾时停止回调。即如果 period_len=64 且 buff_len 为 64*1024,则 dma 回调将运行 1024 次并暂停。
【问题讨论】:
标签: c linux-device-driver dma imx6