UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Contributor
Contributor
809 Views
Registered: ‎08-28-2014

Zynq dma failure

Jump to solution

I am currently designing an ADC interface to a Cora Z7 that contains a ZYNQ 7010.  Internally I have a test block that generates ADC data to the interface.  The interface connects directly to an AXI dma controller via a stream port.  The burst size of the data is always 8 32-bit words.  As a test I am using the XSCT console to setup the dma for a single burst using scatter-gather.  Whenever I setup the registers and descriptor, an interrupt is generated immediately after I complete the write to the tail descriptor which caused the tready to de-assert.  Consequently, the burst from my test module will not occur.  Below is the sequence of writes I use to setup the dma registers and descriptor


#reset the dma and init
mwr 0x40400030 0x0101dfe6
mwr 0x40400030 0x0101dfe2

#descriptor for s2mm
mwr 0x40000000 0x40000000
mwr 0x40000004 0x00000000
mwr 0x40000008 0x00b00000
mwr 0x4000000c 0x00000000
mwr 0x40000010 0x00000000
mwr 0x40000014 0x00000000
mwr 0x40000018 0x0c000040
mwr 0x4000001c 0x00000000
mwr 0x40000020 0x00000000
mwr 0x40000024 0x00000000
mwr 0x40000028 0x00000000
mwr 0x4000002c 0x00000000
mwr 0x40000030 0x00000000

#start s2mm
#write current descriptor pointer
mwr 0x4040003c 0x00000000
mwr 0x40400038 0x40000000

#start the s2mm engine
mwr 0x40400030 0x0101dfe3

#write tail descriptor pointer
mwr 0x40400044 0x00000000
mwr 0x40400040 0x40000000

 

When I read the S2MM_STATUS register before I send these writes I get 0x00010009.  After the final tail descriptor write the S2MM_STATUS register contains 0x00015019.  The error appears to indicate that there is a problem with the buffer length specified or the length fields not matching.  Can someone explain what I am doing wrong.

0 Kudos
1 Solution

Accepted Solutions
Xilinx Employee
Xilinx Employee
540 Views
Registered: ‎10-04-2016

Re: Zynq dma failure

Jump to solution

Hi @aldopowell,

I tried out your script on a ZC702 board and was able to see the same thing: it appears that the 0xB00000 range is not updated.

I tried two other things and was able to see the correct data.

1. In XSCT, I changed which target read the 0xB00000 range after my transfer completed. If I changed to "ta 1" and "mrd 0xB00000 0x8", I see the correct data. I believe this path goes straight to DRAM and does not pass through the L2 cache.

2. If I disable caching of the 0xB00000 range, I am able to read the correct data with APU1. I run the basic "hello world" application to set up my system before running the DMA transfer script. I added the following line to the hello world application to disable caching:

        Xil_SetTlbAttributes(0xb00000, NORM_NONCACHE);

This is a coherency problem, but I'm having a hard time figuring out why. I'm just not sure how those values are getting into the cache. My hello world application does not run in that region of memory. If I remove the mwr to 0xB00000 from the script, I do not read the correct data from ta 2/APU1. 

If anything, this just goes to show the great pains software has to go through to manage coherency when performing DMA transfers. 

Regards,

Deanna

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------

View solution in original post

15 Replies
Xilinx Employee
Xilinx Employee
741 Views
Registered: ‎10-04-2016

Re: Zynq dma failure

Jump to solution

Hi @aldopowell,

The buffer length looks okay to me. Two thoughts about things to try:

1. When you write the tail descriptor, do you see a difference in behavior if you write the least significant dword before the most significant dword? Try changing your script from this:

#write tail descriptor pointer
mwr 0x40400044 0x00000000
mwr 0x40400040 0x40000000

To this:

#write tail descriptor pointer
mwr 0x40400040 0x40000000
mwr 0x40400044 0x00000000

2. Are there any additional errors reported in the status of the descriptor at address 0x4000_001C? 

Regards,

Deanna

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Contributor
Contributor
729 Views
Registered: ‎08-28-2014

Re: Zynq dma failure

Jump to solution

Your first suggestion of writing 0x40400040 before 0x40400044 resulted with the same error occurring.  The interrupt is generated immediately after I write 0x40400040.  I never get the chance to write 0x40400044.  Also, reading 0x4000001C yields 0x00000000.

0 Kudos
Xilinx Employee
Xilinx Employee
724 Views
Registered: ‎10-04-2016

Re: Zynq dma failure

Jump to solution

Hi @aldopowell,

Could you post a picture of your block diagram and a listing from Address Editor?

Regards,

Deanna

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Contributor
Contributor
702 Views
Registered: ‎08-28-2014

Re: Zynq dma failure

Jump to solution

Here are the pictures you requested.

address edit.JPG
block 1.JPG
block 2.JPG
block 3.JPG
0 Kudos
Xilinx Employee
Xilinx Employee
693 Views
Registered: ‎10-04-2016

Re: Zynq dma failure

Jump to solution

Hi @aldopowell,

Thanks for posting the BD and Address Editor.

Is there a reason you decided to have two BRAM controllers rather than a 2:1 interconnect going to a single BRAM controller? I'm wondering if this is part of the issue.

The tools sometimes do funny things when there are independent address domains talking to the same memory location, which is what your configuration looks like. If you double click on the Block Memory Generator, is it trying to instantiate a 4kB BRAM or an 8kB BRAM?

To debug this theory, I'd stick a System ILA on the Zynq PS M_AXI_GP0 interface and another one on the AXI DMA M_AXI_SG interface. I'd verify that the mwr from xsct get to BRAM as expected. I'd then see what AXI DMA reads back when it fetches the BD from 0x4000_0000. I suspect it is reading back 0s.

Regards,

Deanna

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Contributor
Contributor
653 Views
Registered: ‎08-28-2014

Re: Zynq dma failure

Jump to solution

I made a change to currently simplify the design while I debug this problem.  I have removed the bram and now get the descriptor via a smart connect from the external dram.  The block diagram with the new connections are included.  I have also included pictures of the bus showing the data that the dma controller is reading from the dram.  The first (snap 1.jpg) is the trigger showing the address of the read.  The second (snap 2.jpg) is the read of the data descriptor which appears to be correct.  The third (snap 3.jpg) is a write to address 0x00c0001c.  The last (snap 4.jpg) is the interrupt being generated.  Below is the sequence of accesses I am making to the device to program and start this sequence of events.


#reset the dma and init
mwr 0x40400030 0x0101dfe6
mwr 0x40400030 0x0101dfe2

#descriptor for s2mm
mwr 0x00c00000 0x00c00000
mwr 0x00c00004 0x00000000
mwr 0x00c00008 0x00b00000
mwr 0x00c0000c 0x00000000
mwr 0x00c00010 0x00000000
mwr 0x00c00014 0x00000000
mwr 0x00c00018 0x0c004000
mwr 0x00c0001c 0x00000000
mwr 0x00c00020 0x00000000
mwr 0x00c00024 0x00000000
mwr 0x00c00028 0x00000000
mwr 0x00c0002c 0x00000000
mwr 0x00c00030 0x00000000

#start s2mm
#write current descriptor pointer
mwr 0x4040003c 0x00000000
mwr 0x40400038 0x00c00000

#start the s2mm engine
mwr 0x40400030 0x0101dfe3

#write tail descriptor pointer
mwr 0x40400044 0x00000000
mwr 0x40400040 0x00c00000

I have also included a picture of the address editor values.

 

new address editor values.JPG
new block 1.JPG
snap 1.JPG
snap 2.JPG
snap 3.JPG
snap 4.JPG
0 Kudos
Xilinx Employee
Xilinx Employee
647 Views
Registered: ‎10-04-2016

Re: Zynq dma failure

Jump to solution

Hi @aldopowell,

If you change this line of your script:

mwr 0x00c00018 0x0c004000

to:

mwr 0x00c00018 0x0c000400

Does the transfer succeed? 

If it does, take a look at the configuration GUI for AXI DMA and check the size of the buffer length register. You may need to increase it from the default 14 bits to something larger. axiDMA_bufferLength.JPG

 

Regards,

Deanna

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Contributor
Contributor
636 Views
Registered: ‎08-28-2014

Re: Zynq dma failure

Jump to solution

That appears to resolve that issue.  I no longer get an interrupt immediately after the final write to the tail descriptor pointer.  The data from my test block (dma data.jpg) can now be transferred to dma controller.  The dma controller writes status information (dma response.jpg) indicating the transfer is complete and that 32 bytes have been transferred which is correct.  The next picture (dma data to ps.jpg) shows data written to the slave port on the ps.  The only issue I am seeing now is that although the address (0x00b0_0000) is generated in each picture, when I read those locations for the data I only see that test pattern I placed there before the dma was initiated.

dma data.JPG
dma response.JPG
dma data to ps.JPG
0 Kudos
Xilinx Employee
Xilinx Employee
628 Views
Registered: ‎10-04-2016

Re: Zynq dma failure

Jump to solution

Hi @aldopowell,

I'm glad the transfer is working.

The incorrect data in the write buffer is probably a coherency issue. Depending on how you filled that buffer with initial values, it may reside in the A9 processor cache. The DMA transfer only interacts with DRAM in the Zynq-7000 architecture, so it's likely that you are reading stale data in the cache. Ideally, you would flush the cache before beginning the DMA transfer. I don't know of an easy way to flush the cache from the xsdk command line.

If you change the target with xsdk and read from the write buffer from that target's perspective, however, do you see the correct data? From xsdk, do the "targets" command to see the list of targets and their ID number. Use the "ta" command to select a different master than the A9 you are using. The command would look like "ta 3". I don't have a Zynq-7000 in front of me to give the exact command sequence to use.

Regards,

Deanna 

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Contributor
Contributor
624 Views
Registered: ‎08-28-2014

Re: Zynq dma failure

Jump to solution

I tried what you suggested and still get the same results.  What I notice is that I can read back the descriptor and what I get back is the original with the status word modified indicating that the transfer is complete and the amount of bytes transferred.

0 Kudos
Xilinx Employee
Xilinx Employee
607 Views
Registered: ‎10-04-2016

Re: Zynq dma failure

Jump to solution

I'd expect the descriptor to update okay since that is all handled through the debugger. 

How do you fill the write buffer with the test pattern data?

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Contributor
Contributor
604 Views
Registered: ‎08-28-2014

Re: Zynq dma failure

Jump to solution

I used the debugger to write the following pattern

mwr 0x00b00000 0x01234567
mwr 0x00b00004 0x12345678
mwr 0x00b00008 0x23456789
mwr 0x00b0000c 0x3456789a
mwr 0x00b00010 0x456789ab
mwr 0x00b00014 0x56789abc
mwr 0x00b00018 0x6789abcd
mwr 0x00b0001c 0x789abcde

 

 

 

0 Kudos
Xilinx Employee
Xilinx Employee
584 Views
Registered: ‎10-04-2016

Re: Zynq dma failure

Jump to solution

Hi @aldopowell,

If you don't pre-fill the write buffer at 0xB0_0000, are you then able to read the correct data after the DMA transfer completes?

Regards,

Deanna

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Contributor
Contributor
560 Views
Registered: ‎08-28-2014

Re: Zynq dma failure

Jump to solution

Sorry about the delayed response.  I attempted what you suggested and the results were the same.  I did not write to the target ram locations and after the DMA the data in those locations were not changed.

0 Kudos
Xilinx Employee
Xilinx Employee
541 Views
Registered: ‎10-04-2016

Re: Zynq dma failure

Jump to solution

Hi @aldopowell,

I tried out your script on a ZC702 board and was able to see the same thing: it appears that the 0xB00000 range is not updated.

I tried two other things and was able to see the correct data.

1. In XSCT, I changed which target read the 0xB00000 range after my transfer completed. If I changed to "ta 1" and "mrd 0xB00000 0x8", I see the correct data. I believe this path goes straight to DRAM and does not pass through the L2 cache.

2. If I disable caching of the 0xB00000 range, I am able to read the correct data with APU1. I run the basic "hello world" application to set up my system before running the DMA transfer script. I added the following line to the hello world application to disable caching:

        Xil_SetTlbAttributes(0xb00000, NORM_NONCACHE);

This is a coherency problem, but I'm having a hard time figuring out why. I'm just not sure how those values are getting into the cache. My hello world application does not run in that region of memory. If I remove the mwr to 0xB00000 from the script, I do not read the correct data from ta 2/APU1. 

If anything, this just goes to show the great pains software has to go through to manage coherency when performing DMA transfers. 

Regards,

Deanna

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------

View solution in original post