Forum Discussion

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

DMA fails to transmit

Hi,

On my Cyclone IV FPGA Development board, I have built a Qsys system with Nios II processor and two standard linear DMAs, and I am DMA'ing data from one on-chip memory buffer to another through a data processing block. After the first pass of the DMA runs, I update the contents in the source buffer and repeat the process. I need to repeat this over several MB of data, so will need to do this a few thousand times. Unfortunately, the process fails after the 3rd iteration of the DMA with this message: "Failed to post CH_DMA transmit request, reason = " (i.e. no error code printed out).

Not sure why the DMA would fail on the 4th pass. Is this a situation anyone has encountered before?

Here is the crux of the code I'm using:

.

.

.

// **************************************************************************

// ENABLE CH_DMA(s)

// **************************************************************************

// Use CH_DMA to move data from CH_FIFO into CH_BUFFER:

if ((CH_dma_txchan = alt_dma_txchan_open("/dev/ch_dma")) == NULL)

{

alt_printf ("Failed to open CH_DMA transmit channel\n");

exit (1);

}

// Create the receive channel

if ((CH_dma_rxchan = alt_dma_rxchan_open("/dev/ch_dma")) == NULL)

{

alt_printf ("Failed to open CH_DMA receive channel\n");

exit (1);

}

// Lock the CH_DMA transmit (ie. read) channel to CH0_FIFO

alt_dma_rxchan_ioctl(CH_dma_rxchan, ALT_DMA_RX_ONLY_ON, (void *)CH_DMA_READ_MASTER_CH_FIFO_BASE);

// **************************************************************************

// ENABLE ABC_DMA:

// **************************************************************************

// Use ABC_DMA to move data from ABC_DATA into ABC_FIFO:

if ((ABC_dma_txchan = alt_dma_txchan_open("/dev/ABC_DMA")) == NULL)

{

alt_printf ("Failed to open ABC_DMA transmit channel\n");

exit (1);

}

// Create the receive channel

if ((ABC_dma_rxchan = alt_dma_rxchan_open("/dev/ABC_DMA")) == NULL)

{

alt_printf ("Failed to open ABC_DMA receive channel\n");

exit (1);

}

// Lock ABC_DMA rx (destination) channel to ABC_FIFO

alt_dma_txchan_ioctl(ABC_dma_txchan, ALT_DMA_TX_ONLY_ON, (void*) ABC_DMA_WRITE_MASTER_ABC_FIFO_BASE);

// **************************************************************************

// Start superloop

// **************************************************************************

while (1) {

// **************************************************************************

// Flush Nios II Data Cache

// **************************************************************************

alt_dcache_flush_all();

// **************************************************************************

// POST CH_DMA:

// **************************************************************************

// Post CH_DMA transmit request:

if ((rc = alt_dma_txchan_send (CH_dma_txchan,(void *)CH_DMA_READ_MASTER_CH_FIFO_BASE,bytes,NULL,NULL)) < 0)

{

alt_printf ("Failed to post CH_DMA transmit request, reason = %i\n", rc);

exit (1);

}

// Post CH0_DMA receive request:

if ((rc = alt_dma_rxchan_prepare (CH_dma_rxchan,(void *)CH_DMA_WRITE_MASTER_CH_BUFFER_BASE,bytes,CH_dma_done, NULL)) < 0)

{

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

exit (1);

}

// **************************************************************************

// POST ABC_DMA:

// **************************************************************************

// Post ABC_DMA transmit request:

if ((rc = alt_dma_txchan_send (ABC_dma_txchan,(void *)ABC_DMA_READ_MASTER_ABC_DATA_BASE,bytes,ABC_dma_done,NULL)) < 0)

{

alt_printf ("Failed to post ABC_DMA transmit request, reason = %i\n", rc);

exit (1);

}

// **************************************************************************

// Vary LEDs

// **************************************************************************

IOWR(LED_PIO_BASE,0,0xAA);

// **************************************************************************

// Wait until buffer(s) is filled up then proceed

// **************************************************************************

//

while (!(ABC_dma_complete && CH_dma_complete)) {

IOWR(LED_PIO_BASE,0,0xFF);

}

// **************************************************************************

// Turn appropriate LED on indicating which channel(s) transfer is complete

// **************************************************************************

IOWR(LED_PIO_BASE,0,0xFE);

// **************************************************************************

// Check data in buffer(s)

// Format in Memory: {XYZ} LITTLE ENDIAN

// A <-> X B <-> Y C <-> Z

// **************************************************************************

# ifdef echo

printf ("\nReading final contents of CH_BUFFER:\n");

read_data = (int*) CH_BUFFER_BASE;

// Check XYZ data values

for (j=0; j <= (words-1); j++)

{

printf(" 0x%-.8x", read_data[j]);

X = (X_val << 16) & 0xFF0000; // MSB

Y = (X_val+1 << 8) & 0xFF00;

Z = (X_val+2 ) & 0xFF; // LSB

Exp_Value = X | Y | Z;

printf(" Expected value = 0x%.8x",Exp_Value);

if (read_data[j] == Exp_Value)

printf(" - Passed\n");

else

printf(" - Failed\n");

X_val = X_val + 3;

}

// Init ABC_DATA with NON-default values

write_data = (int*) ABC_DATA_BASE;

for (j=0; j <= (words-1); j++)

{

A = (R_val << 16) & 0xFF0000; // MSB

B = (R_val+1 << 8) & 0xFF00;

C = (R_val+2 ) & 0xFF; // LSB

ABC_Value = A | B | C;

*write_data = ABC_Value;

write_data++;

A_val = A_val + 3;

}

# endif

// *************************************************************************

// Pause then repeat with updated values

// *************************************************************************

# ifdef echo

printf("\nPausing...\n\n");

# endif

usleep(1000000);

printf("\nEnd of iteration\n");

// Reset flags

ABC_dma_complete = 0;

CH_dma_complete = 0;

printf("\nPress Enter to proceed with program.");

GetInputString(line,sizeof(line),stdin);

} // end of superloop

.

.

.

Thank you for any help.
No RepliesBe the first to reply