Forum Discussion

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

DMA problem

why when i use my dma, the program stucks here:

--- Quote Start ---

while (!rx_done);

printf ("Transfer successful!\n");

--- Quote End ---

pls help! thanks!

17 Replies

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

    akira: thanks for your explanation. now i understand better of the function. because i got the code from example and try to understand the flow of the code.

    Cris72: only now i know cant use DMA between SDRAM and flash. i would like to try between flash and SDRAM but as in my other thread, i have problem in writing to flash.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You can't DMA from dram to flash. DMA is like a normal memory write: the only difference is that it's performed by DMA controller and not by CPU.

    Since flash can't be written as RAM, the operation is invalid.

    Anyway the DMA transfer should work, although after execution you will not find in the flash memory the transferred data.

    I suggest in the debug phase you don't use the while(!rx_done) instruction, which involves dma interrupt. Instead, wait for a while (i.e. with a long loop) and then test if your data has been correctly transferred. You may even test the status bits for dma completion.

    As said above you must first change your buffers: dma from sdram to sdram, or from flash to sdram.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    all right.

    this code may be OK.( this is copied from NiosII example, right?)

    you know what is going on.

    after alt_dma_rxchane_pepare();

    DMA is started by the function and continues transfer as long as data remain.

    after then, when transfer is finished the function "done" is called in background of the sequence.

    value in rx_done is turned into "1"

    then the while loop will finish due to its logic.

    so, I'm not sure why dma is not finished.

    but I wonder can you DMA from SDRAM to Flash?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi, this is my code:

    --- Quote Start ---

    # include <stdio.h># include <stdlib.h># include <unistd.h># include "altera_avalon_pio_regs.h"# include "system.h"# include "alt_types.h"# include "sys/alt_dma.h"# include "sys/alt_flash.h" # include "sys/alt_flash_dev.h"# include "altera_avalon_dma_regs.h"# include "altera_avalon_dma.h"

    # define loop 16384# define size 65536

    static volatile int rx_done = 0;

    static void done (void* handle, void* data)

    {

    rx_done = 1;

    }

    int main (int argc, char* argv[], char* envp[])

    {

    alt_flash_fd* fd;

    int ret_code, i;

    int *src_ptr;

    int *dest_ptr;

    int addr;

    int rc;

    alt_dcache_flush_all();

    alt_u32 start,end;

    alt_dma_txchan txchan;

    alt_dma_rxchan rxchan;

    addr = 0;

    src_ptr = SDRAM_BASE + 0x200000; //Location of data written in SDRAM

    dest_ptr = EXT_FLASH_BASE; //Location of data written in flash

    void* tx_data = (void*) SDRAM_BASE + 0x200000; /* pointer to data to send */

    void* rx_buffer = (void*) EXT_FLASH_BASE + 0x100000; /* pointer to rx buffer */

    //Open flash

    fd = alt_flash_open_dev(EXT_FLASH_NAME);

    if(fd!=NULL)

    {

    //Generate data into SDRAM

    for(i=0;i<loop;i++)

    {

    IOWR(src_ptr, i, i);

    }

    //Write data into flash

    while(addr < size)

    {

    ret_code = alt_write_flash(fd, addr, src_ptr+addr, 0x10000);

    if(ret_code != 0)

    {

    printf("Error writing into flash: %d\n", ret_code);

    exit(1);

    }

    addr += 0x10000; // next 64kb block

    }

    //Read from flash

    for(i=0;i<loop;i++)

    {

    printf("Value at %X is %d, written is %d\n", dest_ptr, *dest_ptr, IORD(src_ptr, i));

    dest_ptr++;

    }

    }else

    {

    printf("Unable to open flash\n");

    exit(1);

    }

    /* Create the transmit channel */

    if ((txchan = alt_dma_txchan_open(DMA_NAME)) == NULL)

    {

    printf ("Failed to open transmit channel\n");

    exit (1);

    }

    /* Create the receive channel */

    if ((rxchan = alt_dma_rxchan_open(DMA_NAME)) == NULL)

    {

    printf ("Failed to open receive channel\n");

    exit (1);

    }

    /* Post the transmit request */

    if ((rc = alt_dma_txchan_send (txchan,

    tx_data,

    size,

    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,

    size,

    done,

    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");

    alt_flash_close_dev(fd);

    return 0;

    }

    --- Quote End ---

    I am not sure where it stuck because it does not return any error messages. so i assume dma is working. pls help. thanks!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    you know when rx_done is changed?

    it is changed in an interrupt logic.

    (I'm not quite sure your source code).

    find function which set "rx_done = 1".

    basically, the function is called when rx-dma is done.

    but rx_done is note turned into 1.

    so, which means dma is not done.

    why it is not done is ...

    DMA may not started.

    DMA may stuck in somewhere in your FPGA.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I don't know why it happens.

    but rx_done is not occurred anyway.

    you need to chase rx_done status.

    see you later.