14 Replies Latest reply on Mar 7, 2019 1:11 PM by user_343349849

    SPI inter-byte delay

    user_343349849

      I note a gap between each byte in an array being sent over SPI (using 5LP SPIM component).

       

      Is there a way to prevent this? I assume that it is caused by software polling to see when byte has been sent.

       

      My code is sending and receiving an array and can be blocking until all bytes have been sent.

       

      I have seen DMA used but would this be useful mainly when you want to continue processing other commands while SPI is being sent.

       

      Maybe I should be using an interrupt and checking the the flag instead of reading SPI status between each byte?

       

      Thanks

        • 1. Re: SPI inter-byte delay
          user_13463998

          Hi,

           

          Have you tried SPIM_PutArray() function?

          For sending an array it might be better.

           

          We had some discussion using that function in the topic below.

          SPI bus:  non SCB components

           

          Although the topic is for PSoC 4, PSoC 5LP's SPM also has

              void SPIM_PutAttry(const uint8 buffer[], uint8 byteCount) ;

           

          moto

          • 2. Re: SPI inter-byte delay
            user_343349849

            I am still a bit lost. Is the requirement to load the first byte only used for Slave but master does not need to do it and do I need to check SPI is ready before sending or do I do as below

             

            int readfromspi(uint16 headerLength, const uint8 *headerBuffer, uint32 readlength, uint8 *readBuffer)

            {

             

                int i=0;

                CS_Write(0);

             

                SPIM_PutArray( headerBuffer, headerLength );  //Send Read command to device

                while(!(SPIM_ReadTxStatus() & SPIM_STS_SPI_DONE)){};  //wait till sent  //wait till all bytes sent

             

                SPIM_PutArray( readBuffer, readlength );  //read all bytes by sending dummy bytes

                while(!(SPIM_ReadTxStatus() & SPIM_STS_SPI_DONE)){};  //wait till sent

             

                for(i=0; i<(int)readlength; i++)  //get received data from Spi received buffer

                {

                    readBuffer[i] = SPIM_ReadRxData();

                }

             

               SPIM_ClearRxBuffer();

             

                CS_Write(1);

             

                return 0;

            }

            • 3. Re: SPI inter-byte delay
              user_13463998

              Hi

               

              > I am still a bit lost. Is the requirement to load the first byte only used for Slave

              > but master does not need to do it and do I need to check SPI is ready

              > before sending or do I do as below

              I'm sorry your English is too difficult for me.

              Would you make your sentence shorter and separate topic in each sentence?

               

              I think that you are talking about the SPIS specification.

              Yes, SPIS put 0 for the first byte, so if we want to have our data from the first byte

              we needed to re-wind the pointer then fill the data from the first byte.

              Although this is stated in the Datasheet, I'd rather call it a bug.

              Are you planning to use SPIS, too?

              Then you need to care this "feature", but otherwise you don't have to care about it.

               

              Now my question is by using SPIM_PutArray(), was the gap you were hoping to get rid of taken care of?

              Or is/are there still gap between each byte?

               

              > ... or do I do as below

              As I don't know about the slave connected to your SPIM, I can not predict the behavior of the slave

              but I would add

                   SPIM_ClearRxBuffer() ;

              before receiving the result.

               

              And depending on the slave, may be we need to add some delay between

              sending header and receiving the result.

               

              So I would modify readfromspi() referring the previous topic something like

              =====================

              /* note this is an "IDEA SKETCH" and has not been tested */

              int readfromspi(uint16 headerLength, const uint8 *headerBuffer, uint32 readlength, uint8 *readBuffer)

              {  

                  int i = 0 ;

                  uint8_t rxBufSz  ;

               

                  SPIM_ClearRxBuffer() ;

                  SPIM_ClearTxBuffer() ;

                

                  /* Start transfer */

                  SPIM_PutArray( headerBuffer, headerLength );

               

                  /* Wait for the end of the transfer. In SPI, the number of transmitted data

                     elements has to be equal to the number of received data elements. */

                  rxBufSz = SPIM_GetRxBufferSize();

                  while( headerLength != rxBufSz ) {

                      rxBufSz = SPIM_GetRxBufferSize();

                  }

               

              /* may be we need to allow some time for the slave to prepare data */

               

                    SPIM_ClearRxBuffer() ;

               

                  SPIM_PutArray(readBuffer, readlength);

                  while(readlength != rxBufSz ) {

                      rxBufSz = SPIM_GetRxBufferSize();

                  }

                

                  for (i = 0 ; i < readlength ; i++ ) {

                      mRxBuffer[i] = SPIM_ReadRxData() ;

                  }

               

                 return 0 ;

              }

              =====================

               

              moto

              • 4. Re: SPI inter-byte delay
                user_343349849

                This code cause the micro to lock up at first getRxBufferSize.

                 

                I am surprised how few examples or tutorials I can find for SPI on the PSOC. Some are simple send 1 byte and receive 1 byte and some using DMA. Some of the examples clear the buffers during the routine and others don't and the datasheet does not appear to stipulate what MUST be done for proper transfer.

                 

                I cannot find any decent examples showing how to read a block of data from an external device. The PSOC 4 did have an example for FRAM but it was clearing the buffers every read or write and waiting for each write to end before continuing and resulting in gaps between digits.

                 

                For your example, are you assuming the buffer size is set to 4 in the component and not using the internal circular buffer?

                 

                I also looked around for any decent ebooks for PSOC but could not find much at all.

                • 5. Re: SPI inter-byte delay
                  user_13463998

                  Hi,

                   

                  > This code cause the micro to lock up at first getRxBufferSize.

                  That is not a good sign, but probably it's    

                    SPIM_PutArray( headerBuffer, headerLength );

                  who triggered the problem.

                   

                  > I am surprised how few examples or tutorials I can find for SPI on the PSOC.

                  I totally agree with you. Meantime, the behavior of SPI(M) needs to be adjusted depending on the behavior of the Slave and there are many different behavior(s) from different Slaves, so unless you specify the Slave, it it impossible to specify the exact  behavior of a Master.

                   

                  > For your example, are you assuming the buffer size is set to 4 in the component and not using the internal circular buffer?

                  In the previous discussion we were assuming 16.

                  000-SPI-CONFIG-SPIM.JPG

                   

                  I suppose that the SPIM_PutArray() assumes that the Buffer size is bigger or equal to the length of the buffer to be sent.

                  So I wonder how big is your headerLength and readlength?

                   

                  moto

                  • 6. Re: SPI inter-byte delay
                    user_343349849

                    I think I need to use DMA to get rid of the delays. Are there any "simple" tutorials that show how to get data from SPI to array in memory and visa versa?

                     

                    The packet sizes for the data are specified in the calling routines and are different for various parts of the application so I need to be able to start the DMA each time with different number of bytes to send and receive.

                     

                    Also, the function using the DMA needs to stay in the routine until received bytes are loaded in the receive buffer before returning.

                    • 7. Re: SPI inter-byte delay
                      user_13463998

                      I'm sorry for could not be a help.

                       

                      > I think I need to use DMA to get rid of the delays.

                      > Are there any "simple" tutorials that show how to get data from SPI to array in memory and visa versa?

                       

                      I, myself do not know such tutorial nor application notes,

                      there may be some though.

                       

                      moto

                      • 8. Re: SPI inter-byte delay
                        user_343349849

                        Do you know how I can get help from Cypress Technical Support? The support has gone and now referred just to the forum but I cannot get the answers I need or appropriate documentation.

                         

                        The most hopeful info I found was a post by Bob. I am attempting to rearrange it to suit as per the code below but not sure if this will work.

                         

                        I am not sure whether you just write data to the tx buffer and it automatically sends (So, for example: If I was reading from external SPI ram device should I simply set CS low, write the command bytes and dummy bytes for read and then once tx is done I can assume all received data is in the buffer ready to use?

                         

                        I have not used DMA before. I assume once set up it is the writing to data buffer that triggers the send and then receive happens as incoming data arrives at spi device.

                         

                        Also not sure what I need to call to update the Buffer size (in my attempt below I have re-called the configuration with buffer size as a parameter. But not sure if all I really need to do is write to this line

                         

                        CyDmaTdSetConfiguration(txTD, bufLength*sizeof(DataItem), CY_DMA_DISABLE_TD, TD_INC_SRC_ADR);

                         

                        #include <project.h>

                         

                         

                        void DmaTxConfiguration(uint8 bufLength);

                        void DmaRxConfiguration(uint8 bufLength);

                         

                         

                        /* DMA Configuration for DMA_TX */

                        #define DMA_TX_BYTES_PER_BURST      (sizeof(DataItem))

                        #define DMA_TX_REQUEST_PER_BURST    (1u)

                        #define DMA_TX_SRC_BASE             (CYDEV_SRAM_BASE)

                        #define DMA_TX_DST_BASE             (CYDEV_PERIPH_BASE)

                         

                         

                        /* DMA Configuration for DMA_RX */

                        #define DMA_RX_BYTES_PER_BURST      (sizeof(DataItem))

                        #define DMA_RX_REQUEST_PER_BURST    (1u)

                        #define DMA_RX_SRC_BASE             (CYDEV_PERIPH_BASE)

                        #define DMA_RX_DST_BASE             (CYDEV_SRAM_BASE)

                         

                         

                        #define BUFFER_SIZE                 (8u)

                        #define STORE_TD_CFG_ONCMPLT        (1u)

                         

                         

                        #if(SPIM_USE_SECOND_DATAPATH)

                        typedef uint16  DataItem; // Set this to uint8 or uint16

                        #else

                        typedef uint8 DataItem;

                        #endif

                         

                         

                        /* Variable declarations for DMA_TX*/

                        uint8 txChannel;

                        uint8 txTD;

                         

                         

                        /* Variable declarations for DMA_RX */

                        uint8 rxChannel;

                        uint8 rxTD;

                         

                         

                        DataItem txBuffer [BUFFER_SIZE] = {0x0u};

                        DataItem rxBuffer[BUFFER_SIZE] = {0};

                         

                         

                        void SendSpi(uint8 numBytes){

                            uint8 i;

                           

                            DmaTxConfiguration(numBytes);

                            DmaRxConfiguration(numBytes);

                            txBuffer[0] = 0x01;

                            txBuffer[1] = 0x02;

                            txBuffer[2] = 0x03;

                            while (0u == (SPIM_ReadTxStatus() & SPIM_STS_SPI_DONE))

                            {

                            }

                            //At this point rxBuffer holds all receive data??   

                        }

                         

                         

                        int main()

                        {  

                        uint8 i;

                            SPIM_Start();

                            CyDmaChEnable(rxChannel, STORE_TD_CFG_ONCMPLT);

                            CyDmaChEnable(txChannel, STORE_TD_CFG_ONCMPLT);

                         

                         

                            for(;;)

                            {

                              SendSpi(3);

                              CyDelay(100);

                             

                            }

                        }

                         

                        void DmaTxConfiguration(uint8 bufLength)

                        {

                            txChannel = DMA_TX_DmaInitialize(DMA_TX_BYTES_PER_BURST, DMA_TX_REQUEST_PER_BURST,

                                                                HI16(DMA_TX_SRC_BASE), HI16(DMA_TX_DST_BASE));

                            txTD = CyDmaTdAllocate();

                            CyDmaTdSetConfiguration(txTD, bufLength*sizeof(DataItem), CY_DMA_DISABLE_TD, TD_INC_SRC_ADR);

                            CyDmaTdSetAddress(txTD, LO16((uint32)txBuffer), LO16((uint32) SPIM_TXDATA_PTR));

                            CyDmaChSetInitialTd(txChannel, txTD);

                        }   

                         

                         

                        void DmaRxConfiguration(uint8 bufLength)

                        {

                            rxChannel = DMA_RX_DmaInitialize(DMA_RX_BYTES_PER_BURST, DMA_RX_REQUEST_PER_BURST,

                                                             HI16(DMA_RX_SRC_BASE), HI16(DMA_RX_DST_BASE));

                            rxTD = CyDmaTdAllocate();

                            CyDmaTdSetConfiguration(rxTD, bufLength*sizeof(DataItem), CY_DMA_DISABLE_TD, TD_INC_DST_ADR);

                            CyDmaTdSetAddress(rxTD, LO16((uint32)SPIM_RXDATA_PTR), LO16((uint32)rxBuffer));

                            CyDmaChSetInitialTd(rxChannel, rxTD);

                        }

                         

                        /* [] END OF FILE */

                        • 9. Re: SPI inter-byte delay
                          user_13463998

                          > Do you know how I can get help from Cypress Technical Support?

                          > The support has gone and now referred just to the forum but I cannot get the answers I need or appropriate documentation.

                           

                          I will try to send a message to the Community Manager to contact you about accessing the Technical Support.

                          (BTW, I am not a Cypress Employee, though)

                           

                          moto

                           

                           

                           

                           

                          • 10. Re: SPI inter-byte delay
                            HimaM_31

                            The DMA method will be effective only if the number of bytes is fixed. Otherwise also you can use it. However if you want to chnag eth enumber of bytes very frequently it migh not be an effective way. For changing the number of bytes you will need to disable the DMA channel and then reconfigure the DMA.

                             

                            Can you please have a look at the thread: Problem SPI with DMA

                             

                            Thanks,

                            Hima

                            1 of 1 people found this helpful
                            • 11. Re: SPI inter-byte delay
                              user_343349849

                              Thanks for your response Hima,

                               

                              I will try the approach given in the link you provided.

                               

                              The small delay at start or end of entire function is ok as long as I can run the transfer at max. rate without gaps, it should be fine

                              • 12. Re: SPI inter-byte delay
                                user_343349849

                                Hima,

                                 

                                I attached the files in the wrong forum. I replied to your post for the branching problem but it should have been here. The only issue right now is the speed to spi transactions.

                                 

                                Attached are my project, information regarding speed of spi transfer and a snippet from the datasheet showing spi timing diagram.

                                 

                                I need max. rate spi with no inter-digit gaps.

                                • 13. Re: SPI inter-byte delay
                                  HimaM_31

                                  Hello David,

                                   

                                  As per the expectation there will not be inter byte delay if you have data in the RX buffer all the time. If DMA is able to load the data at the rate at which the data is being sent. The maximum data rate is application specific mostly as the the main factor limiting the maximum data rate between the master and slave is the round trip path delay.

                                   

                                  DMA transfer will happen faster if the drq is configured as level triggered and the Tx Rx flags are configured as given in the code example "SPIM_Example" in PSoC Creator. We do not have a characterised value to give since this is more application dependent.

                                   

                                  Are you facing inter byte delay even after implementing DMA based transfer?

                                   

                                  Thanks,

                                  Hima

                                  • 14. Re: SPI inter-byte delay
                                    user_343349849

                                    Hima,

                                    The DMA has removed the inter-byte delay. The routines appear to be working ok now. Except the application is not reliable. For my prototype, I have long wires dangling between the PSOC and the device and I suspect I am getting poor transfer as a result. However, It the waveforms look good on the Logic Analyzer.

                                     

                                    I have designed a PCB with the 5LP right next to the device to keep tracks short and will try it on the new board.

                                     

                                    If I still have trouble I would be interested in finding someone (happy to pay them if needed) to send the small test PCB and Code and ask them to help me debug my application. Do you know anyone I could approach or a link where I could request?

                                     

                                    Thanks