Forum Discussion
Serious Problem with DMA transfer.
Guys,
I have a desperate problem on my hand. Using DMA to do burst transfers from DDR to on-chip RAM. Using the reference code as shown below. Searched all the forums and confirmed people using the same NIOS code and succesfully making the transfer. Please help Code: int main() { int i,rc; unsigned int On_chip_SRAM_base_dma= 0x41030000; unsigned int DDR_write_OFFSET_ADDRESS_dma=0x00000500; int data_dma[4]={2882343476,4020983416, 9867509251, 6945207616}; unsigned long *sram_ptr2=(unsigned short*)On_chip_SRAM_base_dma; printf("Hello from Nios II!\n"); printf("Testing DMA transfer from DDR to SRAM\n"); for (i=0;i<4;i++){ IOWR(ALTMEMDDR_BASE,DDR_write_OFFSET_ADDRESS_dma + i, data_dma);printf("data: %08x is correctly written to memory offset on ddr: %08x \n",data_dma,DDR_write_OFFSET_ADDRESS_dma+i); } for(i=0;i<4;i++){ read_data1=iord(altmemddr_base,ddr_write_offset_address_dma+i);
printf("read %08x from address %08x on ddr\n",read_data1,(DDR_write_OFFSET_ADDRESS_dma+ i)); } // DMA code alt_dma_txchan txchan; alt_dma_rxchan rxchan; void *tx_data= (void*)DDR_write_OFFSET_ADDRESS_dma; void *rx_buffer= (void*)On_chip_SRAM_base_dma; /* Create the transmit channel */ if ((txchan = alt_dma_txchan_open("/dev/dma_0")) == NULL) { printf ("Failed to open transmit channel\n"); exit (1); } else { printf("Transmit channel setup successful\n"); } /* Create the receive channel */ if ((rxchan = alt_dma_rxchan_open("/dev/dma_0")) == NULL) { printf ("Failed to open receive channel\n"); exit (1); } else { printf("Receive channel setup successful\n"); } /* Post the transmit request */ if ((rc = alt_dma_txchan_send (txchan, tx_data, 4 ,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 , 4, done, NULL)) < 0) { printf ("Failed to post read request, reason = %i\n", rc); exit (1); } /*while(1){ unsigned int status[32]= IOWR_ALTERA_AVALON_DMA_STATUS(0x41000000,0X00); if(status[0]=1){ prontf("VIOLA!!"); break; } } /* wait for transfer to complete */ while (!rx_done); printf ("Transfer successful!\n"); alt_dma_rxchan_close ("/dev/dma_0"); alt_dma_txchan_close ("/dev/dma_0"); //sram_ptr=On_chip_SRAM_base_dma; for(i=0;i<4;i++){ read_data3=*sram_ptr2;
printf("read %08x from address %08x ,read_data3,(On_chip_SRAM_base_dma+ i)); sram_ptr2++; } The results: Hello from Nios II! Testing DMA transfer from DDR to SRAM Data: abcd1234 is correctly written to memory offset on DDR: 00000500 Data: efab5678 is correctly written to memory offset on DDR: 00000501 Data: 4c263e03 is correctly written to memory offset on DDR: 00000502 Data: 9df77540 is correctly written to memory offset on DDR: 00000503 Read abcd1234 from address 00000500 on DDR Read efab5678 from address 00000501 on DDR Read 4c263e03 from address 00000502 on DDR Read 9df77540 from address 00000503 on DDR Transmit channel setup successful Receive channel setup successful Transfer successful! Read 08080808 from address 41030000 //WORING RESULTS!:( Read 00000000 from address 41030001 Read 00000000 from address 41030002 Read 00000000 from address 41030003 Altera Gurus, Please come to the rescue!!!!!!!! Many Thanks. Appreciate your response!
11 Replies
- Altera_Forum
Honored Contributor
In the above code i was testing for just a word transfer(4 bytes) . When I tried transferring 16 bytes, the 00000000s in the result changed as follows:
Hello from Nios II! Testing DMA transfer from DDR to SRAM Data: abcd1234 is correctly written to memory offset on DDR: 00000500 Data: efab5678 is correctly written to memory offset on DDR: 00000501 Data: 4c263e03 is correctly written to memory offset on DDR: 00000502 Data: 9df77540 is correctly written to memory offset on DDR: 00000503 Read abcd1234 from address 00000500 on DDR Read efab5678 from address 00000501 on DDR Read 4c263e03 from address 00000502 on DDR Read 9df77540 from address 00000503 on DDR Transmit channel setup successful Receive channel setup successful Transfer successful! Read 08080808 from address 41030000 //WroNG RESULTS!:( Read 7665642f from address 41030001 Read 7665642f from address 41030002 Read 61746a2f from address 41030003 But still wrong results!:(:(:( Many Thanks. Appreciate your response! - Altera_Forum
Honored Contributor
I would use IORD to readback the destination buffer to make sure you are not reading back cached data. Also the transfer length is in bytes so if you want to move 16 bytes worth of data pass in '16' instead of '4' to the rx and tx calls.
- Altera_Forum
Honored Contributor
Yeah, I am using 16 for 16 bytes transfer. In the code I posted I was just trying for 1 word transfer. And with IORD also , it doesn't work.:(.Anyone else has a clue please????
Looks such a small straight forward thing. Can't figure out what is wrong!!!!!!!!!!!! - Altera_Forum
Honored Contributor
Could it be a problem with memory width?
Why do you use the 'unsigned short' cast? (unsigned short*)On_chip_SRAM_base_dma; Is onchip ram 16-bit or 32-bit wide? - Altera_Forum
Honored Contributor
Nope. I changed that to (long*). Was hoping for something different. BUT No luck there as well.:(
- Altera_Forum
Honored Contributor
Which memory are you running your code from? Make sure it's not in one of those memories you are storing test data or the destination. If you are randomly picking locations which also host your code you might be clobbering your software.
- Altera_Forum
Honored Contributor
@BadOmen.. The DE3 board I am using does not have an on-board SRAM. So I ma assuming that the NIOS code is stored on the on-chip memory which is also my destination. I thought of it, but how do i figure out which locations exactly does my NIOS code occupy??
Many thanks for your reply. really appreciate it!:) - Altera_Forum
Honored Contributor
Your code footprint will change if you breath on it so instead of finding a spot that is not occupied I would do one of the following instead:
- Pre-allocate your buffer so that the compiler will not attempt to place anything there
- Dynamically allocate your buffer at run time
- Altera_Forum
Honored Contributor
SO I DID WHAT YOU SAID. INITIALIZED AN ARRAY AND USED IT TO STORE THE VALUES T MAKE SURE CODE AND DATA DONT OVE
LAP AS FOLLOWS: volatile static int rx_done = 0; static void done_DMA(void* handle, void* data) { rx_done = 1; printf("Thanks Jeez\n"); } int main(int argc, char* argv[], char* envp[]) { int rc,i; long data_dma[4]={0xAAAAAAAA,0xABCD1234, 0x12345678, 0x945207616}; unsigned long DDR_write_OFFSET_ADDRESS_dma=0x03000000; unsigned long read_data1[4],read_data3[4]; for (i=0;i<4;i++){ IOWR(ALTMEMDDR_BASE,DDR_write_OFFSET_ADDRESS_dma + i, data_dma);printf("data %08x is correctly written to memory offset %08x on ddr\n",data_dma,DDR_write_OFFSET_ADDRESS_dma+4*i); } for(i=0;i<4;i++){ read_data1=iord(altmemddr_base,ddr_write_offset_address_dma+i);
printf("read %08x from address %08x on ddr\n",read_data1,(DDR_write_OFFSET_ADDRESS_dma+ 4*i)); } //DMA opeartion alt_dma_txchan txchan; alt_dma_rxchan rxchan; unsigned long* tx_data = (unsigned long*)DDR_write_OFFSET_ADDRESS_dma ;// pointer to data to send unsigned long* rx_buffer = (unsigned long*) read_data3; printf("\n\nTesting DMA transfer from DDR to SRAM\n\n"); alt_dcache_flush_all(); // // 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); } if(alt_dma_txchan_ioctl(txchan,ALT_DMA_SET_MODE_32,NULL)<0) { exit(1); } if(alt_dma_rxchan_ioctl(rxchan,ALT_DMA_SET_MODE_32,NULL)<0) { exit(1); } if(alt_dma_txchan_ioctl(txchan,ALT_DMA_TX_ONLY_OFF,NULL)<0) { exit(1); } if(alt_dma_rxchan_ioctl(rxchan,ALT_DMA_RX_ONLY_OFF,NULL)<0) { exit(1); } // Post the transmit request if ((rc = alt_dma_txchan_send (txchan,tx_data,16,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,16,done_DMA,NULL)) < 0) { printf ("Failed to post read request, reason = %i\n", rc); exit (1); } // wait for transfer to complete while (!rx_done); printf ("Transfer successful!\n\n"); for(i=0;i<4;i++){ printf("Read %08x from address %08x \n",read_data3,&read_data3); } return 0; } Results: Read 00000001 from address 3fffffd0 Read 000001ff from address 3fffffd4 Read 3fffffec from address 3fffffd8 Read deadbeef from address 3fffffdc //DEADBEEF!! what the heck?? Still not working Badomen!! :(
- Altera_Forum
Honored Contributor
Any suggestions people? Still stuck. Fr transferring 16 bytes of burst, even tried using something as:
alt_dcache_flush_all(); & tx_data = (void*)alt_uncached_malloc(0x10); rx_buffer = (void*)alt_uncached_malloc(0x10); to make sure there are no data cache problems. Suggestions please.........