我们正在使用带有集成ARM Cortex-A9双核处理器系统的CycloneV FPGA系统。该处理器系统运行带有4.1内核的angstrom linux,并具有pl330 DMA内核。我们正在尝试编写一个内核模块来使用这个DMAC将数据推送到FPGA架构并从中读取。
写入FPGA工作(尽管速度很慢),但每次我们尝试读取时都会看到读取传输发生,但是linux dmaengine报告超时并且在内核级别,传输永远不会完成。
有人知道为什么会这样吗?我可以注释掉超时逻辑并从中获取数据,所以我猜它可能与缓存一致性或类似的东西有关。
这是我们内核模块中的read函数:
static int dma_start_rx(struct platform_device *pdev, unsigned datalen, unsigned char *databuf, u32 burst_size, bool isDecrypt) {
struct mRiddler_dev *pdata = platform_get_drvdata(pdev);
struct dma_chan *dmaChan;
struct dma_slave_config dmaConf;
struct dma_async_tx_descriptor *dmaDesc = NULL;
dmaChan = pdata->dma_rx_chan;
memset(&dmaConf, 0, sizeof(dmaConf)); // Clear memory for DMA config
// Build DMA configuration
dmaConf.direction = DMA_DEV_TO_MEM;
if (isDecrypt)
dmaConf.src_addr = pdata->dma_datareg_phy + RID_DMA_DATA_READ_DECRYPT;
else
dmaConf.src_addr = pdata->dma_datareg_phy + RID_DMA_DATA_READ_ENCRYPT;
#ifdef DEBUG
pr_info("Accessing device address: %u, based on dma_datareg_phy: %u\n", dmaConf.src_addr, pdata->dma_datareg_phy);
#endif
dmaConf.src_addr_width = 8;
dmaConf.src_maxburst = burst_size;
pdata->dma_rx_addr = dma_map_single(&pdev->dev, databuf, datalen, DMA_FROM_DEVICE);
// Error handling
if (dma_mapping_error(&pdev->dev, pdata->dma_rx_addr)) {
pr_err("dma_map_single for RX failed!\n");
return -EINVAL;
}
// Setup slave config
dmaengine_slave_config(dmaChan, &dmaConf);
// Get DMA descriptor
dmaDesc = dmaengine_prep_slave_single(dmaChan, pdata->dma_rx_addr, datalen, dmaConf.direction, DMA_PREP_INTERRUPT);
// Error handling
if (!dmaDesc) {
dma_shutdown(pdata);
return -ENOMEM;
}
// Set callbacks
dmaDesc->callback = dma_rx_done;
dmaDesc->callback_param = pdata;
// Get cookie and submit transfer to queue
pdata->dma_rx_cookie = dmaengine_submit(dmaDesc);
// Error handling
if (dma_submit_error(pdata->dma_rx_cookie))
pr_err("RX cookie error on dmaengine_submit\n");
#ifdef DEBUG
pr_info("Issueing RX transfer to DMA engine...\n");
#endif
// Start DMA
dma_async_issue_pending(dmaChan);
return 0;
}
编辑:这是设置超时并调用DMA读取功能的地方:
if (numBytes > 0) {
#ifdef DEBUG
pr_info("Calling dma_start_rx with following values: numBytes=%d, burstSize=%d\n", numBytes, burstSize);
#endif
retVal = dma_start_rx(pdata->pdev, numBytes, pdata->dma_rx_buffer, burstSize, false);
if (retVal) {
pr_err("Error starting RX DMA!\n");
return retVal;
}
if (!wait_for_completion_timeout(&dma_read_complete, msecs_to_jiffies(timeout))) {
pr_err("Timeout while waiting for RX DMA\n");
dmaengine_terminate_all(pdata->dma_rx_chan);
return -ETIMEDOUT;
}
*offset = 0;
}
当我尝试从设备读取时,这是dmesg输出:
[ 326.486364] Issueing DMA transfer...
[ 326.489952] DMA TX transfer finished!
[ 335.607286] There are 4 words available in enc_tx FIFO!
[ 335.612497] DMA read 32 > requested bytes 16, adjusting...
[ 335.617992] Now reading 16 bytes in 2 words!
[ 335.622246] Adjusted burstSize/numWords, new values: 2 and 2
[ 335.627898] Calling dma_start_rx with following values: numBytes=16, burstSize=2
[ 335.635283] Accessing device address: 3221225480, based on dma_datareg_phy: 3221225472
[ 335.643168] Issueing RX transfer to DMA engine...
[ 336.643795] Timeout while waiting for RX DMA, cookie: 2