FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6355 Discussions

Pause needed between multiple DMA transfers?

Altera_Forum
Honored Contributor II
1,301 Views

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) { 

Nr++; 

 

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

NULL)) < 0) { 

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

exit(1); 

 

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

 

// necessary pause 

 

usleep(40);  

 

--- 

 

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 

avail.  

 

Any idea how I can solve this? 

 

Thanks! 

Jos
0 Kudos
2 Replies
Altera_Forum
Honored Contributor II
247 Views

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.

0 Kudos
Altera_Forum
Honored Contributor II
247 Views

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 

puzzle...
0 Kudos
Reply