Forum Discussion
Altera_Forum
Honored Contributor
21 years agoDMA transfer length problem
http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/wink.gif
There is a problem in transferring data from SDRAM to my device ( avalon slave device ) . I use the DMA component provided by SOPC Builder (QuartusII 4.0 + sp1 ) . My system use the Nios II processor and my soft program write with the HAL . The problem : When the transferring data size is bigger than 574720 byte , the program come to a halt situation. But , when the data size is smaller than 574720 byte , the program work normally. I have set the width of DMA length register for 30 bits .The program still has the problem . Is there a idea to solve the problem ? http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/tongue.gif5 Replies
- Altera_Forum
Honored Contributor
I have next assume.
Maybe your device sets "endofpacket" signal before ending of transferring. In this case disable bit REEN or WEEN, it depends on a direction or transferring. Other case there is an increment of write address. Disable WCON in this case. I hope it helps you http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/smile.gif - Altera_Forum
Honored Contributor
My slave device use the basic avalon signals and I don't use the end of packet .
I have no experience to disable REEN or WEEN or WCON. How to do this work ? - Altera_Forum
Honored Contributor
You can use IOWR(DMA_BASE, some_value_of_control_register_dma);
See description of dma control register in n2cpu_nii51006.pdf. - Altera_Forum
Honored Contributor
I still can not solve the problem.
I read the DMA control register and the length register . The results of the two register are normal. This is my soft program : int main(void) { printf("Hello from Nios II!\n"); //perform the DMA test unsigned int* data_source ; data_source = (unsigned int*) alt_uncached_malloc(258624); //fill the source memory int m; for(m=0 ; m < 258624 ; m++ ) { *(data_source+m)=0x00111111; } //test the DMA alt_dma_txchan tx; tx = alt_dma_txchan_open("/dev/dma_0"); if(tx== NULL) { printf("\n DMA Test: DMA ERROR "); } // perform dma transfer void* tx_data =(void*) data_source ; int rc; alt_dma_txchan_ioctl(tx,ALT_DMA_RX_STREAM_ON,(void *)(USER_DEFINED_ME_BASE)); if((rc=alt_dma_txchan_send(tx,tx_data, (1796*80*4) ,tx_done, NULL ))<0) { printf("\n Failed to post transmit request ,reason %i",rc); exit(1); } printf("\n Wait for DMA Transfer ... "); while(!tx_complete){} printf("\n DMA Transaction complete ! "); return 0; } - Altera_Forum
Honored Contributor
Try to use io.h's functions IOWR and IORD as next:
unsigned int *p = (unsigned int*)(SDRAM_BASE + 0xF4240); void *pdma = (void*) SD_DMA_BASE; //Interrupt function if need void isr_dma(void* context, alt_u32 id) { if ((IORD_ALTERA_AVALON_DMA_STATUS(SD_DMA_BASE))&&ALTERA_AVALON_DMA_STATUS_DONE_MSK) { IOWR_ALTERA_AVALON_DMA_STATUS(SD_DMA_BASE, 0); IOWR_ALTERA_AVALON_DMA_RADDRESS(SD_DMA_BASE, (int)p); IOWR_ALTERA_AVALON_DMA_WADDRESS(SD_DMA_BASE, SD_BASE); IOWR_ALTERA_AVALON_DMA_LENGTH(SD_DMA_BASE, 40); IOWR_ALTERA_AVALON_DMA_CONTROL(SD_DMA_BASE, 0x02DC); } } int main(void) { unsigned int *p = (unsigned int*)(SDRAM_BASE + 0xF4240); ............. //Write to memory something (in this case 10 words) for (i=0, pattern=0xFFAAFFAA; i<10; i++) { IOWR_32DIRECT(p+i, 0, pattern); } //Registration of interrupt function if it need alt_irq_register(SD_DMA_IRQ, pdma, isr_dma); //Send to some device 10 words IOWR_ALTERA_AVALON_DMA_STATUS(SD_DMA_BASE, 0); IOWR_ALTERA_AVALON_DMA_RADDRESS(SD_DMA_BASE, (int)p); //Pointer to memory IOWR_ALTERA_AVALON_DMA_WADDRESS(SD_DMA_BASE, SD_BASE); //Pointer to your device IOWR_ALTERA_AVALON_DMA_LENGTH(SD_DMA_BASE, 40); //Sending 10 words (1 word == 4 bytes) IOWR_ALTERA_AVALON_DMA_CONTROL(SD_DMA_BASE, 0x02DC); //See description of dma control register ............... }