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

URGENT: Peripheral to Memory DMA Transaction

Altera_Forum
Contributeur émérite II
9 099 Visites

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 Compliments
111 Réponses
Altera_Forum
Contributeur émérite II
1 518 Visites

Ok. Thanks!

0 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

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

It's good anough to add a DMA.
0 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

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 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

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 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

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 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

 

--- 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 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

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

 

Sean
0 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

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 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

 

--- 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 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

 

--- 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 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

my code does both, with double DMA and interrupts. 

But I don't have it here, because i'm already in the weekend ;-)))
0 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

 

--- 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 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

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 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

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

0 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

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

Under drivers, all periphereals should be listed.
0 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

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

0 Compliments
Altera_Forum
Contributeur émérite II
1 518 Visites

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 Compliments
Altera_Forum
Contributeur émérite II
1 521 Visites

huh? where to get SBT?

0 Compliments
Altera_Forum
Contributeur émérite II
1 521 Visites

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 Compliments
Altera_Forum
Contributeur émérite II
1 521 Visites

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 Compliments
Altera_Forum
Contributeur émérite II
1 521 Visites

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

0 Compliments
Répondre