08-18-2016 06:21 AM - edited 08-18-2016 06:29 AM
In our application we have an AXIS Data fifo's upstream port connect to a DMA controller, to perform S2MM transfers. I've put together a simplfied schematic to make things clear - the pink line is the S2MM path
Our main problem is to know if there is 1 or more words available in the pipeline, before initiating a DMA transfer. We don't want to initiate a transfer when there are 0 words in the pipeline. (for the reason please see at the end).
The DMA IP doesn't seem to have a flag that says 'data available'.
However, the AXIS Data fifo has a 'data count' output ( green line) which reflects the number of datawords residing in the FIFO, so we thought of using this count to find out if there's is data available, and even the exact data count.
Now asume the DMA controller is stopped, and not doing anything.
With an ILA, I found out that if I let's say 10 words entered the fifo through the S_AXIS input, almost immediately 4 words are streamed further towards the DMA controller, I asume this is because the DMA IP has 4 input pipeline registers - can someone confirm this?
Consequence : the axis_data_count value is showing '6' instead of the '10' I would like to see, because that is actually the number of words we could transfer.
We'd like to know, before we initiate a DMA transfer - how many words there are in the fifo+ the pipeline registers. Now that's easy if there are 5 or more words, we could just take the count and subtract 4 to compensate for the pipeline registers. Unfortunately, this does not work for 0 to 4 words ... which is what we need.
The reason for this is within the Xilinx DMA driver : when there are 0 words in the stream available, and we initiate a DMA transfer, Xilinx dma driver timeouts after a while. Which is acceptable, but for some reason, once it has experienced a time out, we start loosing datawords in later DMA transactions. We assume this is caused by a bug in the DMA driver.
We hoped that our workaround was to read the fifo data count through a custom AXI IP (which we implemented and which works fine), but unfortunately for data counts < 4 (= pipeline depth) this workaround does not work.
Also the DMA controller seems to have no flag indicating that 'some' data is available in it's incoming pipeline ... (?)
Any solution for this? How can we know if there is at least 1 word available in the pipeline?
08-18-2016 08:10 AM
With an ILA, I found out that if I let's say 10 words entered the fifo through the S_AXIS input,
almost immediately 4 words are streamed further towards the DMA controller, I asume this is because
the DMA IP has 4 input pipeline registers - can someone confirm this?
Yes, that's correct. This is expected/normal behavior.
Also the DMA controller seems to have no flag indicating that 'some' data is available in it's
incoming pipeline ... (?)
Also correct; no such flag exists.
Are you using the linux driver or is this baremetal?
My first suggestion would be a different direction to solve it: why not program the DMA with the max possible transfer length and then go and read the appropriate registers thereafter to get the actual number of bytes transferred? Don't want to allocate that much memory every time?
Another approach might be to have your upstream IP (or some block between FIFO and DMA) hold off asserting tvalid until it's sure the DMA has been given a command.
08-19-2016 02:51 AM
thanks @bwiec for confirming my thoughts ...
Answer to your question : our issue is with the linux driver.
Your first suggestion is indeed how we use the driver, the dma count is set to the max allowed size (= size of the receiving buffer), and after completion we read the effective nbr of bytes transferred.
however our issue is this : we currently have no separate DMA thread, so we use the DMA driver in a 'blocking mode'. So when we ask the DMA for a transfer, it blocks everything else. I know this is not ideal, but our linux programmer is currently busy on an urgent project, and I have to live with this situation for now.
So what we do is : we set the timeout in the DMA driver very short (like 1ms), and ask the DMA to transfer data. As long as there is data available in the fifo, the DMA works fine. But as soon as there is no data available, the DMA timeouts of course. So far so good, but on the next DMA transfer where there is valid data, there is 1 word 'gone' ... so in case of a timeout, the driver seems to throw away 1 word from the incoming fifo stream (we have used known data like a counter sequence to find this out).
I don't really expect the DMA IP will throw away this single word because of the timeout, my feeling says that this is the driver doing something wrong after a timeout, like incrementing a pointer while it should not have done it, because of the timeout. But I'm not a linux expert unfortunately :-)
Could this ring a bell on your side?
08-19-2016 08:31 AM
From how we use AXI dma the software needs to specify the length of the DMA transfer.
So for example if you are expecting 4 words than the length is 4. Could it be happening that you send a 1-3 words to the DMA and than timeout because you do not have the 4th? IF that is the case after a timeout it would be wise to reset the DMA because in the logic once you give a Tvalid with the remaining words needed the DMA transaction will be completed. Meaning it will have 1-3 entries of stale data (before timeout) and remaining data after timeout.
What you can do is make a custom AXI ip between the Fifo and DMA to control the data going to the dma. For example I would make sure in a custom axi IP that 4 words are in the fifo than I would pop the 4 words and than I would send them as a package of 4 into DMA. This is one way to do this. Or you can just pop the fifo until you get the required amount of data. I would have another control register AXI ip between PS and PL that the PS can poll a register that says data is ready to DMA. Then I would have another bit in a register (That the ps can control to start PL) that initiates the custom IP between the fifo and DMA to send the appropriate AXI (tvalid mainly) to DMA.
These are just ideas but basically you can write custom logic that can fix everything.