Forum Discussion
111 Replies
- Altera_Forum
Honored Contributor
is it ok to use the method in this post? http://www.alteraforum.com/forum/showthread.php?t=13023
- Altera_Forum
Honored Contributor
I tried out some code from this forum. I cannot write the result from peripheral to SDRAM. my code is as follow:
--- 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" # ifndef datax # define datax 0x0# endif# ifndef datay # define datay 0x1# endif# ifndef datau # define datau 0x2# endif /* unsigned long add_h(unsigned long a, unsigned long b); unsigned long add_h(unsigned long a, unsigned long b) { long result; IOWR(AVALON_0_BASE,datax,a); IOWR(AVALON_0_BASE,datay,b); result = IORD(AVALON_0_BASE,datau); return result; } */ static volatile int rx_done = 0; static void transfer_done (void* handle, void* data) { rx_done++; } void mem2mem_DMA(unsigned int dst, int length, unsigned long a, unsigned long b) { void *rx_data = (void *) dst; alt_dma_rxchan rxchan; int ret_code; IOWR(AVALON_0_BASE,datax,a); // Data x IOWR(AVALON_0_BASE,datay,b); // Data y /* 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*)(AVALON_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 long number[100]; //unsigned long output1[100]; int i=0; int w; printf("Please specify number of sets of random number:\t "); scanf("%d", &w); for (i=0;i<w;i++) { number= 300000000;mem2mem_dma(dst, w, number, number);
}
for(i=0; i<w; i++)
{
printf("%ld\t %ld\n",number, IORD(dst, i)); } return 0; } --- Quote End --- My peripheral address is AVALON_0_BASE. This peripheral will add up 2 number, x and y. In this case, I set both x and y to be number[i], that is 300000000. Please assist. Thanks! really headache dealing with DMA.
- Altera_Forum
Honored Contributor
I think, what you are trying to do is not possible in this way.
First, your periphereal is memory mapped, so you are correct using the DMA. But DMA only makes sense when transferring multiple data in one run. Let me give you an example: For a serial interface, you could have the DMA transferring the contents of a buffer to the periphereal. For the opposite direction, you could use the DMA too, but not at the same time. (You could use a second DMA, if you wanted to send and receive parallel, allthough I don't think that would be neccessary). As a DMA is typically much faster than the periphereal, the DMA had to wait until the periphereal finished processing a value, before delivering the next one. Therefore, periphereals usually employ a buffer (e.g. a FIFO), so the DMA can write or read an amount of data in one run. The more data you can transfer at once, the more efficient it gets to use a DMA. Your code seems to use the DMA to deliver one value at a time. It does not make sense to setup the DMA to transfer 1 value of x, one value of y and one value of z. It would make more sense to add a fifo to your periphereal, and transmit the whole array of number[] for x, then for y, then have your periphereal calulate the result, and then again fetch the whole result[] via DMA. So you'd have to add 3 FIFOs to your periphereal, and some control to start a calculation once you have all data transmitted. - Altera_Forum
Honored Contributor
I see.. no wonder i cant get anything... what is FIFO? so, now i need to change my peripheral only? is there any example?
- Altera_Forum
Honored Contributor
Not really.
I used the megawizard to create a custom megafunction dcFifo, and used that in my code. It will be a bit tricky, because you will need to implement logic that fetches data for your periphereal, but the Avalon side is pretty straightforward. - Altera_Forum
Honored Contributor
do you mind to explain further? or maybe is there any tutorial about this? i have to understand the simple one like now, so i can implement in image processing... thanks!
- Altera_Forum
Honored Contributor
FIFO is a type of RAM, namely First In First Out.
You can use it to queue data for processing. Have a look at the user guide from altera (http://www.altera.com/literature/ug/ug_fifo.pdf). - Altera_Forum
Honored Contributor
Thanks, correct me if I am wrong: For my peripheral now, I have to create a memory to fit in the peripheral, all the result of computation is stored in the memory first, then, use DMA to transfer it to SDRAM. Am I right? is that consider as peripheral to memory transfer or still memory to memory transfer?
- Altera_Forum
Honored Contributor
It is a periphereal to memory transfer, as the DMA dosn't know about what your periphereal does with the data.
The difference between memory and periphereal access is, that the DMA increments addresses for memory access, but not for periphereal access. (Just a side note: If your periphereal implements a memory interface (e.g. like the Opencores I2S does), it would be neccessary to use memory-to-memory transfer.) - Altera_Forum
Honored Contributor
I am trying to make a peripheral to memory transfer. So, I add a RAM from Megawizard to my peripheral. Is that it? Besides, what are the differences between FIFO and RAM1port in Megawizard?
Besides, if DMA does not increase the memory address for peripheral, how does it transfer the data?