Forum Discussion

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

DMA receive channel

Hi Nios community,

I'm building a system that uses a DMA device in a NiosII core. It is set up as a DMA receive channel to stream data from a fixed address peripheral to SRAM memory.

There are examples of memory to memory designs, and memory to peripheral designs (DMA transmit channel), but I cannot find an example of a peripheral to memory design.

If a design example for DMA receive channel exists, I would like to find out about it.

Thanks,

peter

8 Replies

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

    Further comments / questions:

    The HAL API for controlling the DMA process appears to be incomplete. To operate a receive side DMA from a fixed address and using flow control (including an endofpacket signal) some bits of the DMA control register need to be set / cleared. The only way to do this is to resort to the IOWR_ALTERA_AVALON_DMA_CONTROL macros and set / clear the bits manually.

    Now I'm thinking why use the API at all, if I need to resort to older style register access macros. Is there any disadvantage to using these macros?

    Any comments or suggestions welcome.

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

    --- Quote Start ---

    originally posted by mumford@Mar 29 2007, 12:52 AM

    further comments / questions:

    the hal api for controlling the dma process appears to be incomplete. to operate a receive side dma from a fixed address and using flow control (including an endofpacket signal) some bits of the dma control register need to be set / cleared. the only way to do this is to resort to the iowr_altera_avalon_dma_control macros and set / clear the bits manually.

    now i'm thinking why use the api at all, if i need to resort to older style register access macros. is there any disadvantage to using these macros?

    any comments or suggestions welcome.

    peter

    <div align='right'><{post_snapback}> (index.php?act=findpost&pid=22603)

    --- quote end ---

    --- Quote End ---

    Hi Peter,

    well I tried to use the HAL API functions, but failed. Maybe I included some headerfiles in the wrong way or don&#39;t no what. Then I changed over to use the IOWR_ALTERA_AVALON_DMA_... macros and it works perfectly. So I couldn&#39;t find any disadvantages.

    Additionally I use the "streaming_output_register" component from "Post your own IP" here in the forum. But in my case it&#39;s again a memory to peripheral design, so can&#39;t tell about the other way round. Anyway, maybe you find some ideas there on how to do it.

    Big success!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks Ellis,

    I will try my design with the macros and avoid the API and see how it goes.

    DMA should be pretty easy, but the lack of complete documentation and design examples is slowing me down a lot.

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

    --- Quote Start ---

    originally posted by mumford@Apr 2 2007, 02:08 AM

    thanks ellis,

    i will try my design with the macros and avoid the api and see how it goes.

    dma should be pretty easy, but the lack of complete documentation and design examples is slowing me down a lot.

    peter

    <div align='right'><{post_snapback}> (index.php?act=findpost&pid=22714)

    --- quote end ---

    --- Quote End ---

    Hi Peter,

    yes, I know what you mean. I add my code with some comments, maybe this helps a bit. Sorry, but I can&#39;t remember where I found it, it was somewhere here in the forum.

    Purpose of this code: Write one line of a picture from memory to peripheral.

    ------------------------------------------------------# define ARRAY_SIZE 1280 // pixel(=byte) amount of one picture line# define SDRAM_MEM_ADD 0x00080000 // base address of picture memory part# define DMA_BASE DMA_0_BASE // this time the dma component is named dma_0

    alt_u32 pic_mem_offset = 0x00000000; // address offset of actual line in memory

    int do_dma(int counter)

    {

    int mode;

    alt_u32 wadd;

    wadd = SDRAM_MEM_ADD | pic_mem_offset; // offset changes after every picture line

    // status bit must be reset

    IOWR_ALTERA_AVALON_DMA_STATUS(DMA_BASE, 0);

    // set read address (memory address in this case)

    IOWR_ALTERA_AVALON_DMA_RADDRESS(DMA_BASE, (int)wadd);

    // set write address (peripheral address in this case)

    IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE, STREAMING_OUTPUT_REGISTER_0_BASE);

    // set dma length (dma component in SOPC builder allows byte, halfword and word, but byte should be enough and "width of DMA length register" is 11 => 2047 > 1280(=ARRAY_SIZE) fits!)

    IOWR_ALTERA_AVALON_DMA_LENGTH(DMA_BASE, sizeof(unsigned char) * ARRAY_SIZE);

    // meaning of registers is explained in Quartus II Handbook, Volume V: Embedded Peripherals, Chapter 4: DMA Controller Core with Avalon Interface

    mode =

    ALTERA_AVALON_DMA_CONTROL_BYTE_MSK |

    ALTERA_AVALON_DMA_CONTROL_GO_MSK |

    ALTERA_AVALON_DMA_CONTROL_LEEN_MSK |

    ALTERA_AVALON_DMA_CONTROL_WCON_MSK |

    0;

    IOWR_ALTERA_AVALON_DMA_CONTROL(DMA_BASE,mode);

    return 0;

    }

    //function call in interrupt handling routine:

    ...

    do_dma(*count_ptr);

    pic_mem_offset += 0x500; // ARRAY_SIZE

    ...

    ------------------------------------------------------

    Any comments welcome!

    <edit> sorry, thought the "*count_ptr" parameter isn&#39;t important for function "do_dma", but it is indeed.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Ellis,

    Thanks for the code.

    I had success using the DMA register control macros instead of the API.

    I think that it is impossible to use the API alone to do what I need to do - please correct me if I&#39;m wrong...I would like to simply use the API.

    Now I&#39;ve just got to get the rest of the design behaving...

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

    Hi Nios users,

    For DMA receive transfers, using the MACRO access to DMA registers instead of the API is the way to go in my opinion.

    You get much better control and understanding of the DMA behavior.

    Using the API is fine for memory to memory transfers.

    My design is working nicely now.

    Some things to watch out for:

    It may be helpful to use

    IOWR_ALTERA_AVALON_DMA_STATUS(DMA_BASE,0);

    to reset before a new transfer.

    Also, if the size of the data reads is not always correct (in hardware) a reset of the write address between transfers sorts things out:

    IOWR_ALTERA_AVALON_DMA_WADDRESS(DMA_BASE, (int)buff_ptr);
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You&#39;re right. Using the macros provided in the regs header for the DMA is much easier. There&#39;s probably a reason for the HAL API (re-entrancy or something like that), but for a simple DMA transfer it&#39;s overkill.

    Even more trivial than what you&#39;ve done, however, is to use C2H to create your own custom DMAs, or, perhaps, try your hand at accelerating some code...

    Cheers,

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

    If the memory required is small enough (i.e. can be on the SOPC), another technique is to use a megafunction such as "altsyncram" for your buffers.