Forum Discussion

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

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's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hy everyone ..

    I am trying to experiment with this DMA things too.

    The result:

    
    testing ssram & sdram : dma operation 
    content of ssram_0:before DMA operation 
    0: 0 
    1: 1 
    2: 2 
    3: 3 
    4: 4 
    5: 5 
    6: 6 
    7: 7 
    8: 8 
    9: 9 
    10: a 
    11: b 
    12: c 
    13: d 
    14: e 
    15: f 
    content of sdram_1:before 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 
    
    I don'd get the result after that.. seems like it stuck on

    
    while(!txrx_done);
    

    or txrx_done never go to 1 ?

    Besides, "content of sdram_1:before DMA operation " is always changing. Sometimes it'll become :

    
    0: 33
    1: 33
    2: 33
    3: 33
    4: 33
    5: 33
    6: 33
    7: 33
    8: 33
    9: 33
    10: 33
    11: 33
    12: 33
    13: 33
    14: 33 
    15: 33
    

    Any reply will be appreciated Thank you:-P

    Yuyex:o
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    besides , I changed the code to :

    
        /* Post the transmit request */
        if ((tc = alt_dma_txchan_send (txchan,
                tx_data,
                0x10,
                NULL,
                NULL)) < 0)
        {
            printf ("Failed to post transmit request, reason = %i\n", tc);
            exit (1);
        }
       else
        {
            printf ("Succeed to post transmit request when tc = %i\n",tc);
            //exit (1);
        }
        
        /* Post the receive request */
        if ((rc = alt_dma_rxchan_prepare (rxchan,
                rx_buffer,
                0x10,
                txrxDone,
                NULL)) < 0)
        {
            printf ("Failed to post read request, reason = %i\n", rc);
            exit (1);
        }
       else
        {
            printf ("Succeed to post read request when rc = %i\n",rc);
            printf ("txrx_done = %d",txrx_done);
        }
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    How about your txrxDone function?

    Ensure that the txrx_done variable is declared as volatile to prevent any optimisations from reading the value properly.

    Check that tx_data and rx_buffer are pointed to valid memory areas, and memories the DMA's avalon masters are actually connected to.

    If it still doesn't work, put some Signaltap probes on the DMA component to see what it is doing and if/where it gets stuck.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    How about your txrxDone function?

    Ensure that the txrx_done variable is declared as volatile to prevent any optimisations from reading the value properly.

    --- Quote End ---

    I have declared it already.

    --- Quote Start ---

    Check that tx_data and rx_buffer are pointed to valid memory areas, and memories the DMA's avalon masters are actually connected to.

    --- Quote End ---

    I think I have connected it right. (*picture attached)

    
        void* tx_data = (void*)SSRAM_BASE; /* pointer to data to send */
        void* rx_buffer = (void*)SDRAM_1_BASE; /* pointer to rx buffer */
    

    --- Quote Start ---

    If it still doesn't work, put some Signaltap probes on the DMA component to see what it is doing and if/where it gets stuck.

    --- Quote End ---

    I haven't tried this coz I don't know how to do it :(

    --- Quote Start ---

    And don't forget to flush/bypass the data cache where appropriate.

    --- Quote End ---

    Sorry but I don'g get it.. I am new to SOPC stuff. can you please give more explanation?

    Besides , from this thread http://www.alteraforum.com/forum/showthread.php?t=13023 ,it seems like this code (or the code from NIOS II Software's Developer user guide) have some bug, since "while (!dma_done);" doesn't work at all. I have changed it by using if-statement

    
        if (txrx_done == 1)
        {
        printf ("Transfer Function Done!\n");
        /* Post the receive request */
        if ((rc = alt_dma_rxchan_prepare (rxchan,
                rx_buffer,
                0x10,
                rx_done,
                NULL)) < 0)
        {
            printf ("Failed to post read request, reason = %i\n", rc);
            exit (1);
        }
       else
        {
            printf ("Succeed to post read request when rc = %i\n",rc);
            printf ("txrx_done = %d\n",txrx_done);
            //printf ("done = %d",done);
        }
    
    but it still doesnt work! :confused:

    Is it a bug on the callback function?? since txrx_done never become 1.

    
    //callback function when DMA transfer done
    static void tx_done(void * handle, void * data)
    {
        txrx_done = 1;
    }
    
    Any reply will be appreciated:)

    Yuyex:)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The problem with the if is that if it is executed before the DMA transfer ends, then you will exit your main function without displaying anything. That's why the original code had a while(). Besides I don't think it's a good idea to wait for the end of the tx operation before setting the tx channel. I don't know how the HAL driver is written, but there is probably nothing happening in the DMA until both the transmit and receive channels have been configured.

    You should have a look at the turorials to learn how to use SignalTap. It is relatively easy to use and is an essential debugging tool in those kind of situations.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thank you for your reply Daixiwen:o,

    Btw , is it true that this "SignalTap" function can only be used in Quartus II and NIOS II version 11.0 or later?

    Since I am using Quartus 10.1 and NIOS II 10.1.

    Besides, seems like it's using Qsys rather than SOPC? (page.11 on the PDF)

    Source : http://www.altera.com/literature/an/an446.pdf

    Or you guys have some good examples for me to practice this "SignalTap" function?:)

    Thank you in advance,

    Yuyex:o
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    No SignalTap can be used with older versions of Quartus and SOPC builder without any problems.