Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Valued Contributor III
749 Views

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 << 😎 & 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 << 😎 & 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.
0 Kudos