Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
16 years ago

Nios Uart And Dma

HI:

I try to transfer datas from uart to onchip memory using DMA,following code is my programme,I use uart assistant to transfer data per 1000m second ,but sometimes I can see the right datas on onchip memory but sometimes i can not.

#include <stdio.h>

#include "system.h"

#include "string.h"

#include <stddef.h>

#include <stdlib.h>

#include "sys/alt_dma.h"

#include "alt_types.h"

#include "altera_avalon_uart_regs.h"

//main &#20027;&#31243;&#24207;

int main()

{

int rc;

void * rx_buffer = (void*) 0x27000;

alt_dma_rxchan rx;

rx = alt_dma_rxchan_open("/dev/dma_uart5");

/* Obtain a handle for the device */

if (rx != null)

{

printf("dma start.");

while(1)

{

/* Post the receive request */

alt_dma_rxchan_ioctl(rx,ALT_DMA_SET_MODE_8,null);

alt_dma_rxchan_ioctl(rx,

ALT_DMA_RX_ONLY_ON,(void*) UART_5_BASE);

if ((rc=alt_dma_rxchan_prepare(rx,rx_buffer,20,

null, null))< 0)

{

printf ("Error: failed to post receive request,reason = %i\n", rc);

exit (1);

}

alt_dma_rxchan_close (rx);

printf("done!");

}

}

return 0;

}

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi,

    I also want to transmit data from UART to memory by using DMA and I have the same problem you discribe. So I´m glad to see that I´m not the only one with that problem. But first of all I think you don´t really know what a DMA should do. So I´m wondering why prepare DMA without using the interrupt handle. The next think is that you close DMA after prepare him in order to open DMA again cause you are in an endless while loop. That doesn´t seem to make sense. You have to wait till DMA has finished. Thats why you have to use the DMA interrupt handle - I think.

    And last you should begin with a transfer of 4 Byte. I realized that the DMA works better with a small transfer size than with a large one.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    hi ,

    my problem has been resolved ,the uart ip has "end of packet"selection,if you use it,it sets zero as the end character,so if your characters to be transferred include zero,the uart will stop the transfer when it meets zero .:)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    hi,

    kind of new in the nios world, trying to use dma with my uart...

    you wrote :

    void * rx_buffer = (void*) 0x27000;

    can you explain this please ?

    I understand that DMA is a cpu feature, is it a default or I need to add it to my system ?

    how do you access the the in coming data ?

    thank you...
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    hi ,

    my problem has been resolved ,the uart ip has "end of packet"selection,if you use it,it sets zero as the end character,so if your characters to be transferred include zero,the uart will stop the transfer when it meets zero .:)

    --- Quote End ---

    Hi,

    Currently I got problem with DMA as Rx channel :(. What I'm trying to don now is I want to verify whether the DMA can handle data transfer from a PIO to memory. So in my verification system here, I'm doing a loopback test by adding two PIOs in my SOPC system which functions as the data transmitter (the PIO's name is PIO_DUMY_OUTPUT) and receiver (the PIO's name is PIO_DATA_8BIT), respectively. I connected those PIO's in my verilog code.

    Here is my code :

    
    volatile static 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, int data)
    {
    	int i;
    	for (i=0; i<len; i++)
    	{
    		IOWR_8DIRECT(base_addr+i, 0, 33);
    	}
    }
    // peripheral - memory transfer 1
    void pio_transfer()
    {
    	int		rc, i, mode;
    	int     dma_len = 0x25;
    	alt_dma_rxchan	rxchan;
    	void * rx_buffer = (void*) DDR3_TOP_BASE;
    	txrx_done = 0;
    	// -------------------------------------------------------------------------------
    	printf("testing peripheral to memory dma operation\n");
    	initMEM(DDR3_TOP_BASE,dma_len,3);
    	printf("content of the memory content before DMA operation : \n");
    	for (i=0; i<dma_len; i++)
    	{
    		printf("%d : %x\n", i, IORD_8DIRECT(DDR3_TOP_BASE,i));
    	}
    	// -------------------------------------------------------------------------------
    	if((rxchan = alt_dma_rxchan_open("/dev/dma_data_8bit")) == NULL)
    	{
    		printf("Failed to open receive channel\n");
    		exit(1);
    	}
    	// -------------------------------------------------------------------------------
    	if(alt_dma_rxchan_ioctl(rxchan,ALT_DMA_SET_MODE_8,NULL)<0)
    	{
    		exit(1);
    	}
    	printf("debug0 \n");
    	check_dma();
    	if(alt_dma_rxchan_ioctl(rxchan,ALT_DMA_RX_ONLY_ON, (void*) PIO_DATA_8BIT_BASE)<0)
    	{
    		exit(1);
    	}
    	// -------------------------------------------------------------------------------
    	printf("debug1 \n");
    	if((rc = alt_dma_rxchan_prepare(rxchan, rx_buffer, dma_len, NULL, NULL))<0)
    	{
    		printf("Failed to post receive request, reason = %i\n", rc);
    		exit(1);
    	}
    	// -------------------------------------------------------------------------------
    	printf("PIO : generate, transmit, and receive the dummy data\n");
    	for (i=0; i<dma_len; i++)
    	{
    		IOWR_ALTERA_AVALON_PIO_DATA(PIO_DUMY_OUTPUT_BASE, 3*i+2);
    		printf("PIO : receiving dummy data : %d - %d\n",IORD_ALTERA_AVALON_PIO_DATA(PIO_DATA_8BIT_BASE), txrx_done);
    	}
    	IOWR_ALTERA_AVALON_PIO_DATA(PIO_DUMY_OUTPUT_BASE, '\0');  //write end-of-packet character
    	// -------------------------------------------------------------------------------
    	printf("debug2 \n");
    	check_dma();
    	printf("wait DMA transfer is completed\n");
    	//while(!txrx_done);
    	//alt_dma_rxchan_close (rxchan);
    	printf("Transfer is success\n");
    	check_dma();
    	// -------------------------------------------------------------------------------
    	printf("content of the memory DDR3 content after DMA operation : \n");
    	for (i=0; i<dma_len; i++)
    	{
    		printf("%d : %x\n", i, IORD_8DIRECT(DDR3_TOP_BASE,i));
    	}
    	// -------------------------------------------------------------------------------
    }

    And here is the result :

    
    content of the memory content before DMA operation : 
    0 : 21
    1 : 21
    2 : 21
    3 : 21
    4 : 21
    5 : 21
    6 : 21
    7 : 21
    8 : 21
    9 : 21
    10 : 21
    11 : 21
    12 : 21
    13 : 21
    14 : 21
    15 : 21
    16 : 21
    17 : 21
    18 : 21
    19 : 21
    20 : 21
    21 : 21
    22 : 21
    23 : 21
    24 : 21
    25 : 21
    26 : 21
    27 : 21
    28 : 21
    29 : 21
    30 : 21
    31 : 21
    32 : 21
    33 : 21
    34 : 21
    35 : 21
    36 : 21
    PIO : generate, transmit, and receive the dummy data
    PIO : receiving dummy data : 2 - 0
    PIO : receiving dummy data : 5 - 0
    PIO : receiving dummy data : 8 - 0
    PIO : receiving dummy data : 11 - 0
    PIO : receiving dummy data : 14 - 0
    PIO : receiving dummy data : 17 - 0
    PIO : receiving dummy data : 20 - 0
    PIO : receiving dummy data : 23 - 0
    PIO : receiving dummy data : 26 - 0
    PIO : receiving dummy data : 29 - 0
    PIO : receiving dummy data : 32 - 0
    PIO : receiving dummy data : 35 - 0
    PIO : receiving dummy data : 38 - 0
    PIO : receiving dummy data : 41 - 0
    PIO : receiving dummy data : 44 - 0
    PIO : receiving dummy data : 47 - 0
    PIO : receiving dummy data : 50 - 0
    PIO : receiving dummy data : 53 - 0
    PIO : receiving dummy data : 56 - 0
    PIO : receiving dummy data : 59 - 0
    PIO : receiving dummy data : 62 - 0
    PIO : receiving dummy data : 65 - 0
    PIO : receiving dummy data : 68 - 0
    PIO : receiving dummy data : 71 - 0
    PIO : receiving dummy data : 74 - 0
    PIO : receiving dummy data : 77 - 0
    PIO : receiving dummy data : 80 - 0
    PIO : receiving dummy data : 83 - 0
    PIO : receiving dummy data : 86 - 0
    PIO : receiving dummy data : 89 - 0
    PIO : receiving dummy data : 92 - 0
    PIO : receiving dummy data : 95 - 0
    PIO : receiving dummy data : 98 - 0
    PIO : receiving dummy data : 101 - 0
    PIO : receiving dummy data : 104 - 0
    PIO : receiving dummy data : 107 - 0
    PIO : receiving dummy data : 110 - 0
    content of the memory DDR3 content after DMA operation : 
    0 : 0
    1 : 0
    2 : 0
    3 : 0
    4 : 0
    5 : 0
    6 : 0
    7 : 0
    8 : 0
    9 : 0
    10 : 0
    11 : 0
    12 : 0
    13 : 0
    14 : 0
    15 : 0
    16 : 0
    17 : 0
    18 : 0
    19 : 0
    20 : 0
    21 : 0
    22 : 0
    23 : 0

    So anyone can tell me why the DMA can't write correctly the data that received by PIO_DATA_8BIT to DDR3 ? Is my loopback test wrong? Is it possible to handle data transfer from a PIO to memory like what I'm doing? :confused:

    Thanks before, I really appreciate any comments and help :)