FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
Intel Support hours are Monday-Fridays, 8am-5pm PST, except Holidays. Thanks to our community members who provide support during our down time or before we get to your questions. We appreciate you!

Need Forum Guidance? Click here
Search our FPGA Knowledge Articles here.
5914 Discussions

Pause needed between multiple DMA transfers?

Honored Contributor II

I try to sequentially read buffers from PIO at the fastest possible 

speed with NIOS II/f. Everything works fine, however the speed 

seems to be limited to ~25 MB/s, independently of the buffer size. 

The essential part of the C-code is: 



while (Nr < NrBuffers) { 



if ((rc = alt_dma_rxchan_prepare(rxchan, rx_buffer, NrBytes - 1, done, 

NULL)) < 0) { 

printf("Failed to post read request, reason = %i\n", rc); 



while (!rx_done); // wait for transfer to complete 


// necessary pause 






With NrBuffers= 100000 and NrBytes= 1000 ( 

a total of 100 MByes) this takes about 4 s, hence  

the ~25 MB/s. Note that usleep(40) alone accounts  

for the entire 4 s (40E-6x1E5= 4 s). Larger buffers 

need larges pauses, hence the aforementioned 

maximum speed of ~25 MB/s. 


However, with the shorter pause usleep(30) 

alt_dma_rxchan_prepare gives error message -28= 

ENOSPC= No space left on device. In addition, 

the program starts at the top, resulting in an 

infinite loop of starts and ENOSPC messages.  


On the other hand, usleep(30) with a small  

NrBuffers= 5 works fine. 


Apparently, calling many alt_dma_rxchan_prepare's  

too fast (although the data is transferred) after  

each other is upsetting things seriously. 


I tried to adjust some settings of the DMA core 

(enable burst transfers, larger FIFO depth) to no 



Any idea how I can solve this? 



0 Kudos
2 Replies
Honored Contributor II

Your description sounds like you have a bug in your done() callback and rx_done handshake. For example, you might get the behavior you described if you had never reset rx_done back to zero before starting the next transfer.

Honored Contributor II

You are completely right, thanks! I copied the done() and rx_done part from somewhere  

without giving it sufficient attention. By resetting rx_done back to 0 when needed  

I can now omit the usleep(). However, I still am stuck at the ~25 MB/s. The next