Forum Discussion
About DMA problem..please help me
hi all
I have try the altera memory test project with Nios II IDE.. but always display "-Testing memory using DMA"... http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/sad.gif the dma might be already open.. and didn`t display "Memory at 0x%X Okay"....... so...I found the code at nios forum...it should be work but it always display"wait for transfer to complete"...why? look like the same problem with memory test !? I use Quartus II 5.1 SP2 & Nios II IDE 5.1 SP1 the exception address is sram_0 at SOPC Builder the program memory & .rodata & .rwdata & heap memory & stack memory are sdram_0 and I sure I have connect the DMA read & write master with sdram_0 & avalon tristate bridge in the SOPC builder this is the code...please help me thanks.... # include <stdio.h># include "system.h"# include "sys/alt_dma.h"# include "alt_types.h" /* Create the transmit channel */ static volatile int rx_done = 0; /* ready handler*/ static void done (void* handle, void* data) { rx_done++; } int main (int argc, char* argv[], char* envp[]) { int rc; alt_u8 Inbuf[1024], Outbuf[1024]; alt_dma_txchan txchan; alt_dma_rxchan rxchan; void* tx_data = (void*) &Inbuf[0]; /* pointer to data to send */ void* rx_buffer = (void*) &Outbuf[0]; /* pointer to rx buffer */ if ((txchan = alt_dma_txchan_open("/dev/avalon_dma")) == NULL) { printf ("Failed to open transmit channel\n"); exit (1); } /* Create the receive channel */ if ((rxchan = alt_dma_rxchan_open("/dev/avalon_dma")) == NULL) { printf ("Failed to open receive channel\n"); exit (1); } /* Post the transmit request */ if ((rc = alt_dma_txchan_send (txchan,tx_data,1024,NULL,NULL)) < 0) { printf ("Failed to post transmit request, reason = %i\n", rc); exit (1); } /* Post the receive request */ if ((rc = alt_dma_rxchan_prepare (rxchan,rx_buffer,1024,done,NULL)) < 0) { printf ("Failed to post read request, reason = %i\n", rc); exit (1); } /* wait for transfer to complete */ printf ("wait for transfer to complete\n"); while (!rx_done); printf("Transfer successful!\n"); return 0; }30 Replies
- Altera_Forum
Honored Contributor
im also having the same kind of problem..
the memory test program example (provided in nios eds) stuck at "-testing memory using dma".unfortunately i didnt see anybody reply to your thread.. and i know this is an old thread, but have you found the solution to it? Im stuck with it like two weeks now finding the solution. please guide me through this if you or somebody else has already solved it. I dont believe its a physical hardware problem of the memory chip since the bits testing of the sdram does work.. Only the dma didnt work. Seems like it never got the "rx_done" into '1' since the transfer does not complete. I wonder why.. here is the screen shot of my sopc: https://www.alteraforum.com/forum/attachment.php?attachmentid=2382 i tried to attach my full system but its too big. sorry BTW im using Altera 8.0 version software. - Altera_Forum
Honored Contributor
I don't see anything wrong with the hardware configuration... Does your design meet timing requirements?
You could use some signaltap probes on the avalon master busses from the DMA to check if it is doing anything or not. - Altera_Forum
Honored Contributor
I manage to get DMA transfer complete. but rewrite the code, and it only copy from a single address to buffer.(more like a streaming).
I read from the documentation that this method is supposed to be for peripheral to memory copy..however i give the input to it my 2nd SDRAM base address - which i name it mem_sdram (im using de2-70). So im assuming that it supposed to be copying only the first data to buffer which i declare earlier. However after the transfer finish..i check the value inside buffer.Its not the same as in mem_sdram. here is the output:
it shows there '3' and followed by 0.Im expecting the buffer to be filled with '78'. because at the first 32bits of mem_sdram i have already write it with this command : iowr_32direct(mem_sdram_base,0,0x12345678); Here is my code:Testing DMA! readaddress =4000000, length =0, status =0, control =1f9 dma transfer: 1ms Transaction complete 0:3 1:0 2:0 3:0# define DEPTH 4 # include <stdio.h># include <stddef.h># include <stdlib.h># include "string.h"# include "system.h" # include "sys/alt_dma.h"# include "altera_avalon_dma_regs.h"# include "altera_avalon_dma.h" # include "sys/alt_cache.h"# include "sys/alt_alarm.h"# include "alt_types.h" volatile int dma_complete = 0; void dma_done (void * handle, void * data) { dma_complete = 1; } void check(void) { alt_u32 control, status, readaddress, length; readaddress = IORD_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE); printf ("readaddress =%x, ", readaddress); length = IORD_ALTERA_AVALON_DMA_LENGTH (DMA_BASE); printf ("length =%x, ", length); status = IORD_ALTERA_AVALON_DMA_STATUS (DMA_BASE); printf ("status =%x, ", status); control = IORD_ALTERA_AVALON_DMA_CONTROL (DMA_BASE); printf ("control =%x \n", control); } int main() { printf("Testing DMA!\n"); alt_u8 buffer; //memset(buffer, 0x55, 2024); alt_dcache_flush_all(); alt_dma_rxchan_dev * rx; alt_u32 start,end; IOWR_32DIRECT(MEM_SDRAM_BASE,0,0x12345678); start = alt_nticks(); if ((rx = alt_dma_rxchan_open ("/dev/dma")) == NULL) { printf ("Error: failed to open device"); exit(1); } else { alt_dma_rxchan_ioctl(rx, ALT_DMA_SET_MODE_8, NULL); alt_dma_rxchan_ioctl(rx, ALT_DMA_TX_ONLY_OFF, NULL); alt_dma_rxchan_ioctl(rx, ALT_DMA_RX_ONLY_ON, (void *)MEM_SDRAM_BASE); check(); } int ret; if ((ret = alt_dma_rxchan_prepare (rx,(void *) buffer, DEPTH , dma_done, NULL)) <0) { printf ("Error: failed to post receive request\n"); exit (1); } while (!dma_complete); end = alt_nticks(); printf("dma transfer: %dms\n",(end-start)); /*start = alt_nticks(); memcpy(buffer,(void *)MEM_SDRAM_BASE,DEPTH); end = alt_nticks(); printf("memcpy transfer: %dms\n",(end-start));*/ printf ("Transaction complete \n"); alt_dma_rxchan_close(rx); for(int x=0;x<DEPTH;x++) { printf("%d:%x\n",x,buffer); } printf("---using IORD---\n"); for(int x=0;x<DEPTH;x++) { printf("%d:%x\n",x,IORD_8DIRECT(MEM_SDRAM_BASE,0)); } return 0; } - Altera_Forum
Honored Contributor
You could have a cache problem. The CPU could be reading its data cache instead of the buffer in memory.
Try to create a second pointer:
and when you print the contents of the buffer, read the data with uncached_buffer[x], and see if you have different results.alt_u8 *uncached_buffer = alt_remap_uncached(buffer,DEPTH); - Altera_Forum
Honored Contributor
--- Quote Start --- You could have a cache problem. The CPU could be reading its data cache instead of the buffer in memory. Try to create a second pointer:
and when you print the contents of the buffer, read the data with uncached_buffer[x], and see if you have different results. --- Quote End --- alt_u8 *uncached_buffer = alt_remap_uncached(buffer,depth); gave compile error : invalid conversion from `volatile void*' to `alt_8*' so i change it to volatile void * uncached_buffer = alt_remap_uncached(buffer,depth);alt_u8 *uncached_buffer = alt_remap_uncached(buffer,DEPTH);but now the "uncached_buffer" variable cannot be read.
- Altera_Forum
Honored Contributor
Sorry, try this:
alt_u8 *uncached_buffer = (alt_u8 *)alt_remap_uncached(buffer,DEPTH); - Altera_Forum
Honored Contributor
--- Quote Start --- Sorry, try this:
--- Quote End --- cool.. it works like a charm .. thank you Daixiwen here is the code (in case somebody else having the same problem):alt_u8 *uncached_buffer = (alt_u8 *)alt_remap_uncached(buffer,DEPTH);
i found that this line , memset(ubuffer, 0x55, depth * 2);# define DEPTH 100 # include <stdio.h># include <stddef.h># include <stdlib.h># include "string.h"# include "system.h" # include "sys/alt_dma.h"# include "altera_avalon_dma_regs.h"# include "altera_avalon_dma.h" # include "sys/alt_cache.h"# include "sys/alt_alarm.h"# include "alt_types.h" volatile int dma_complete = 0; void dma_done (void * handle, void * data) { dma_complete = 1; } void check(void) { alt_u32 control, status, readaddress, length; readaddress = IORD_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE); printf ("readaddress =%x, ", readaddress); length = IORD_ALTERA_AVALON_DMA_LENGTH (DMA_BASE); printf ("length =%x, ", length); status = IORD_ALTERA_AVALON_DMA_STATUS (DMA_BASE); printf ("status =%x, ", status); control = IORD_ALTERA_AVALON_DMA_CONTROL (DMA_BASE); printf ("control =%x \n", control); } int main() { printf("Testing DMA!\n"); alt_u8 buffer; alt_u8 * ubuffer = (alt_u8 *)alt_remap_uncached(buffer,DEPTH); memset(ubuffer, 0x55, DEPTH * 2); //alt_dcache_flush_all(); alt_dma_rxchan_dev * rx; alt_u32 start,end; IOWR_32DIRECT(MEM_SDRAM_BASE,0,0x12345678); start = alt_nticks(); if ((rx = alt_dma_rxchan_open ("/dev/dma")) == NULL) { printf ("Error: failed to open device"); exit(1); } else { alt_dma_rxchan_ioctl(rx, ALT_DMA_SET_MODE_8, NULL); alt_dma_rxchan_ioctl(rx, ALT_DMA_TX_ONLY_OFF, NULL); alt_dma_rxchan_ioctl(rx, ALT_DMA_RX_ONLY_ON, (void *)MEM_SDRAM_BASE); check(); } int ret; if ((ret = alt_dma_rxchan_prepare (rx,(void *) ubuffer, DEPTH, dma_done, NULL)) <0) { printf ("Error: failed to post receive request\n"); exit (1); } while (!dma_complete); end = alt_nticks(); printf("dma transfer: %dms\n",(end-start)); /*start = alt_nticks(); memcpy(buffer,(void *)MEM_SDRAM_BASE,DEPTH); end = alt_nticks(); printf("memcpy transfer: %dms\n",(end-start));*/ printf ("Transaction complete \n"); alt_dma_rxchan_close(rx); for(int x=0;x<DEPTH;x++) { printf("%d:%x\n",x,ubuffer); } printf("---using IORD---\n"); for(int x=0;x<DEPTH;x++) { printf("%d:%x\n",x,IORD_8DIRECT(MEM_SDRAM_BASE,0)); } return 0; }is somehow also affect the output.. -if i comment this line the output is not correct. //seems like we have to initialize the ubuffer first -if i change it to memset(ubuffer, 0x0, depth * 2);, the output is incorrect -if i change it to memset(ubuffer, 0x0, depth); -- somehow the length which must be set has to be double the size of the buffer we need. :p so many mystery that i still dont understand about this dma controller provided by altera in sopc.. rite now im back to trying the transfer from memory to memory with dma controller provided with sopc. memcpy works best without bug for me. somehow the disadvantage is that i have to wait until memcpy operation finish b4 i can do other operation. With dma controller, i can tell it to copy a certain block of memory and do other operation. if the copy operation is done (can check it with flag) i can continue what i want todo with the copied data.
- Altera_Forum
Honored Contributor
There could still be a cache problem, because with your memcpy statement, you are using the cached address, and as a result the NIOS CPU may not immediately write the cache contents to the buffer area. After that you read and display the uncached values, so they could be different than what was written by memcpy.
I wouldn't recommend to keep the memset with DEPTH*2. You are writing on the stack in a space that was probably allocated for something else, and it could trigger all kind of unexplainable bugs in your code. - Altera_Forum
Honored Contributor
....continue from previous post ...
this is an example of a larger chunk transfer using dma from ssram_0 to buffer (allocated in sdram_0)
The output:/* * NIOSimg.cpp * * Created on: Apr 26, 2010 * Author: suki */ # include <stdio.h># include <stdlib.h># include <stddef.h># include <string.h> # include <system.h># include <io.h> # include <alt_types.h># include "sys/alt_dma.h"# include "sys/alt_cache.h"# include "sys/alt_alarm.h"# include "alt_types.h" # define DEPTH 0x4b000 static volatile int txrx_done = 0; //callback function when DMA transfer done static void txrxDone(void * handle, void * data) { txrx_done = 1; } void initMEM(int base_addr,int len) { for (int i=0;i<len;i++) { IOWR_8DIRECT(base_addr,i,i); } } int main() { printf("testing memory to memory DMA transfer operation of 0x%x bytes\n",DEPTH); alt_8 buffer; //memset((void *)SSRAM_0_BASE,0x7a,0x10);//this write base on byte initMEM(SDRAM_1_BASE,DEPTH); //memset((void *)(SDRAM_1_BASE+0x10),0x33,0x10); memset(buffer,0x33,DEPTH); int rc; //request alt_dma_txchan txchan; alt_dma_rxchan rxchan; void* tx_data = (void*)SDRAM_1_BASE; /* pointer to data to send */ void* rx_buffer = (void*)&buffer; /* pointer to rx buffer */ /* 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); } /* Post the transmit request */ if ((rc = alt_dma_txchan_send (txchan, tx_data, DEPTH, NULL, NULL)) < 0) { printf ("Failed to post transmit request, reason = %i\n", rc); //exit (1); } /* Post the receive request */ if ((rc = alt_dma_rxchan_prepare (rxchan, rx_buffer, DEPTH, txrxDone, NULL)) < 0) { printf ("Failed to post read request, reason = %i\n", rc); //exit (1); } printf("DMA transfer running. . ."); /* wait for transfer to complete */ while (!txrx_done); printf ("Transfer finish!\n"); printf("Verifying transfered data using memcmp. . ."); if (!(memcmp((void*)SDRAM_1_BASE,(void*)&buffer,DEPTH))) printf("Verification succesful!\n"); else printf("Verification failed\n"); // printf("content of buffer\n"); // for (int i=0;i<sizeof(buffer)/2;i++) // printf("%d: %x\n",i,buffer); // this output width ,base on what we declare /*printf("content of ssram_0\n"); for (int i=0;i<sizeof(buffer);i=i+2) { printf("%d: %x\n",i/2,IORD_16DIRECT(SSRAM_0_BASE,i)); } printf("content of sdram_1\n"); for (int i=0;i<sizeof(buffer);i=i+2) { printf("%d: %x\n",i/2,IORD_16DIRECT(SDRAM_1_BASE,i)); } memcpy((void*)SDRAM_1_BASE,(void *)SSRAM_0_BASE,20); printf("content of sdram_1: after memcpy operation\n"); for (int i=0;i<sizeof(buffer);i=i+2) { printf("%d: %x\n",i/2,IORD_16DIRECT(SDRAM_1_BASE,i)); }*/ return 0; }
cheers, sukiminna.testing memory to memory DMA transfer operation of 0x4b000 bytes DMA transfer running. . .Transfer finish! Verifying transfered data using memcmp. . .Verification succesful! - Altera_Forum
Honored Contributor
HELLO, thanks for the info. but i am using altera de2 board with one sdram (8Mb)and one sram (512kb). is the same code can be used? by the way, may i know how to configure sram module in sopc? like the setting..? thanks.