Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
9 years ago

Pause needed between multiple DMA transfers?

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

2 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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...