Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20686 Discussions

[Problem] Simple Memory to Memory DMA example

Altera_Forum
Honored Contributor II
1,796 Views

here, i got rid of some code from full program. 

my program go into infinite loop while(!rx_done) 

that is, i can't get "done" from rxchan.. 

this is just example which stated in the altera document!  

i can't figure out what problem is.. can you help me? 

 

# include <stdio.h> 

# include <stdlib.h> 

# include "sys/alt_dma.h" 

# include "altera_avalon_jtag_uart_regs.h" 

# include "system.h" 

# include "alt_types.h" 

# include "altera_avalon_dma_regs.h" 

# include <sys/alt_alarm.h> 

# include <sys/alt_timestamp.h> 

# include <string.h> 

 

static volatile int tx_done = 0; 

 

void software_display(FILE *fp_LCD); 

void hardware_display(FILE *fp_LCD); 

void displayMemory(char *address, int length); 

void check(void); 

 

static volatile int rx_done = 0; 

 

static void done (void *handle, void* data){ 

rx_done = 1; 

 

void hardware_display(FILE *fp_LCD){ 

 

int rc; 

alt_dma_txchan txchan; 

alt_dma_rxchan rxchan; 

 

void* tx_data = 0x9000000; 

void* rx_buffer = 0x9001000; 

 

if((txchan = alt_dma_txchan_open("/dev/dma")) == NULL){ 

printf("Failed to open transmit channel\n"); 

exit (1); 

else{ 

alt_dma_txchan_ioctl(txchan, ALT_DMA_SET_MODE_32, NULL); 

alt_dma_txchan_ioctl(txchan, ALT_DMA_TX_ONLY_ON, rx_buffer); 

alt_dma_txchan_ioctl(txchan, ALT_DMA_RX_ONLY_OFF, NULL); 

 

if((rxchan = alt_dma_rxchan_open("/dev/dma")) == NULL){ 

printf("Failed to open receive channel\n"); 

exit (1); 

else{ 

alt_dma_rxchan_ioctl(rxchan, ALT_DMA_SET_MODE_32, NULL); 

alt_dma_rxchan_ioctl(rxchan, ALT_DMA_TX_ONLY_OFF, NULL); 

alt_dma_rxchan_ioctl(rxchan, ALT_DMA_RX_ONLY_ON, tx_data); 

 

if((rc = alt_dma_txchan_send(txchan, tx_data, 0x1000, NULL, NULL)) <0 ){ 

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

exit (1); 

 

if((rc = alt_dma_rxchan_prepare(rxchan, rx_buffer, 0x1000, done, NULL)) <0){ 

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

exit (1); 

 

while(!rx_done); 

 

alt_dma_txchan_close(txchan); 

alt_dma_rxchan_close(rxchan); 

 

printf("Transfer successful!\n"); 

}
0 Kudos
4 Replies
Altera_Forum
Honored Contributor II
456 Views

Are 0x9000000 to 0x9002000 valid memory addresses in your system?

0 Kudos
Altera_Forum
Honored Contributor II
456 Views

Yes address is valid because I tested this example using IOWR Macro.. 

at then, this address is executed well.. 

but when I used these channel, then it didn't work.. 

anybody help me~ T.T:(
0 Kudos
Altera_Forum
Honored Contributor II
456 Views

The question actually was: are you sure those addresses are not used by the compiler for anything else? 

You'd better never use a constant for a memory buffer since the code is not portable and you don't know if that memory range is free. 

The best way to define a DMA buffer is using an array, static or malloc-ed or using a system define for the pointer address. 

Then, instead of void* tx_data = 0x9000000 : 

static int tx_data[BUFFER_SIZE]; 

or 

int * tx_data; 

tx_data = (int*)malloc(BUFFER_SIZE*sizeof(int)); 

or 

int * tx_data = DMA_MEMORY_BASE_ADDRESS; 

(where DMA_MEMORY_BASE_ADDRESS is defined automatically by sopc builder in your system file)  

 

However, in your specific case, if you know that memory range is available, the error can be due to the fact you are exceeding max dma length.
0 Kudos
Altera_Forum
Honored Contributor II
456 Views

Have you tried changing the addresses to for example 0x9000000 and 0x9000104 (with a smaller data length?). And are you sure your program can't access that memory? For example that your program runs in the same memory as you try to perform the DMA transfers in. 

 

I have a similar problem though. My code can be found in this thread: 

http://www.alteraforum.com/forum/showthread.php?p=105717#post105717 (one of the last posts) 

The code in this thread works fine, but if I add streaming mode by adding the following after the ALT_DMA_SET_MODE_32 it stops working. 

 

if i add: 

if ((rc = alt_dma_txchan_ioctl(txchan, ALT_DMA_TX_ONLY_ON, tx_data)) < 0) 

printf ("Failed to set tx ioctl to TX_ONLY_ON, reason = %i\n", rc); 

exit (1); 

my code hangs (while (!txrx_done) never completes). 

 

and if i add  

if ((rc = alt_dma_rxchan_ioctl(rxchan, ALT_DMA_RX_ONLY_ON, rx_buffer)) < 0) 

printf ("Failed to set rx ioctl to RX_ONLY_ON, reason = %i\n", rc); 

exit (1); 

}  

i get back: Failed to set rx ioctl to RX_ONLY_ON, reason = -5 

 

Ok if I change my code using some of the code in the startpost (cheers :P) I get the following code (the rest can be found in the forementioned thread): 

txrx_done=0; if((txchan = alt_dma_txchan_open(dma_name)) == NULL) { printf("Failed to open transmit channel\n"); exit (1); } else { alt_dma_txchan_ioctl(txchan, ALT_DMA_SET_MODE_32, NULL); alt_dma_txchan_ioctl(txchan, ALT_DMA_TX_ONLY_ON, rx_buffer); alt_dma_txchan_ioctl(txchan, ALT_DMA_RX_ONLY_OFF, NULL); } if((rxchan = alt_dma_rxchan_open(dma_name)) == NULL) { printf("Failed to open receive channel\n"); exit (1); } else { alt_dma_rxchan_ioctl(rxchan, ALT_DMA_SET_MODE_32, NULL); alt_dma_rxchan_ioctl(rxchan, ALT_DMA_TX_ONLY_OFF, NULL); alt_dma_rxchan_ioctl(rxchan, ALT_DMA_RX_ONLY_ON, tx_data); } /* Post the transmit request */ if ((rc = alt_dma_txchan_send (txchan, tx_data, length, NULL, NULL)) < 0) { printf ("Failed to post transmit request, reason = %i\n", rc); exit (1); } /* Post the receive request */ if ((rc = alt_dma_rxchan_prepare (rxchan, rx_buffer, length, txrxDone, NULL)) < 0) { printf ("Failed to post read request, reason = %i\n", rc); exit (1); } /* wait for transfer to complete */ printf( "Waiting on DMA..."); while (!txrx_done) printf("."); printf(" Done!\n"); /* Close channels */ alt_dma_txchan_close(txchan); alt_dma_rxchan_close(rxchan);  

This code works for me, but it reads from a constant address and writes to an incrementing address. I would like to turn that around, I think I have tried all the combinations, but it doesn't seem to work. Anyone knows how to turn this around?
0 Kudos
Reply