- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Tags:
- Include
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok. Thanks!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Actually, what you have so far does work from my point of view.
It's good anough to add a DMA.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
yes. it does work. but in the Nios II IDE, i use the c code i posted here earlier, it cannot write into SDRAM.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 ---- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My DMA work ok... I'm be able to copy from SDRAM to OnChip... I guess it could be a bug...
Sean- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
my code does both, with double DMA and interrupts.
But I don't have it here, because i'm already in the weekend ;-)))- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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...- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
how to disable it? I cant find it. where is the BSP setting?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IIRC: Right-click on the BSP project, ->Nios II->Edit BSP settings
Under drivers, all periphereals should be listed.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I dont see the BSP project. I am using Nios II IDE.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
huh? where to get SBT?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 ---- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am using QII V9.0 and Nios II IDE V9.0
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page