Hello everyone,
I'm writing to ask you about some unexpected behaviour when working with the DMA of a Pluto SDR.
The desired functionality is:
* I'm "feeding" the DMA as some data is generated at a rate, lets say, of 1Mbps in the operating system.
* The DMA is "consuming" that data much faster (>5times).
* The expected data at the output would be:
|DDDD 00000000000000000000000 DDDD 0000000000000000000000 DDDD 000000000000000000000000|
where 'D' represents the data generated at the Processing System.
To do this, I'm using the following code:
ssize_t dma_tx_bytes; char *p_dat, *p_end; ptrdiff_t p_inc; if (dma_tx_bytes < 0) { printf("[!] Error pushing buffer DMA %d \n", (int) dma_tx_bytes); iio_ctx_shutdown(); return true; } p_inc = iio_buffer_step(txbuf); p_end = iio_buffer_end(txbuf); p_dat = (char *)iio_buffer_first(txbuf, tx0_i); for (p_dat; p_dat < p_end; p_dat += p_inc) { ((int16_t *) p_dat)[0] = (int16_t) (tf_data[i] << 8 | tf_data[i + 1]); ((int16_t *) p_dat)[1] = IMAG_MASK << 4; } return 0;
which is very similar to the iio_stream.c example, and it is called every time some data is available.
Each data block is 1024 Bytes long and my DMA buffer length is 512.
I have also added an HDL block (image below) that inserts 4 bytes (P) every 4096 bytes, no matter what the information of the DMA is, so that could result in some stream like:
| P 0000 DDDD 00000 | P 0000000000 DD | P DD 0000000000 |
for the HDL block, what I'm doing is forcing low the 'ready' of the axi bus that is visible to the DMA, in order for it to wait until the 'P' signal is sent.
It basically bypasses the tx_upack ready signal that goes to the DMA, but has a counter what every X number of clock cycles forces that signal low, waits for the necessary clock cycles to send the 'P' sequence and then bypasses the ready signal from the tx_upack again.
This block works fine, the 'P' sequence is always inserted every 4096 bytes. When I do not push any data to the DMA I see the | P 00000000000000 | P 0000000000000 | as expected.
The issue:
For some reason, the first 4 bytes of the D data are repeated sometimes. That is, not consistently for every DMA buffer pushing.
After some testing, I found out that this does not happen if I don't use the "insertion" block designed in HDL. I'm almost sure that I'm handling bus correctly.
I don't see how this could mess with the DMA's functioning but I might be missing something.
Some other interesting points are that:
* The repetition (the malfunctioning) does not happen if I "feed" the DMA continuously. That is, if I do not let the 'zeros' appear when the DMA has no more data to transmit. It doesn't happen when the DMA is working in cyclic mode neither.
* When the repetition DOES occur, the transmitted data are of 1028 bytes in length, not corresponding to the size of 1024 bytes that I would expect to see, as it is the buffer length.
* If I make the DMA buffer larger (lets say, 4096), I do not have this issue. The thing is that a buffer that big takes too long to be transmitted, and it would always be almost empty, and it would mean a very inefficient use.
The question:
- Could forcing low the "ready" signal have some impact in how the DMA expects to transmit data and be the cause of this 4 byte repetition?
- Is there anything I could/should do regarding the flushing of the dma buffer?
- Any other thoughts of this strange behaviour?
Added context.
[edited by: zoqueton99 at 5:04 PM (GMT -5) on 10 Nov 2023]