PL-PS data transfer using AXI-DMA on Zybo-Z7-20 (Xilinx tool set 2018.3, Linux)

# Requirement
- Digilent Zybo-Z7-20 board
- Xilinx tool set 2018 (Vivado, XSDK)
- Linux on Zybo-Z7-20 (See previous articles [(a)][4] and [(b)][5])

# 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"][2] 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][5]. The `#include` should be,

```system_top.dts
/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][1] driver as the interface driver. As in the [README][1], 'xilinx_axidma' requires following node under `amba_pl` node.

```pl.dtsi
		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`. 

```pl.dtsi
			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`

```pl.dtsi
			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][1])
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][5]. 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`



[1]:https://github.com/bperez77/xilinx_axidma
[2]:http://www.fpgadeveloper.com/2014/08/using-the-axi-dma-in-vivado.html
[3]:https://dora.bk.tsukuba.ac.jp/~takeuchi/?%E9%9B%BB%E6%B0%97%E5%9B%9E%E8%B7%AF%2Fzynq%2FDMA%E5%87%A6%E7%90%86
[4]:https://qiita.com/yhmtmt/items/d62756d40544fa4b4fe9
[5]:https://qiita.com/yhmtmt/items/cba5330ad7ded151882d