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

URGENT: Peripheral to Memory DMA Transaction

Altera_Forum
Honored Contributor II
6,037 Views

Hello, may I know how to transfer data from peripheral to memory using DMA? It is quite confusing from memory-to-memory transfer. please help! thanks!

0 Kudos
111 Replies
Altera_Forum
Honored Contributor II
885 Views

Ok. Thanks!

0 Kudos
Altera_Forum
Honored Contributor II
885 Views

Actually, what you have so far does work from my point of view. 

It's good anough to add a DMA.
0 Kudos
Altera_Forum
Honored Contributor II
885 Views

yes. it does work. but in the Nios II IDE, i use the c code i posted here earlier, it cannot write into SDRAM.

0 Kudos
Altera_Forum
Honored Contributor II
885 Views

where does it fail? 

 

I have seen lots of reports in this forum asking why the DMA does not work. 

So far I have only seen implementations, where the DMA HAL drivers were completely disabled in the BSP settings, and the DMA registers is programmed directly. 

 

I also find it much more understandable than the HAL drivers.
0 Kudos
Altera_Forum
Honored Contributor II
885 Views

When transferring data from peripheral to SDRAM using DMA. My code is as followed: 

--- Quote Start ---  

#include "io.h"# include <stdio.h># include <unistd.h># include <sys/alt_dma.h># include "altera_avalon_pio_regs.h"# include "alt_types.h"# include "system.h"# include "sys/alt_timestamp.h" 

 

static volatile int rx_done = 0; 

static void transfer_done (void* handle, void* data) 

rx_done++; 

 

void mem2mem_DMA(unsigned int dst, int length) 

void *rx_data = (void *) dst; 

alt_dma_rxchan rxchan; 

int ret_code; 

 

int i; 

int x[100]; 

for(i=0;i<100;i++) 

IOWR(ADDER_0_BASE,0,1); 

 

/* Create the receive channel */ 

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

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

exit (1); 

ret_code = alt_dma_rxchan_ioctl(rxchan, ALT_DMA_SET_MODE_32, NULL); 

if (ret_code) 

printf("Error: SET_MODE_32: %d.\n", ret_code); 

exit(1); 

 

ret_code = alt_dma_rxchan_ioctl(rxchan, ALT_DMA_RX_ONLY_ON, (void*)(ADDER_0_BASE)); 

if (ret_code) 

printf("Error: ALT_DMA_RX_STREAM_ON: %d.\n", ret_code); 

exit(1); 

/* Post the receive request */ 

if ((ret_code = alt_dma_rxchan_prepare(rxchan, rx_data, length, transfer_done, NULL)) < 0) 

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

exit (1); 

/* wait for transfer to complete */ 

while (!rx_done); 

printf("Transfer successful!\n\n"); 

 

int main(void) 

printf("\nThis is 32bits addition operation \n\n"); 

unsigned int dst = SDRAM_BASE + 0x600000; 

unsigned x[150]; 

//unsigned long output1[100]; 

int i=0; 

int w; 

 

mem2mem_DMA(dst, 100); 

 

for(i=0; i<100; i++) 

printf("%d\n",IORD(dst, i)); 

 

return 0; 

}  

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
885 Views

 

--- Quote Start ---  

where does it fail? 

 

I have seen lots of reports in this forum asking why the DMA does not work. 

So far I have only seen implementations, where the DMA HAL drivers were completely disabled in the BSP settings, and the DMA registers is programmed directly. 

 

I also find it much more understandable than the HAL drivers. 

--- Quote End ---  

 

 

Yes, i experienced it too. but I dont have much tutorial on DMA registers. So i have no idea where to start and how to do it.
0 Kudos
Altera_Forum
Honored Contributor II
885 Views

My DMA work ok... I'm be able to copy from SDRAM to OnChip... I guess it could be a bug... 

 

Sean
0 Kudos
Altera_Forum
Honored Contributor II
885 Views

Yes, I had the DMA drivers work in one direction, but not the other. 

Whatever I tried, no luck. 

 

Look in the Quartus Handbook DMA chapter (google for altera nios dma).  

The registers are explained there. 

You have a status register, read and write address, length and some control bits. 

you program them like you did with your periereal: IOWR(AVALON_0_BASE,reg,val); 

Adresses and length should be obvious. 

You only need to select the correct control bits.
0 Kudos
Altera_Forum
Honored Contributor II
885 Views

 

--- Quote Start ---  

My DMA work ok... I'm be able to copy from SDRAM to OnChip... I guess it could be a bug... 

 

Sean 

--- Quote End ---  

 

 

Using HAL functions for mem-to-mem is easier i guess. but for per-to-mem, it is difficult
0 Kudos
Altera_Forum
Honored Contributor II
885 Views

 

--- Quote Start ---  

Yes, I had the DMA drivers work in one direction, but not the other. 

Whatever I tried, no luck. 

 

Look in the Quartus Handbook DMA chapter (google for altera nios dma).  

The registers are explained there. 

You have a status register, read and write address, length and some control bits. 

you program them like you did with your periereal: IOWR(AVALON_0_BASE,reg,val); 

Adresses and length should be obvious. 

You only need to select the correct control bits. 

--- Quote End ---  

 

 

Ok. thanks! I will try it now. I am trying to transfer from peripheral to sdram. if this works, then i think it should be enough. your code is transferring from peripheral to mem or mem to peripheral?
0 Kudos
Altera_Forum
Honored Contributor II
885 Views

my code does both, with double DMA and interrupts. 

But I don't have it here, because i'm already in the weekend ;-)))
0 Kudos
Altera_Forum
Honored Contributor II
885 Views

 

--- Quote Start ---  

my code does both, with double DMA and interrupts. 

But I don't have it here, because i'm already in the weekend ;-))) 

--- Quote End ---  

 

ok. thanks! i will try the dma register now
0 Kudos
Altera_Forum
Honored Contributor II
885 Views

Dont forget to disable the DMA drivers in the BSP settings, or it won't work. 

The HAL DMA init does something weird to the DMA...
0 Kudos
Altera_Forum
Honored Contributor II
885 Views

how to disable it? I cant find it. where is the BSP setting?

0 Kudos
Altera_Forum
Honored Contributor II
885 Views

IIRC: Right-click on the BSP project, ->Nios II->Edit BSP settings 

Under drivers, all periphereals should be listed.
0 Kudos
Altera_Forum
Honored Contributor II
885 Views

I dont see the BSP project. I am using Nios II IDE.

0 Kudos
Altera_Forum
Honored Contributor II
885 Views

You should consider switching to the SBT (software build tools) flow. It has been the default for a number of Altera software releases now....soon the "classic/IDE" flow will go away. 

 

Cheers, 

 

slacker
0 Kudos
Altera_Forum
Honored Contributor II
888 Views

huh? where to get SBT?

0 Kudos
Altera_Forum
Honored Contributor II
888 Views

What Quartus version do you work with? The NIOS EDS is a download at the Altera website, right next to Quartus. 

 

From the IDE help, I guess it should be right-click on the project, then select properties, System library properties.
0 Kudos
Altera_Forum
Honored Contributor II
888 Views

This is my code: I dunno why it wont work... the data cant be written into sdram. 

--- Quote Start ---  

#include "io.h"# include <stdio.h># include <unistd.h># include <sys/alt_dma.h># include "altera_avalon_dma_regs.h"# include "altera_avalon_pio_regs.h"# include "alt_types.h"# include "system.h" 

//#include "sys/alt_timestamp.h" 

 

int main() 

int i; 

int a=100; 

unsigned int dst = SDRAM_BASE + 0x400000; 

IOWR_ALTERA_AVALON_DMA_STATUS(DMA_BASE, 0x00); 

 

for(i=0;i<100;i++) 

IOWR(PERIPHERAL_0_BASE, 0, 30); 

IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE, PERIPHERAL_0_BASE); 

IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE,dst); 

IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_BASE,100); 

 

IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE,0X199); 

for(i=0;i<100;i++) 

printf("%d\n", IORD(dst, i)); 

 

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
888 Views

I am using QII V9.0 and Nios II IDE V9.0

0 Kudos
Reply