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

NiosII DMA Tutorial

Altera_Forum
Honored Contributor II
7,933 Views

Hello, may I know where can I get NiosII DMA Tutorial? Currently, I am doing a project to implement DMA on FPGA board. So I would to refer to some tutorials that can help me. Thanks.

0 Kudos
25 Replies
Altera_Forum
Honored Contributor II
3,586 Views

Software or Hardware tutorial?

0 Kudos
Altera_Forum
Honored Contributor II
3,586 Views

Start with DMA module user guide: 

www.altera.com/literature/ug/ug_embedded_ip.pdf 

Then, you can refer to any sample code using dma. 

Which one, depends on what you mean to do. 

You can find many examples and a lot of information by browsing the forum. 

 

Regards
0 Kudos
Altera_Forum
Honored Contributor II
3,586 Views

pillemann: both hardware and software 

 

Cris72: Ok, thanks. will see it..
0 Kudos
Altera_Forum
Honored Contributor II
3,585 Views

Software: Look at nios ii software developer's handbook (10.0) page 6-25 following. It's not exactly a tutorial but it's an example on how to use the DMA with HAL-driver. 

 

I prefer to write the registers of the DMA directly without using the HAL. The functionality of the various registers and bits are described in the user guide mentioned above by Cris. See dma controller core -> software programming model -> register map.
0 Kudos
Altera_Forum
Honored Contributor II
3,585 Views

Dear all, 

 

Sorry for asking other questions about DMA in this post.  

 

I have tried to do memory-to-memory data transfer using DMA and it worked successfully. But when I tried to do peripheral-to-memory data transfer using DMA, it was failed. 

 

Currently in my system I'm trying to move data that received by a PIO to memory using DMA. Here are some points about the current condition : 

 

- The DMA can write data which length is same as its DMA length configuration (for example, if I configure my DMA to do 10 bytes data transfer, it will write 10 bytes data in memory) 

 

- However, the data that are written by DMA in memory is only the last data that is received by PIO (for example, if the PIO is suppose to receive 10 bytes data which values are 1 to 10, the DMA will write only the last data, 10, and copy it as 10 bytes to the memory):confused:. 

 

I have tried to configure my DMA either using Altera API or accessing DMA register directly, but the result is same. :( 

 

According to these results, do you have any suggestions about how is the correct way to handle PIO - memory data transfer using DMA? Is this PIO-memory data transfer really possible?  

I'm wondering that the data transfer that can be handled by dma is only a data transfer case from an address range (like fifo, or memory, not from a pio) to another address range. Is it true??  

 

Please help me....:( I have tried many times to find out in this forum about the peripheral-to-memory DMA configuration (DMA as Rx channel), but only one post about it and it can't solve my problem.
0 Kudos
Altera_Forum
Honored Contributor II
3,589 Views

How is you pio supposed to receive data? What's the interface to the PIO peripheral?  

Usually PIO signal are driven manually in order to emulate the desired interface, so you can't use dma. 

If you start a 10bytes-long dma on raw PIO inputs, you will get 10 times the value currently driven onto the PIO inputs, unless this value changes during dma; but in this case you need something to synchronize data to dma, for example an address to access different locations of an external memory or a RD signal to pop data from a fifo. 

 

Regards
0 Kudos
Altera_Forum
Honored Contributor II
3,589 Views

Thank you for your reply :) 

 

Well, actually the PIO will be connected to several FIFOs which are located outside the Nios II system. So I thought that at first I needed to verify whether the DMA can handle data transfer from the PIO to memory (is it correct?) 

 

I forgot to tell you about my current debugging system. It consists of a CPU, a memory (DDR3), two PIO, and a DMA. So here are what I'm doing to verify my PIO-DMA data transfer : 

 

- I set a PIO in output direction (lets call it PIO-A) and another PIO in input direction (lets call it PIO-B ). I connect those two PIOs (PIO-A is connected to PIO-B ) in my verilog code. So in other words it is just like a loopback test. 

 

- In my Nios-II software, I generate dummy data and transmit them via PIO-A.  

Then of course, the data will be received back by PIO-B (I have ensured that PIO-B received the correct data from PIO-A). 

 

- The problem happens when I try to move data which are received by PIO-B to memory via DMA. The data transfer result was just like what I wrote in my previous post. The DMA only wrote and copied the last data that was received by PIO-B (why did the DMA copy the last data?? :confused:I thought that if the DMA only recognizes the last data it won't copy as many as the specified data length) 

 

Is there anything wrong with my verification method? I'm wondering that the dummy data  

that is generated by Nios-II software and received by PIO-B is too slow for DMA.  

If it is the problem, do you have any suggestion how is the correct way to verify my PIO-DDR3 data transfer via DMA? 

 

Thanks!
0 Kudos
Altera_Forum
Honored Contributor II
3,589 Views

The problem is what I said before: you don't have any synchronization signal. 

When you start dma (tx) on PIO port A, the dma engine will transfer data from memory to pio at the fastest speed possible, depending from bus sharing and arbitration (up to a byte every clock cycle if the bus is not busy!!). Then, if your dma is 10 bytes long and you have 1 to 10 data in memory, you'll see those data byte values rapidly changing on PIO outputs.  

When you start rx dma on PIO port B, the tx dma has probably already ended, so you will get 10 times the same value, i.e. the last one driven. 

The same would happen with your FIFOs. You must provide a synchronization signal. 

How is your system supposed to signal FIFO to push/pop a single byte of data? 

Usually the external peripheral has address, chip select and rd/wr lines. Then, when you start a dma transfer, these signals changing at every dma access will tell the peripheral to modify the driven/latched data. 

 

I hope my explanation is clear to you 

Cris
0 Kudos
Altera_Forum
Honored Contributor II
3,589 Views

Thanks Cris for replying my post :) I really appreciate it. 

 

Ah.. I just know about this synchronization signal requirement in the DMA data transfer. Well, in my system, the FIFO will be controlled by the Nios processor. The Nios will send read/write signals for FIFO. 

 

Ok, so based on your explanation, can I make a conclusion like this : I should verify the data transfer handled by DMA while integrating the FIFO into my Nios-II system. CMIIW 

 

If my conclusion is correct, can I still use a PIO as an interface between the FIFO and my Nios-II system? or do I have to connect my FIFO directly to my Nios-II system?  

The FIFO that I used was designed by MegaFunction, but I also made some modules to control the write and read process of my FIFO. So I hope that I can use the PIO as an interface to my Nios-II system. Otherwise, I have to modify my FIFO :( 

 

Well Cris, your advice make me enthusiastic again to finish this task, thanks! :)
0 Kudos
Altera_Forum
Honored Contributor II
3,589 Views

The FIFO (or any other device) is accessed in the same way with dma as with simple IORD/IOWR. The only difference being that dma performs the rd/wr operations in the background without involving the cpu. 

So you'd better test your FIFOs (memories, I/O devices or whatever) first with simple rd/wr operations. When you are sure your hardware works properly you can start using dma and be confident this will work too. 

 

Regarding FIFO integration, if this is used by Nios only, the better approach would be to integrating it in sopc system. The pio is not that fast and efficient way to interface an external device. 

 

Regarding the possibility use PIO for dma, I can see a solution only for tx dma to the fifo, though very very inefficient: 

Supposing your data is 8bit wide, you can define a wider PIO, including the extra signals needed to drive the fifo: in the minimal case it would be a single signal for latching data, say FIFO_PUSH.  

So, you dma to the PIO 9 bits data, where the highest bit is used to toggle the FIFO_PUSH signal. Clearly you must dma at least twice the data you actually need to transfer: as I said, this is not very efficient. 

 

Cris
0 Kudos
Altera_Forum
Honored Contributor II
3,589 Views

Hmm.. I see.  

 

Ok Cris, I'll try with a simple FIFO first. If it is succeed, later I'll integrate my FIFO with the Nios-II system.  

 

Thanks a lot Cris!
0 Kudos
Altera_Forum
Honored Contributor II
3,589 Views

Hi Cris 

 

Long time no see. Thank you for helping me last time. Now I can do data transfer from FIFO to DDR3 via DMA correctly. However, this time I would like to ask your suggestion again. 

 

Currently I'm using three DMAs in my SOPC system to handle three different data transfers from three different FIFOs to a DDR3 memory. I have verified each FIFO and DMA data transfer and all of them work well.  

 

The problem occurs when I put all FIFOs and DMAs in one SOPC system design. I ran the DMA data transfer in sequence (not parallel). Somehow my Nios software hung / stopped. From the Nios software debugging, it was noticed that the Nios software might stop in different location, but mostly it stopped when it tried to open the DMA ('alt_dma_rxchan_open' function) or when it checked the DMA data transfer volatile indicator variable.  

 

Do you have any idea what caused my software hung? Or do you have any suggestion how to figure out the reason behind this problem? 

 

Thanks ... looking forward any replies from you guys!
0 Kudos
Altera_Forum
Honored Contributor II
3,589 Views

Hi, 

I saw you opened a thread on this topic yesterday, but I had no certain solution, so I didn't answer. The only thing I can think about it is timing problems; is your design fully constrained and does it meet timing? 

Have you also checked interrupt or arbitration priorities; is it possible you have a highest priority interrupt which is blocking everything? 

I'd run in debug mode and step into alt_dma_rxchan_open to see the exact point where code hangs.
0 Kudos
Altera_Forum
Honored Contributor II
3,589 Views

Hi Cris, 

 

Finally I know what's wrong with my program. :)  

Actually it was caused by a misplacement 'waitrequest' signal in the avalon slave MM. So this misplaced 'waitrequest' signal caused the 'write' signal from CPU kept high and blocked other process. Now my system and its program can work correctly :) 

 

Btw Cris, I have some questions about RS-485 (in a new thread), I'm really appreciate if you want to help me :) 

 

Thanks :)
0 Kudos
Altera_Forum
Honored Contributor II
3,589 Views

Hello i am trying to do the same thing that you did, but i am kinda new to software development for NIOS. And i would like to get a "start point" i've read a lot of altera documentation but i can't find a simple "read from a memory" and "write in another memory" design/tutorial with the hardware and the software. 

 

I made a system consisting of a SDRAM, SGDMA and a NIOS. I want to write something to the DMA and that the dma writes the same data to the SDRAM. 

 

DO you have any piece of sw code that do something like that? Thanks a lot.
0 Kudos
Altera_Forum
Honored Contributor II
3,589 Views

Hi aprado, 

I have this piece of code for a simple dma core.  

I think you need to make a few changes in order to use with your sgdma core. 

 

# include "sys/alt_dma.h"# include "altera_avalon_dma.h" # define DMA_LENGTH 512 volatile int dma_complete; short rx_buffer; // pointer to rx buffer short tx_buffer; // pointer to tx buffer void dma_done (void* handle, void* data) { int rc; // turn the LED off (for DEBUG) rc = IORD_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE); IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, rc & ~0x10); dma_complete = 1; } int test_dma(void) { int rc; alt_dma_txchan txchan; alt_dma_rxchan rxchan; void* tx_data = (void*) tx_buffer; // pointer to data to send dma_complete = 0; // Create the transmit channel if ((txchan = alt_dma_txchan_open("/dev/ts_dma")) == NULL) { printf ("Failed to open transmit channel\n"); return -1; } // Create the receive channel if ((rxchan = alt_dma_rxchan_open("/dev/ts_dma")) == NULL) { printf ("Failed to open receive channel\n"); return -2; } if(alt_dma_txchan_ioctl(txchan, ALT_DMA_SET_MODE_16, NULL)<0) { return -3; } if(alt_dma_rxchan_ioctl(rxchan,ALT_DMA_SET_MODE_16,NULL)<0) { return -4; } if(alt_dma_txchan_ioctl(txchan,ALT_DMA_TX_ONLY_OFF,NULL)<0) { return -5; } if(alt_dma_rxchan_ioctl(rxchan,ALT_DMA_RX_ONLY_OFF,NULL)<0) { return -6; } printf ("Test DMA transfer...\n"); // turn a LED on (for DEBUG) rc = IORD_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE); IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, rc | 0x10); // Post the transmit request if ((rc = alt_dma_txchan_send (txchan,tx_data,DMA_LENGTH-16,NULL,NULL)) < 0) { printf ("Failed to post transmit request, reason = %i\n", rc); return -7; } // Post the receive request if ((rc = alt_dma_rxchan_prepare (rxchan,rx_buffer,DMA_LENGTH-16, dma_done,NULL)) < 0) { printf ("Failed to post read request, reason = %i\n", rc); return -8; } // wait for transfer to complete while (!dma_complete) TK_SLEEP(10); printf ("Transfer successful!\n"); return 0; }
0 Kudos
Altera_Forum
Honored Contributor II
3,590 Views

@ Aprado 

Hi, you can also learn about it from here http://www.alteraforum.com/forum/showthread.php?t=16850&highlight=dma+about , they discussed about DMA-memory data transfer and shared some code 

 

@ Cris 

Hi Cris, sorry for asking you again using this thread. Currently I'm discussing a problem about changing Nios's IP address in other thread http://www.alteraforum.com/forum/showthread.php?p=105881#post105881 . If you don't mind, please kindly to check it, maybe you have some advices for my problem :( 

Thank you!
0 Kudos
Altera_Forum
Honored Contributor II
3,590 Views

Thanks a lot for this posts, Cris i can tranfer from my onchip memory to my sdram memory without any problems. But now i want to do something differnt. Really simmilar to what fightingdreamer did. 

 

I have a fifo outside my sopc system that is connected to a 8bits PIO in my sopc system. 

I want to read this 8 bits from my PIO and write to a DDR memory. How should the code look like? (While i ask i am trying to modify your code) Thanks a lot. 

 

Fightingdreaming, do you have any tips? I saw you did exactly what i am trying to do.
0 Kudos
Altera_Forum
Honored Contributor II
3,590 Views

 

--- Quote Start ---  

 

I have a fifo outside my sopc system that is connected to a 8bits PIO in my sopc system. 

I want to read this 8 bits from my PIO and write to a DDR memory. How should the code look like?  

--- Quote End ---  

 

 

The code will be very similar to the previous one. 

The only difference being you need to read from a fixed address, i.e. the PIO base address: so you must set the RCON bit in the DMA control register. 

As I remarked somewhere in this thread, you also need a signal to pop data out of the fifo for every dma read access. 

 

Cris
0 Kudos
Altera_Forum
Honored Contributor II
3,097 Views

Cool, how can i set it in the software? I see is the 8th bit that i must set to 1. Where can i find examples of that? Thanks

0 Kudos
Reply