4 Replies Latest reply on Sep 28, 2017 9:02 PM by ntan

    SPI DMA operation

    user_343349849

      Hi,

      I have not used the DMA yet and now looking at using it for Buffer to SPI and SPI to Buffer data transfer.

      For beginning, I thought of using the example code in Creator for 5LP. It appears straight forward but how is the transmission initiated in a real world example?

      Can I simply load data into txBuffer, wait till transfer complete and read results each time I want to transfer, like below?

       

      sprintf(txBuffer,"some data"); //put new data in tx Buffer

      while (0u == (SPIM_ReadTxStatus() & SPIM_STS_SPI_DONE))  { }  //.wait till transferred

      for(i=0u; i<BUFFER_SIZE; i++)

        {

            LCD_PrintHexUint8(rxBuffer[i]);  //read received data

         }

       

      Thanks

        • 1. Re: SPI DMA operation
          user_343349849

          Further to my Post, How do you specify how many bytes to send for any particular transaction?

          • 2. Re: SPI DMA operation
            ntan

            Attached is my project connecting F-RAM to PSoC 3 with DMA.  This project is created by PSoC Creator 3.0 SP1.  So, I don't know if a recent PSoC Creator can be used.

            You can find the same project on my GitHub repository at "GitHub - noritan/Design116_3p0_3: F-RAM test project using SPI "

             

            It seems that the data length is specified by the CyDmaTdSetConfiguration() API function.

             

                // Initialize DMA RX descriptors
                DMA_RX_Chan = DMA_RX_DmaInitialize(
                    DMA_RX_BYTES_PER_BURST, DMA_RX_REQUEST_PER_BURST, 
                    HI16(DMA_RX_SRC_BASE), HI16(DMA_RX_DST_BASE)
                );
                DMA_RX_TD[0] = CyDmaTdAllocate();
                CyDmaTdSetConfiguration(DMA_RX_TD[0],
                    sizeof misoBuffer,
                    CY_DMA_DISABLE_TD,
                    TD_INC_DST_ADR | DMA_RX__TD_TERMOUT_EN
                );
                CyDmaTdSetAddress(DMA_RX_TD[0],
                    LO16((uint32)SPIM_RXDATA_PTR), LO16((uint32)misoBuffer.stream)
                );
                CyDmaChSetInitialTd(DMA_RX_Chan, DMA_RX_TD[0]);
            

             

            Regards,

            Noriaki

            • 3. Re: SPI DMA operation
              user_343349849

              Thanks,

               

              Would something like below work? Where I re-init the dma each call with new numBytes to send/receive. Would I still need the "CyDmaChSetRequest(..." function if I am reinitializing the dma each call?

               

              CY_ISR(DMA_RX_INT_ISR) {

                  DMA_RX_completed = 1;

              }

               

              void spiWrite(uint8 numBytes) {

                 

                  txBuffer[0] = dat0;

                  txBuffer[1] = dat1;

                  txBuffer[2] = dat2;

               

              dmaInit(numBytes);

                     

                  CyDmaChSetRequest(DMA_TX_Chan, CY_DMA_CPU_REQ); ???

                     

                  // Wait for transfer completed

                  while (!DMA_RX_completed) ;

              }

               

              void dmaInit(uint8 numBytes) {

                  // Initialize DMA TX descriptors

                  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],

                      numBytes,

                      CY_DMA_DISABLE_TD,

                      TD_INC_SRC_ADR

                  );

                  CyDmaTdSetAddress(DMA_TX_TD[0],

                      LO16((uint32)mosiBuffer.stream), LO16((uint32)SPIM_TXDATA_PTR)

                  );

                  CyDmaChSetInitialTd(DMA_TX_Chan, DMA_TX_TD[0]);

                 

                  // Initialize DMA RX descriptors

                  DMA_RX_Chan = DMA_RX_DmaInitialize(

                      DMA_RX_BYTES_PER_BURST, DMA_RX_REQUEST_PER_BURST,

                      HI16(DMA_RX_SRC_BASE), HI16(DMA_RX_DST_BASE)

                  );

                  DMA_RX_TD[0] = CyDmaTdAllocate();

                  CyDmaTdSetConfiguration(DMA_RX_TD[0],

                      numBytes,

                      CY_DMA_DISABLE_TD,

                      TD_INC_DST_ADR | DMA_RX__TD_TERMOUT_EN

                  );

                  CyDmaTdSetAddress(DMA_RX_TD[0],

                      LO16((uint32)SPIM_RXDATA_PTR), LO16((uint32)misoBuffer.stream)

                  );

                  CyDmaChSetInitialTd(DMA_RX_Chan, DMA_RX_TD[0]);

              }

               

              Main Loop

              ...

              spiWrite(3);

              for(int i = 0; i < numBytes ; i++)

              {

                //do something with rxBuffer

              }

              ...

              • 4. Re: SPI DMA operation
                ntan

                It is required to call CyDmaChSetRequest(DMA_TX_Chan, CY_DMA_CPU_REQ); to start a DMA transfer with or without initialization.  By calling this API, the DMA writes a byte to the SPI data register and the SPI starts a transfer sequence.

                 

                In addition, don't forget to enable the DMA channel when starting a DMA sequence.

                 

                Regards,

                Noriaki