2 Replies Latest reply on Feb 22, 2015 3:23 PM by stephen.santarelli

    16 or 32 bit DMA writes won't work with shift register


      Hi All,


      I cannot transfer anything more than single byte burst DMA to the shift register component . I've read and re-read data sheets, app notes, and just can't find anything I am doing wrong. I've used the same setup successfully with the SPI master (the code is adapted from the SPI Master example project) and it works fine transferring 16 bits at a time . I can do 16 or 32 bit word transfers to the shift register component fine using the API function.


      The address of the register being written to is 0x40006544, which is 32 bit word aligned, so it does not seem to be an alignment problem.


      I'm not sure if there is something being done wrong, or I might have stumbled onto a defect. If someone would look at this, it would be greatly appreciated. I've got this design running on a PSoC 5 CY8CKIT-050 development board, the crystal has been replaced with a 14.318MHz crystal, you might need to change the clock settings back to 24/48MHz.


      Project archive is attached, relevant C code is also copied below.


      Thanks for looking



      #define DMA_TX_M_BYTES_PER_BURST       (2u)
      #define DMA_TX_M_REQUEST_PER_BURST     (1u)
      #define DMA_TX_M_SRC_BASE              (CYDEV_SRAM_BASE)
      #define DMA_TX_M_DST_BASE              (CYDEV_PERIPH_BASE)

      /* Variable declarations for DMA_Tx_M */
      uint8 M_TxChannel;
      uint8 M_TxTD[2u];

      /* Data to be transmitted by Tx */
      uint16 m_txBuffer [8u] = {0x8001u, 0x8001u, 0x8001u, 0x8001u, 0x8001u, 0x8001u, 0x8001u, 0x8001u };

      int main (void)
          uint32 i;
          // Write 16 bit data to shift register FIFO
          for (i=0; i < ShiftReg_1_FIFO_SIZE; i++)

          CyDmaChEnable(M_TxChannel, 1u);

      void Dma_Configuration()
          // Init DMA, 2 byte bursts, each burst requires a request
                                               HI16(DMA_TX_M_SRC_BASE), HI16(DMA_TX_M_DST_BASE));

          M_TxTD[0u] = CyDmaTdAllocate();
          M_TxTD[1u] = CyDmaTdAllocate();

          // Configure this Td chain as follows:
          // - The TD is looping on itself
          // - Increment the source address, but not the destination address  
          CyDmaTdSetConfiguration(M_TxTD[0u], 16u, M_TxTD[1u], TD_INC_SRC_ADR ); //
          CyDmaTdSetConfiguration(M_TxTD[1u], 1u, M_TxTD[1u], 0u);
          // address for 32 bit wide reg:  ShiftReg_1_bSR_sC32_BShiftRegDp_u0__F0_REG
          // Address for 16 bit wide reg:  ShiftReg_1_bSR_sC16_BShiftRegDp_u0__F0_REG
          // Address for 8  bit wide reg:  ShiftReg_1_bSR_sC8_BShiftRegDp_u0__F0_REG
          CyDmaTdSetAddress(M_TxTD[0u], LO16((uint32)m_txBuffer),    LO16((uint32)ShiftReg_1_bSR_sC16_BShiftRegDp_u0__F0_REG ));
          CyDmaTdSetAddress(M_TxTD[1u], LO16((uint32)m_txBuffer), LO16((uint32)m_txBuffer));
          // Associate the TD with the channel
          CyDmaChSetInitialTd(M_TxChannel, M_TxTD[0u]);


        • 1. Re: 16 or 32 bit DMA writes won't work with shift register

          Welcome in the forum!


          You are using two quite different TDs chained together, why not using a single TD in a loop. When the first TD finished transferring 16 Bytes in two byte chunks, the second TD takes over transferring 1(!!) byte (which is an error!!) in an infinite loop.


          Better is to loop on the first TD only.


          You can pick the destination definition from the Shiftreg_1.h file, they are not as cryptic as in cyfitter.h, so you can use


              CyDmaTdSetConfiguration(M_TxTD[0u], 16u, M_TxTD[0u], TD_INC_SRC_ADR );


              CyDmaTdSetAddress(M_TxTD[0u], LO16((uint32)m_txBuffer), LO16((uint32)ShiftReg_1_IN_FIFO_VAL_LSB_PTR ));



          • 2. Re: 16 or 32 bit DMA writes won't work with shift register

            Hi Bob,




            Thanks for the response.  I tried removing the second TD entirely, as you sugguest, but still no go.  It appears that only one byte is getting transferred (I am looking at the serial output of the shift register). If I disable DMA and fill the FIFO with 0x8001, I get both pulses with the correct spacing.




            It would be great to get this working, as I have a neat single chip video application that I would like to share.  It is working with NTSC, but I also want it to display 640x480 VGA, and I need the 16 or 32 bit transfers with the shift register to get it to work.