Requirement
- Digilent Zybo-Z7-20 board
- Xilinx tool set 2018 (Vivado, XSDK)
- Linux on Zybo-Z7-20 (See previous articles (a) and (b))
Create AXI-DMA core in Vivado project
First, We need to create a Vivado project for Zybo-Z7-20 with axi-dma core.
The detailed process is explained here in the good article, "Using the AXI DMA in Vivado" with step by step screenshots. Because we execute DMA operation from Linux application, we only need to follow the article to the end of the section "Export the hardware design to SDK".
After exporting hardware, according to my previous articles, we need to create device tree sources using XSDK. The dts
files XSDK automatically created are to be revised a bit.
Modify Device Tree Source
Basically, we need to modify dts
files required to boot Linux as in previous articles. Here we see the additional modifications required to setup AXI-DMA.
In system-top.dts
, we will see the new #include
description comparing to that in the previous article. The #include
should be,
/include/ "pl.dtsi"
In "pl.dtsi", we will find the node for axi_dma_0
which specify the parameters passed to the driver. But the Xilinx driver for axi_dma does not have interfaces for user application. That's why we need to install xilinx_axidma driver as the interface driver. As in the README, 'xilinx_axidma' requires following node under amba_pl
node.
axidma_chrdev: axidma_chrdev@0 {
compatible = "xlnx,axidma-chrdev";
dmas = <&axi_dma_0 0 &axi_dma_0 1>;
dma-names = "tx_channel", "rx_channel";
};
The parameter dmas
is specifying the pair of the dma-channel with their IDs. Though these IDs are the values of xlnx,device-id
in both dma-channel
nodes, auto-generator sets the two values to 0
.
dma-channel@40400000 {
compatible = "xlnx,axi-dma-mm2s-channel";
dma-channels = <0x1>;
interrupts = <0 29 4>;
xlnx,datawidth = <0x20>;
xlnx,device-id = <0x0>;
};
dma-channel@40400030 {
compatible = "xlnx,axi-dma-s2mm-channel";
dma-channels = <0x1>;
interrupts = <0 30 4>;
xlnx,datawidth = <0x20>;
xlnx,device-id = <0x0>;
};
We need to revise xlnx,device-id
in later dma-channel
as 1
dma-channel@40400030 {
compatible = "xlnx,axi-dma-s2mm-channel";
dma-channels = <0x1>;
interrupts = <0 30 4>;
xlnx,datawidth = <0x20>;
xlnx,device-id = <0x1>;
};
Compile the device tree source, and move the created dtb
file to the boot disk.
Build Interface driver (xilinx_axidma)
Clone the repository xilinx_axidma
,
$ git clone https://github.com/bperez77/xilinx_axidma
We need to define the values CROSS_COMPILE
, ARCH
, and KBUILD_DIR
. Our cross compile environment, we only need to source env.sh
in the previous articles. After setting up cross compile environment, we type simply make
at the root of xilinx_axidma
.
$ cd xilinx_axidma
$ make
Following files under xilinx_axidma
should be moved to rootfs
on Zybo-Z7-20.
- driver/axidma.ko
- library/libaxidma.so
- examples/axidma_transfer
Driver installation
Note that axidma.ko
can only be used from root
account, the driver, can be installed simply with
$ insmod axidma.ko
If the axi-dma core is properly installed, following messages can be seen in dmesg
.
$ dmesg | grep "axidma"
[ 25.223219] axidma: loading out-of-tree module taints kernel.
[ 25.225089] axidma: axidma_dma.c: axidma_dma_init: 718: DMA: Found 1 transmit channels and 1 receive channels.
[ 25.225100] axidma: axidma_dma.c: axidma_dma_init: 720: VDMA: Found 0 transmit channels and 0 receive channels.
And device file axidma
is found in /dev
.
$ ls /dev/axidma -la
crw------- 1 root root 245, 0 Mar 18 02:16 /dev/axidma
The driver uses read
, write
interfaces of char device to transfer data between user and kernel region. The detailed programming interface can easily be understood from the source code of the example axidma_transfer
.
axidma_transfer
takes two arguments: one is the input file to be transferred to PL, and another is output file the data came from PL to be written. For example,
$ axidma_transfer test.dtb test2.dtb
AXI DMA File Transfer Info:
Transmit Channel: 0
Receive Channel: 1
Input File Size: 0.01 MiB
Output File Size: 0.01 MiB
Writing output data to `test2.dtb`.
In our design, rx and tx channels are connected via FIFO, the contents of the file test.dtb
is transferred to the FIFO in PL. Immediately, the data is transferred back and stored as the file test2.dtb