使用环境:Vivado 2020.1,Vitis 2020.1
使用开发板:ZYNQ MPSoc 15EG
Demo
Vivado 工程 双DMA回环
开启SG模式,双DMA控制器,开启四个中断。
Vivado工程并无太多设计问题,根据国产开发板的DMA回环工程稍加修改即可。
驱动设计:
驱动采用GitHub公开的版本修改而来。
驱动设备树修改代码如下:
/include/ "system-conf.dtsi"
/ {
};
/* SD */
&sdhci0 {
disable-wp;
no-1-8-v;
};
/* USB */
&dwc3_0 {
status = "okay";
dr_mode = "host";
};
&amba_pl {
axidma_chrdev: axidma_chrdev@0 {
compatible = "xlnx,axidma-chrdev";
dmas = <&axi_dma_0 0 &axi_dma_0 1 &axi_dma_1 0 &axi_dma_1 1>;
dma-names = "tx_channel", "rx_channel", "tx_channel1", "rx_channel1";
};
};
&axi_dma_0 {
dma-channel@80000000 {
xlnx,device-id = <0x0>;
};
dma-channel@80000030 {
xlnx,device-id = <0x1>;
};
};
&axi_dma_1 {
dma-channel@80010000 {
xlnx,device-id = <0x2>;
};
dma-channel@80010030 {
xlnx,device-id = <0x3>;
};
};
应用层代码实现
1 多DMA使用共同初始函数
axidma_dev = axidma_init();
2 分配多DMA传输Buffer空间
// Map memory regions for the transmit and receive buffers
tx_buf = axidma_malloc(axidma_dev, tx_size/2);
if (tx_buf == NULL) {
perror("Unable to allocate transmit buffer from the AXI DMA device.");
rc = -1;
goto destroy_axidma;
}
rx_buf = axidma_malloc(axidma_dev, rx_size/2);
if (rx_buf == NULL) {
perror("Unable to allocate receive buffer from the AXI DMA device");
rc = -1;
goto free_tx_buf;
}
// Map memory regions for the transmit and receive buffers
tx_buf2 = axidma_malloc(axidma_dev, tx_size/2);
if (tx_buf2 == NULL) {
perror("Unable to allocate transmit buffer from the AXI DMA device.");
rc = -1;
goto destroy_axidma;
}
rx_buf2 = axidma_malloc(axidma_dev, rx_size/2);
if (rx_buf2 == NULL) {
perror("Unable to allocate receive buffer from the AXI DMA device");
rc = -1;
goto free_tx_buf;
}
3 分配通道数
tx_chans = axidma_get_dma_tx(axidma_dev);
rx_chans = axidma_get_dma_rx(axidma_dev);
4 进行传输
rc = axidma_oneway_transfer(axidma_dev, tx_channel, tx_buf, tx_size/2,false);
if (rc < 0) {
return rc;
}
rc = axidma_oneway_transfer(axidma_dev, tx_channel2, tx_buf2, tx_size/2,false);
if (rc < 0) {
return rc;
}
//sleep(3);
rc = axidma_oneway_transfer(axidma_dev, rx_channel, rx_buf, rx_size/2,true);
if (rc < 0) {
return rc;
}
rc = axidma_oneway_transfer(axidma_dev, rx_channel2, rx_buf2, rx_size/2,false);
if (rc < 0) {
return rc;
}
最后测试结果如下