4 Replies Latest reply on Nov 23, 2015 4:47 AM by paulo.amaral

    DMA transfer to SPI

    content.librarian

      Hi Guys,

         
          I am new to PSoc and so to this forum as well. I want to establish a DMA transfer (13bit data) to SPI.   
         
              
         
          Source : SRAM uint16 Array[10] = {};   
         
          DMA - drq is level triggered by FIFO not full interrupt from SPIM   
         
          SPIM : configured to shift  LSB first, Data - 13 bits, mode - 0   
         
              
         
          ISSUE : first 8 bits of data are transmitted correctly, and rest are all messed up.I am able to work it out with 8 bit array, but it somehow doesn't work with 16bits. Can someone here help me out on this. Any help is appreciated.   
         
              
         
          code snippet is attached below :   
         

      Status = 0;
      DMA_RSU_0_Chan = DMA_RSU_0_DmaInitialize(DMA_RSU_0_BYTES_PER_BURST, DMA_RSU_0_REQUEST_PER_BURST, HI16(DMA_RSU_0_SRC_BASE), HI16(DMA_RSU_0_DST_BASE));
      DMA_RSU_0_TD[0] = CyDmaTdAllocate();
      DMA_RSU_0_TD[1] = CyDmaTdAllocate();
      CyDmaTdSetConfiguration(DMA_RSU_0_TD[0],2, DMA_RSU_0_TD[1], 0);
      CyDmaTdSetConfiguration(DMA_RSU_0_TD[1], 1, DMA_RSU_0_TD[0],0);
      CyDmaTdSetAddress(DMA_RSU_0_TD[0], LO16((uint32)&Array[0]), LO16((uint32)SPIM_RSU_0_TXDATA_PTR));
      CyDmaTdSetAddress(DMA_RSU_0_TD[1], LO16((uint32)&Status), LO16((uint32)SPIM_RSU_0_TX_STATUS_MASK_PTR));
      CyDmaChSetInitialTd(DMA_RSU_0_Chan, DMA_RSU_0_TD[0]);
      CyDmaChEnable(DMA_RSU_0_Chan, 1);

         

      PS: I have read all the documents/discussions related to PSoC, and SPIM but I am still struggling to work it out. I must be missing something here. Any help is appreciated.

        • 1. Re: DMA transfer to SPI
          user_14586677

          There are 2 example projects with DelSig over SPIM, 16 bits, that may be

             

          useful. On Creator start page "File", "Example Project" -

             

           

             

           

          • 2. Re: DMA transfer to SPI
            user_14586677

            Blasted paste not working, see attachment.

               

             

               

            Regards, Dana.

            • 3. Re: DMA transfer to SPI
              content.librarian

              Hi danaaknight, Thanks for posting a reply.

                 

              I forgot to mention earlier on, that i was able to achieve this via writing to individual SPI tx register as in the case of the example suggested by you.

                 

              I want to support two SPI blocks transmitting large chunks of 16 bit data simultaneously. Thus i switched to DMA approach. But somehow it doesn't work out.

                 

              Correct me, if my understanding is wrong.

                 

              Thanks again

              • 4. Re: DMA transfer to SPI
                paulo.amaral

                Hello guys,

                   

                 

                   

                I went through the same problem: I was able to work with SPI 16 bits by using the C functions for writing in the TX buffer but was not able to work with DMA moving bytes to the 16 bits FIFO. It's interesting that DMA with SPI 8 bits works fine, but after making a few changes to do a 16 bit communication, the project doesn't work. One can make a 16 bit SPI communication with DMA using SPI 8 bit and transmitting the 2 bytes that form the word. I don't think this is an elegant solution, so I insisted on trying to discover what is wrong with the DMA + SPI 16 bits. After some time of work, I found a tiny modification that made my project with DMA + SPI 16 bit work.

                   

                 

                   

                When configuring the DMA transaction descriptor (in the CyDmaTdSetConfiguration() function),  we have to increment the destination address (TD_INC_DST_ADR), which is the TX fifo (SPIM_TXDATA_PTR).

                   

                 

                   

                My project is attached and, for practical reasons, here follows the code of my DMA configuration (PS: the variable msg (source for the DMA) is a uint16 variable):

                   

                 

                   

                void DMA_TX_Configure(void)
                {
                    /* Defines for DMA_TX */
                    #define DMA_TX_BYTES_PER_BURST 2
                    #define DMA_TX_REQUEST_PER_BURST 1
                    #define DMA_TX_SRC_BASE (CYDEV_SRAM_BASE)
                    #define DMA_TX_DST_BASE (CYDEV_PERIPH_BASE)

                   

                    /* Variable declarations for DMA_TX */
                    /* Move these variable declarations to the top of the function */
                    uint8 DMA_TX_Chan;
                    uint8 DMA_TX_TD[1];

                   

                    /* DMA Configuration for DMA_TX */
                    DMA_TX_Chan = DMA_TX_DmaInitialize(DMA_TX_BYTES_PER_BURST, DMA_TX_REQUEST_PER_BURST, 
                        HI16(DMA_TX_SRC_BASE), HI16(DMA_TX_DST_BASE));
                    
                    DMA_TX_TD[0] = CyDmaTdAllocate();
                    
                    CyDmaTdSetConfiguration(DMA_TX_TD[0], 2, DMA_TX_TD[0], DMA_TX__TD_TERMOUT_EN | TD_INC_DST_ADR);
                    
                    CyDmaTdSetAddress(DMA_TX_TD[0], LO16((uint32)(&msg)), LO16((uint32)SPIM_TXDATA_PTR));
                    
                    CyDmaChSetInitialTd(DMA_TX_Chan, DMA_TX_TD[0]);
                    
                    CyDmaChEnable(DMA_TX_Chan, 1);
                }

                   

                Best regards,

                   

                 

                   

                Paulo Aparecido Amaral Júnior