06-13-2016 09:16 AM
I am currently trying to store images pictures by a camera in the DDR on a Zynq platform. I am using the Video In to Axis IP and I know that this IP is working because I see the AXI stream coming out with the SOF signal.
I would like to store only one frame (the picture is taken by pulling an external trigger on the camera) in the DDR.
So I am using a VDMA instance and I want to begin the transfer to DDR when the SOF comes up. How should I do that ?
I am not using the MM2S channel (Read) and I set Fsync in TUSER mode.
I am trying to set the VDMAregisters to the correct values (according to the API description and IP User Guide) using the API provided with SDK but I cannot make it work.
Is it possible to use the VDMA without interrupts in my case ?
Should I use parking mode (I didn't find anything on this mode) ?
Thanks for your help !
06-13-2016 10:43 AM
Well the VDMA's primary use case is streaming video, but with a bit of work, you should be able to make it happen.
I'd set it up as a 1 frame buffer and use park mode.
Interrupt handling will be the tricky part because in Fsync on TUSER mode, interrupt is generated at the start of the frame (basically, on tuser). So transferring one frame then parking won't see an interrupt like this. You could use something like this as a possible workaround:
06-16-2016 06:36 AM
Thanks for your answer.
I am using park mode and 1 frame buffer. I still get errors on the interrupt side (internal error and SOF late flag). When I look the AXI Stream coming from my previous IP I can see that the SOF is activated at the same time as the first pixel of the frame and in the VDMA datasheet I see that the VDMA operation is beginning on the falling edge of fsync. So maybe the first pixel is not seen by the VDMA.
The problem is that the AXI Stream is generated by the Video In 2 AXIS IP and, because of that, I cannot change the SOF timing.
Should I try to delay AXI stream signal (except TUSER) ?
06-16-2016 08:47 AM
You shouldn't need to delay data with respect to SOF coming from the Vid2AXIS core.
Does this happen on the very first image you try to capture?
I would be very careful about controlling the sequence of events here. For debugging this type of issue, I would use an ILA like this:
1) Launch SDK debugger and let it stop on main()
- This will let everything get loaded and release ps7 reset if on zynq
2) Read the VDMA status register using xmd. Do you have the error yet? You shouldn't since it hasn't been configured yet so it shouldn't be accepting any pixels
3) Arm an ILA to trigger on tvalid&tready
4) Let the debugger run to allow the cores to be configured and video start flowing.
5) The ILA should eventually trigger. Check the relationship to tuser (maybe post a screenshot of this).
06-20-2016 01:07 AM
06-20-2016 07:25 AM - edited 06-20-2016 07:30 AM
Thanks for the comments. Just to be clear in the context of this thread so as not to confuse Francois' question on this tangent, the solution from that AR is highly likely to work just fine in many use cases. I expect, for example, that Francois is going to wait for IRQ, then go read the frame from top to bottom. Barring some extremely odd condition (which would probably mean something catastrophic has gone wrong and you probably need to throw the frame out and do some exception handling anyway), the last couple transactions from the VDMA will complete before he gets to the last few pixels of the frame with the processor. If, however, your processor might access the VDMA framebuffer directly in random fashion then you are right that we need something else. (Actually, Francois, I just noticed that you had asked about how to do this without interrupts. In that case, it's much simpler. You should be able to poll the status register and wait for halt bit to assert (when using park mode)).
Anyway, Muzzaffer, I was thinking about this a little bit more. One way that you could solve this in the meantime is to have a small and simple running counter of requests and responses (increment on request (i.e. awvalid&awready) and decrement on responses (bvalid&bready). So it will keep a running tally of the number of outstanding requests at any given instant. So now you can get your EOF interrupt (when data is actually to backing memory!) by waiting for assertion on tstvec and then wait for our counter to get to 0 (meaning the response from the last outstanding request from the frame has come in), at which point you assert an actual interrupt to the processor. There is one assumption here that you have enough vblank time to complete all outstanding transactions from the previous frame (i.e. so your counter gets back to zero) before any new requests come in. This is a valid assumption for just most real systems I can think of, but if not, you could still solve it but with slightly more complex management of the counter.
06-21-2016 07:38 AM
I followed your instructions and I set an ILA to monitor the AXI MM bus of the VDMA (M_AXI_S2MM to the DDR) and I saw that the data are transmitted to the HP0 port.
So the VDMA seems to be working fine. However, when I try to read the DDR from the Zynq I cannot see the data (if I restart the application on the Zynq I can see them).
So I think that my problem is not coming from the VDMA but from the processor cache.
When I disable the cache, I am able to see the data in the DDR.
06-21-2016 02:31 PM
Yes, your description of the behavior is normal and expected when using the HP ports. They are not cache coherent so any time the DMA changes backing memory (i.e. DDR) via the HP ports, the processor will then be working with stale cache if it has already fetched that memory region. So you need to deal with that. You can either disable cache (generally not recommended if you care about processor performance), do manual cache flushes, or work with cache-coherent interface (the ACP port).
06-22-2016 03:58 AM
I changed my design to use it in polling mode (as I explained to you I don't really need interruptions).
Now I can see that there is a real problem with VDMA. Indeed my transfers are working because I can see the data in the memory (and the ILA confirms that) but the VDMA engine never halt (as if the frame counter was never reached). I am using the VDMA in park mode with only one frame.
Furthermore, if I trigger another snapshot, the VDMA halt as if the previous frame was not complete (which is not the case).
06-23-2016 02:42 AM
Yes I think that PARK_PTR_REG is properly set. I tried to set PARK_PTR_REG.WrFrmPtrRef to 0 and 1 but it's not working (I didn't set the PARK_PTR_REG.RdFrmPtrRef because I am using only the S2MM channel).
06-27-2016 07:58 AM
Here is the configuration of the VDMA register set if it helps :
PARK_PTR_REG = 0x00000100
S2MM VDMA CR = 0x00001011
S2MM VDMA Start Address (DDR) = 0x00100000
S2MM_VDMA_REG_INDEX = 0x00000000
S2MM VDMA Frame Delay And Stride = 0x00000A20
S2MM VDMA Horizontal Size = 0x00000A20
S2MM_VDMA_IRQ_MASK = 0x00000000
S2MM VDMA Vertical Size = 0x00000798
06-29-2016 04:24 AM - edited 06-29-2016 04:25 AM
When you use fsync mode , for a single frame transfer in park mode , the frame count down does not happen, as it waits for SOF of next frame which does not come. Hence VDMA does not halt,
When the VDMA is in fsync mode (either external FSYNC or SOF on TUSER), the frame boundaries are defined by the fsync/tuser event. From the perspective of the core, the first fsync/tuser pulse initiates the first frame and it does not end until the second fsync/tuser pulse. Therefore, if you are only transferring one frame into memory (and thus only 1 fsync/tuser pulse), the VDMA will not fire an interrupt (until the second frame is started). In other words, to get an interrupt after transferring N frames, the channel will need to see (N+1) frame sync/tuser pulses.
By contrast, in free-run mode, the frame is bounded by the programmed VSIZE. So, once the core has transferred VSIZE number of lines, it will fire an interrupt.
hope this clarifies.
Note: I think your colleague must have raised a service request for this same VDMA halt issue. I have explained him the same.