- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I am trying to do a simple DMA mem to mem transfer as per the "Chap24: DMA controller core " example. I have been at this for almost a week now and it is still not working for me. Can you please help me. The dma transfer is getting stuck in the "while(!txrx_done)" loop. I am not getting any error messages. Here is the status of my registers just before it enters the "while loop". readaddress =800000, writeaddress =801000, length =80, status =2, control =fc Here are the details of my setup: I am using the DE2 board. First in Qsys: DMA Controller DMA Read Master -> SDRAM Controller slave DMA Write Master -> SDRAM Controller slave DMA Control-port Slave-> CPU Data Master niosii code: staticvolatileint txrx_done = 0; static void txrxdone(void * handle, void * data) { txrx_done = 1; } init code: alt_dma_txchan txchan; alt_dma_rxchan rxchan; alt_u32* tx_data = (alt_u32*)0x800000; alt_u32* rx_buffer = (alt_u32*)(0x801000); // Create the transmit channel if ((txchan = alt_dma_txchan_open("/dev/dma_0")) == NULL) { printf ("Failed to open transmit channel\n"); exit (1); } // Create the receive channel if ((rxchan = alt_dma_rxchan_open("/dev/dma_0")) == NULL) { printf ("Failed to open receive channel\n"); exit (1); } setting up transfer: printf("Setting up DMA\n"); // Post the transmit request if ((rc1 = alt_dma_txchan_send (txchan, tx_data, 128, NULL, NULL)) < 0) { printf ("Failed to post transmit request, reason = %i\n", rc1); exit (1); }   if ((rc1 = alt_dma_rxchan_prepare (rxchan, rx_buffer, 128, txrxDone, NULL)) < 0) { printf ("Failed to post read request, reason = %i\n", rc1); exit (1); } while (!txrx_done); printf ("Transfer successful!\n"); Please help!Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You have ensured you don't have anything at those locations right? For example it would be really bad if you had a code or data section located at the source or destination address since you code + DMA overwrites those locations.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your note.
As far as I know I don't have anything in this location. In this example I am doing nothing else but this, not sure if the CPU is using the same resource. Is there a way to find out if this memory is being used ? Or is there a safe section of the memory I can try out this in ? Please suggest if there any other test I can do to see the DMA working. It has never worked for me. Regards, N- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You could create a linker section in those locations that prevent the linker from placing any sections in there. The lazy way to test this would be to dynamically allocate those two buffers using a malloc to ensure the linker doesn't put anything there. You can't pick a location that could potentially be used by the processor at run time without ensuring precautions are taken. So it's possible that your code is stomping on itself and causing things to go off in the weeds.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tired using malloc and also using alt_uncached_malloc - No luck.:(
Still getting stuck in the while loop. Here are my DMA settings jus before the While loop: readaddress =827418, writeaddress =827820, length =80, status =2, control =fc Is my Qsys setup OK ?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you use the uncached malloc make sure you pass a pointer to the DMA that is masked with 0x7FFF_FFFF. Uncached pointers have the upper bit set which is the cache bypassing mechanism Nios II uses without an MMU. If you used regular malloc the worst that can happen is a cache coherency issue between the DMA and CPU, that wouldn't cause your waiting loop to get stuck.
I can't tell if your Qsys system is wired up correctly without seeing a screenshot of it.- 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
That looks fine to me, how is the DMA parameterized? I seem to recall some bugs if you attempt to perform 64 or 128 bit transfers but given your system I don't think you would need such a wide DMA.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is my DMA controller settings.
Width of DMA length Register = 13 Enable Burst Transfer not checked FIFO Depth 32 Construnct FIFO from Mem blocks checked Under Advanced - only WORD is clicked.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Try enabling the 8 and 16 bit options as well. It's been a really long time but I seem to recall a bug occuring when those options are disabled.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Tried that as well. No Luck.
Next I am planning to strip all the unnecessary peripherals from the system and test again. I will let you know how that goes. Thanks.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
After you have a minimal system, if you still see the problem I would simulate the software running on the CPU. You might see something in the simulation that will give you a clue as to what is happening.
Another thing you could try is using the macro file from the DMA driver and write the source, destination, and control fields directly to see if the behavior is any different. I forget what the file is called but it will probably be something like "altera_dma_regs.h".- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Created a minimal system. And used direct commands as you suggested.
Still no luck :(. No clue on what's going on! I will try to simulate it next. I have attached the Qsys screen shot. IOWR_ALTERA_AVALON_DMA_STATUS(DMA_0_BASE, 0x00); IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_0_BASE, SDRAM_0_BASE); IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_0_BASE, SDRAM_0_BASE+0x1000); IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_0_BASE, 128); IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_0_BASE, 0x008C); printf("Setting up DMA\n"); while (!(IORD_ALTERA_AVALON_DMA_STATUS(DMA_0_BASE)==0));   printf ("Transfer successful!\n"); Results on the console: Setting up DMA readaddress =800000, writeaddress =801000, length =80, status =2, control =8c- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
After you write the control register I would expect the status register bits [1:0] to be non-zero (either busy transferring or done). As a result you have while (!(non_zero_value == 0)); .... or in other words an infinite loop. You should mask the busy bit and keep looping until it is set:
while ( ((IORD_ALTERA_AVALON_DMA_STATUS(DMA_0_BASE) & ALTERA_AVALON_DMA_STATUS_DONE_MSK) != ALTERA_AVALON_DMA_STATUS_DONE_MSK ) { // spin } If that software change still doesn't work run it in the simulation since it'll be easier to debug with the driver out of the way.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I was able to make the code work on an old Nios II devlopement Kit
Cyclone II edition. Thsi means that the problem is probabily related to hardware or Qsys in the DE2 board. It is strange I am able to read and write but DMA access does not work. I will investigate that further.- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page