3 Replies Latest reply on Oct 31, 2017 9:49 AM by user_14819776

    DMA from SPIS round robbin


      I'm trying to read the SPIS with DMA.  I have the following setup


      /* Defines for DMA_5 */

      #define DMA_5_BYTES_PER_BURST 1

      #define DMA_5_REQUEST_PER_BURST 1


      #define DMA_5_DST_BASE (CYDEV_SRAM_BASE)


      uint8 DMA_5_Chan;

      uint8 DMA_5_TD[2];

      uint8 spisbuffer0[16];

      uint8 spisbuffer1[16];


      void startDMA5()


      /* DMA Configuration for DMA_5 */
      DMA_5_Chan = DMA_5_DmaInitialize(DMA_5_BYTES_PER_BURST, DMA_5_REQUEST_PER_BURST,
          HI16(DMA_5_SRC_BASE), HI16(DMA_5_DST_BASE));
      DMA_5_TD[0] = CyDmaTdAllocate();
      DMA_5_TD[1] = CyDmaTdAllocate();
      CyDmaTdSetConfiguration(DMA_5_TD[0], 16, DMA_5_TD[1], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
      CyDmaTdSetConfiguration(DMA_5_TD[1], 16, DMA_5_TD[0], TD_INC_DST_ADR | TD_AUTO_EXEC_NEXT);
      CyDmaTdSetAddress(DMA_5_TD[0], LO16((uint32)SPIS_1_RXDATA_PTR), LO16((uint32)spisbuffer0));
      CyDmaTdSetAddress(DMA_5_TD[1], LO16((uint32)SPIS_1_RXDATA_PTR), LO16((uint32)spisbuffer1));
      CyDmaChSetInitialTd(DMA_5_Chan, DMA_5_TD[0]);
      CyDmaChEnable(DMA_5_Chan, 1);



      The SPIS is set to interrupt on FIFO not empty.  That feeds to the DMA to trigger transfers.  The DMA is set for rising edge.  The DMA signal looks clean on my scope, with one pulse per byte on the SPI.  My SPI input clock is roughly 4 Mhz.


      It works fine as it is reading the fist buffer.  It seems like when it starts filling the second buffer, instead,it fills both buffers with a constant, in this case, one of the bytes from my incoming data.  I used the DMA Wizard to set up these values.


      Can I get some help understanding the proper way to set up round robbin reads of hardware?

        • 1. Re: DMA from SPIS round robbin

          You set the TD_AUTO_EXEC_NEXT bit for the 1st and 2nd TDs.  This bit is used to trigger the next TD automatically. Following is the description in the DMA datasheet.


          When 1st byte is received from the SPI master, the 1st TD reads the received value and writes it to the buffer.  After that the 2nd TD will be executed without waiting for receiving the 2nd byte.  So, the SPI's DATA register is read and stored into the buffer.

          If you want to execute one DMA transfer for an SPI byte, the flag should not be set for both TDs.






          • 2. Re: DMA from SPIS round robbin

            Thanks for the help.  I am almost there.


            So if I want it to fill one buffer, then the next buffer, then return to the first buffer, continuously, which TD should the flag be set for? 


            Is it possible for it to refill a single buffer over and over forever without restarting the DMA request?


            What I'm trying to do here is have a really large FIFO buffer that I can read separately.  I am using a counter on the IRQ line to count how many bytes have been received.

            • 3. Re: DMA from SPIS round robbin

              It looks like it works correctly if I remove the NEXT flag from both TDs