- 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
Do you wait for the transfer to finish?
Also, 0x199 does not seem correct. I thought you data is 32bit wide?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Oh... yeah 32bit... how to wait for transfer to finish?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
while (IORD_ALTERA_AVALON_DMA_STATUS(DMA_BASE) & 1)==0); ?
but I'd suggest using usleep until you confirm the DMA working.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
i tried but still cant... can you pls provide me a fragment of code of how it run, like i am just using FIFO as peripherals? data is 0-9
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your SOPC connections are ok?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Looks ok to me.
Try reading back the DMA registers, if the correct values are really set.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
currently, this is my code:
--- 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; unsigned int dst = SDRAM_BASE + 0x200000; for(i=0; i<128; i++) { IOWR_32DIRECT(PERIPHERAL_0_BASE, 0, i); //printf("%d\n", IORD_32DIRECT(PERIPHERAL_0_BASE, 0)); } IOWR_ALTERA_AVALON_DMA_STATUS(DMA_BASE, 0x00); printf("%d\n", IORD_ALTERA_AVALON_DMA_STATUS(DMA_BASE)); IOWR_32DIRECT(PERIPHERAL_0_BASE, 0, i); 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,0x19C); usleep(200000); for(i=0; i<128; i++) { printf("%d\n", IORD_32DIRECT(dst, i)); } return 0; } --- Quote End --- i dont know if the arrangement of my code is correct. update: i just manage to get the result for this: printf("%d\n", IORD_ALTERA_AVALON_DMA_STATUS(DMA_BASE)); which is 0- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That's strange, because either done or busy should be set.
What values do you read from the other registers? Try setting the control register first to 0x194, then read it back, and at last 0x19c to add the Run bit. I'm not certain the DMA will start if the control reg is set to run from Zero. Are you sure, you want to enable the interrupt? Maybe it's neccessary to first issue a softreset. Edit: Now I see you read the status right after you reset it. Try reading it later on, to see what happened to the DMA....- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think now my DMA is working... But it seems like it cannot write into the memory.. my code:
--- 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" int main() { int i; for(i=0; i<100; i++) { IOWR(PERIPHERAL_0_BASE, 0, i); } IOWR_ALTERA_AVALON_DMA_STATUS(DMA_BASE, 0x00); IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE, PERIPHERAL_0_BASE); IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE, EXT_SRAM_BASE); IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_BASE, 200); IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE, 0x1102); IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE, 0x10A); printf("done\n"); for(i=0; i<100; i++) { printf("%d\n", IORD(EXT_SRAM_BASE, i)); } return 0; } --- Quote End --- i disable the interrupt and add in the softreset initially... update: result is: done 0 -1 -1 -1 -1 then all are -1....- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
i'm not sure if it is ok to configure the DMA when issuing a reset.
Doesn't the DMA reset the registers then? Resetting the DMA should be the very first thing to do....- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
is it reset the DMA first only then write 0x00 into the dma status? result i got:
result is: done 0 -1 -1 -1 -1 then all are -1....- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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" int main() { int i; for(i=0; i<100; i++) { IOWR(PERIPHERAL_0_BASE, 0, i); } IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE, 0x1000); IOWR_ALTERA_AVALON_DMA_STATUS(DMA_BASE, 0x00); IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE, PERIPHERAL_0_BASE); IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE, EXT_SRAM_BASE); IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_BASE, 200); IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE, 0x102); IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE, 0x10A); printf("done\n"); for(i=0; i<100; i++) { printf("%d\n", IORD(EXT_SRAM_BASE, i)); } return 0; } --- Quote End --- result: --- Quote Start --- done 131072 393220 655368 917516 1179664 1441812 1703960.... --- Quote End --- until finish, all are random numbers
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
maybe is it because i dont disable the dma in BSP setting? because i cant find it in Nios II IDE 9.0
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That might be a reason. The NIOS manual is clear in this case:
--- Quote Start --- If ... the HAL driver is active for the same device, your driver will conflict and fail to operate. --- Quote End --- As I already said, check the DMA register contents, whether the HAl driver interferes with your settings. Do it at least before issuing the run bit.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, I just read all the registers and the values are all correct. before i print out the result, the DONE is already '1' and status is '10001' in binary, suppose finish running. But still, in the dst, cant get the result. my new code is as below, DMA transfer data from SDRAM to peripheral, then second DMA_0 transfer from peripheral to EXT_SRAM.
--- 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" int main() { int i; unsigned int src = SDRAM_BASE + 0x200000; unsigned int dst = EXT_SRAM_BASE; for(i=0; i<100; i++) { IOWR(src, i, 1); printf("initial: %d\n", IORD(src, i)); } IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE, 0x1000); printf("ctrl1: %d\n", IORD_ALTERA_AVALON_DMA_CONTROL(DMA_BASE)); IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_0_BASE, 0x1000); printf("ctrl2: %d\n", IORD_ALTERA_AVALON_DMA_CONTROL(DMA_0_BASE)); IOWR_ALTERA_AVALON_DMA_STATUS(DMA_BASE, 0x00); printf("stat1: %d\n", IORD_ALTERA_AVALON_DMA_STATUS(DMA_BASE)); IOWR_ALTERA_AVALON_DMA_STATUS(DMA_0_BASE, 0x00); printf("stat2: %d\n", IORD_ALTERA_AVALON_DMA_STATUS(DMA_0_BASE)); IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE, src); printf("rdadd1: %d\n", IORD_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE)); IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE, PERIPHERAL_0_BASE); printf("wradd1: %d\n", IORD_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE)); IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_0_BASE, PERIPHERAL_0_BASE); printf("rdadd2: %d\n", IORD_ALTERA_AVALON_DMA_RADDRESS(DMA_0_BASE)); IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_0_BASE, dst); printf("wradd2: %d\n", IORD_ALTERA_AVALON_DMA_WADDRESS(DMA_0_BASE)); IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_BASE, 200); printf("len1: %d\n", IORD_ALTERA_AVALON_DMA_LENGTH(DMA_BASE)); IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_0_BASE, 200); printf("len2: %d\n", IORD_ALTERA_AVALON_DMA_LENGTH(DMA_0_BASE)); IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE, 0x282); printf("crtl1: %d\n", IORD_ALTERA_AVALON_DMA_CONTROL(DMA_BASE)); IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_0_BASE, 0x182); printf("ctrl2: %d\n", IORD_ALTERA_AVALON_DMA_CONTROL(DMA_0_BASE)); IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE, 0x28A); printf("run1: %d\n", IORD_ALTERA_AVALON_DMA_CONTROL(DMA_BASE)); IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_0_BASE, 0x18A); printf("run2: %d\n", IORD_ALTERA_AVALON_DMA_CONTROL(DMA_0_BASE)); printf("status: %d\t%d\n", IORD_ALTERA_AVALON_DMA_STATUS(DMA_BASE), IORD_ALTERA_AVALON_DMA_STATUS(DMA_0_BASE)); for(i=0;i<100;i++) { printf("waiting\n"); } printf("status: %d\t%d\n", IORD_ALTERA_AVALON_DMA_STATUS(DMA_BASE), IORD_ALTERA_AVALON_DMA_STATUS(DMA_0_BASE)); printf("done\n"); for(i=0; i<100; i++) { printf("end: %d\n", IORD(dst, i)); } return 0; } --- Quote End --- pls help me to check the flow of my code. i am not sure if i arrange the calling function in such way is correct or not. i am afraid, maybe sometimes the data hasnt arrive and DMA also start fetching the data. pls help me to check. thanks!- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
my registers: all in decimals
--- Quote Start --- ctrl1: 4096 ctrl2: 4096 stat1: 0 stat2: 0 rdadd1: 10485760 wradd1: 17838208 rdradd2: 17838208 wradd2: 17301504 len1: 200 len2: 200 crtl1: 642 ctrl2: 386 run1: 650 run2: 394 status: 17 17 --- Quote End ---- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So the DMA seems to work.
Why are you setting every register double time? Why are you setting it to different values? e.g the control register is first set to constant write address, then to constant read address. When you start the transaction, you set it again to constant write address, then start it again with constant read address. If the DMA was not finished at that time, your code might confuse it during operation... You can read these register as often as you like, but you should only need to write them only once. The values should not change until the DMA is really started, even afterwards most of them should still read the same values.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am quite confuse with the register as well. But I am using two different DMA in the system. One is for memory to peripheral and another is for peripheral to memory. Do you mind suggest me a solution? thanks!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
oh, i didn't see there's 2 base addresses DMA_BASE and DMA_0_BASE.
So then it should be ok....- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Haha, I think I got it...
your "random" numbers don't seem so random to me.... 131072 = 0x20000 393220 = 0x60004 655368 = 0xA0008 917516 = 0xE000C and so on... Is either of your RAM or your periphereal 16bit wide? Instead of doing a IORD(dst,i) try doing a IORD_16DIRECT(), that shoud do the trick... Edit: Maybe you must do IORD_16DIRECT(dst, i*2), because it might use a byte offset. IORD() itself already converted the offset to bus width, which it thought being 32bit.- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page