cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
gilles007
Visitor
Visitor
819 Views
Registered: ‎12-11-2018

Axi DMA proxy module

Hello all

I am working on a project to transfer data from DDR to a custom IP (created in HLS) in PL and the goal is to do this from the User Space in PetaLinux. To understand the Axi DMA in user space I first created a simple hardware design with a DMA loopback on a ZedBoard. Implemented this into PetaLinux and added the dma_proxy module that I found on forums (dma-proxy.c.golden). After fixing DMA request channel errors I got into a segmentation fault to test transfers and I dont know where to go from here.

I am a total noobie in embedded Linux and I am trying to understand every step to achieve my goal. It is really hard to learn or experiment within this field, because not all application, drivers, modules out there are understandable or working when implemented. All tips and hints are very welcome.

- dma-proxy.c is the module I currently use, dma-proxy.c.golden would give an error "DMA channel request error" and never load my driver under /dev. So on line 400 in the golden one I changed the 

dma_request_slave_channel(&pdev->dev, name);

to

	dma_cap_mask_t mask;

	/* Zero out the capability mask then initialize it for a slave channel that is
	 * private.
	 */
	dma_cap_zero(mask);
	dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask);


	/* Request the DMA channel from the DMA engine and then use the device from
	 * the channel for the proxy channel also.
	 */
	pchannel_p->channel_p = dma_request_channel(mask, NULL, NULL);

And on line 440

rc = create_channel(pdev, &channels[TX_CHANNEL], "dma_proxy_tx", DMA_MEM_TO_DEV);

	if (rc) 
		return rc;

	rc = create_channel(pdev, &channels[RX_CHANNEL], "dma_proxy_rx", DMA_DEV_TO_MEM);
	if (rc) 
		return rc;

to

rc = create_channel(pdev, &channels[TX_CHANNEL], "axidma0", DMA_MEM_TO_DEV);

	if (rc) 
		return rc;

	rc = create_channel(pdev, &channels[RX_CHANNEL], "axidma1", DMA_DEV_TO_MEM);
	if (rc) 
		return rc;

- In the device tree I inserted the module and changed the dma-channels 'xlnx,device-id = <0>;'  to 0 and 1. I am not sure whether I need to change these ID's so the module or driver knows wich one is TX and which RX. Can someone give me more details on this?

/include/ "system-conf.dtsi"
/ {
	amba_pl: amba_pl {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "simple-bus";
		ranges ;
		axi_dma_0: dma@40400000 {
			#dma-cells = <1>;
			clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
			clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>;
			compatible = "xlnx,axi-dma-7.1", "xlnx,axi-dma-1.00.a";
			interrupt-names = "mm2s_introut", "s2mm_introut";
			interrupt-parent = <&intc>;
			interrupts = <0 29 4 0 30 4>;
			reg = <0x40400000 0x10000>;
			xlnx,addrwidth = <0x20>;
			xlnx,sg-length-width = <0x17>;
			dma-channel@40400000 {
				compatible = "xlnx,axi-dma-mm2s-channel";
				dma-channels = <0x1>;
				interrupts = <0 29 4>;
				xlnx,datawidth = <0x20>;
				xlnx,device-id = <0>;
				xlnx,include-dre ;
			};
			dma-channel@40400030 {
				compatible = "xlnx,axi-dma-s2mm-channel";
				dma-channels = <0x1>;
				interrupts = <0 30 4>;
				xlnx,datawidth = <0x20>;
				xlnx,device-id = <1>;
				xlnx,include-dre ;
			};
		};
	};
	dma_proxy {
	   compatible ="xlnx,dma_proxy";
	   dmas = <&axi_dma_0 0
		   &axi_dma_0 1>;
	  dma-names = "axidma0", "axidma1";
	};
};

Changing the module's code the project builds fine and the DMA request channel error is fixed. I can see the module driver loaded under "/dev/axidma0" & "/dev/axidma1". 

Now the next error I encounter is when I run the test application, proxytest.c.  Everytime I run it, a segmentation fault pops up and it is always a replica of the error log below.Zedboard log.PNG

Any ideas or insights ? Much appreciated.

Gilles

0 Kudos
4 Replies
nsullivan
Contributor
Contributor
796 Views
Registered: ‎10-08-2018

Functions from PL330, which is the built-in DMA on Zynq, appear on the stack trace in that crash.  It looks like the DMA proxy isn't using your AXI DMA but instead using the built-in channels to me, though I'm not sure why.


Nathan Sullivan - Senior Embedded Software Engineer - www.designlinxhs.com
0 Kudos
nsullivan
Contributor
Contributor
794 Views
Registered: ‎10-08-2018

Ah, I see - the dma_request_channel function with no filter (the second NULL argument) will get any channel in the system, you need a specific channel and so need to supply a filter function, or use the dma_request_slave_channel API instead.

I don't know what is causing the crash with the wrong channel, but I would look into why dma_request_slave_channel won't work first.


Nathan Sullivan - Senior Embedded Software Engineer - www.designlinxhs.com
gilles007
Visitor
Visitor
724 Views
Registered: ‎12-11-2018

@nsullivan 

Thank you very much for your reply !

I looked up the API and as you mentioned used the dma_request_slave_channel with success. I also then managed to run the application with the setup attached (same device tree) !

The weird thing is, if I would create the app as c++ it would only execute the app once and the next execute(s) has transmit errors . Any clue on why that would be? The C code runs fine, which I thank you again for your help !

Gilles

0 Kudos
nsullivan
Contributor
Contributor
683 Views
Registered: ‎10-08-2018

Off the top of my head, I don't know why C++ versus C would make a difference.  Do both applications make the same system calls to run DMA?  I would double check with the "strace" program.


Nathan Sullivan - Senior Embedded Software Engineer - www.designlinxhs.com
0 Kudos