Nios® II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
Announcements
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.

DMA fails to transmit

Altera_Forum
Honored Contributor II
871 Views

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.
0 Kudos
0 Replies
Reply