4 Replies Latest reply on May 26, 2017 11:56 AM by user_365962704

    [SCB SPI] "Corrupted" SPI transfers

    user_365962704

      Hi,

         

      I'm still trying to finish a custom component for the nRF24 radios [1], i wanted to use the component on all the possible PSoCs, so i had to made it work with UDB and SCB blocks.

         

      To test the component i did three projects (attached):

         

      * using PSoC5LP (kit CY8CKIT-059) and SPI based on UDB blocks

         

      * using PSoC4 (kit CY8CKIT-043) and SPI based on UDB blocks

         

      * using PSoC4 (kit CY8CKIT-043) and SPI based on SCB blocks

         

       

         

      So far i have no problems with the UDB projects (see nrf_udb image attached), but i'm having troubles with the SCB implementation (see nrf_scb attached image) the /SS line asserts between transfers.

         

      I'm writing 2 bytes, the first byte contains the COMMAND + REGISTER and the second byte contains the DATA i want to write to the nRF REGISTER.

         

      Here is the function i use to write to the nRF registers, on the top you can see the UDB version and below the SCB implementation:

         

      void nRF24_WriteRegister(const NRF_REGISTER_t reg, const uint8_t data)
      {
      #if !defined(CY_SCB_SPI_H) // UDB Block
          
          SPI_ClearRxBuffer();
          SPI_ClearTxBuffer();
          
          SS_Write(0);
          SPI_WriteTxData(NRF_W_REGISTER_CMD | reg);
          SPI_WriteTxData(data);
          
          while(0 == (SPI_ReadTxStatus() & SPI_STS_SPI_IDLE));
          SS_Write(1);
          
      #else // SCB Block
          
          SPI_SpiUartClearRxBuffer();
          SPI_SpiUartClearTxBuffer();
          
          SPI_SpiSetActiveSlaveSelect(0);
          SPI_SpiUartWriteTxData(NRF_W_REGISTER_CMD | reg);
          SPI_SpiUartWriteTxData(data);
             
          while( SPI_SpiIsBusBusy() );
          
      #endif
      }

         

       

         

      In the example projects both SPI peripherals have a 32 byte TX-FIFO, i'm not familiar enough with the SPI based on the PSoC4 SCB blocks so maybe i'm missing something very obvious, feel free to look into the code and let me know if i'm doing something silly :/ .

         

       

         

      Thanks in advance

         

      Carlos

         

       

         

      PD: If you want to check the most up to date implementation you can find it here:

         

      [1] github.com/C47D/nRF24_Component

        • 1. Re: [SCB SPI] "Corrupted" SPI transfers
          user_1377889

          To remove the SS-line troubles I always remove the component's SS-line and use a seperate pin. At begin of a transaction i pull it low and at the end I release it to high state using Pin_Write() API. Works perfectly.

             

           

             

          Bob

          • 2. Re: [SCB SPI] "Corrupted" SPI transfers
            user_365962704

            Hi,

               

            I will try it that way and report back here, thanks for the tip ;)

               

             

               

            EDIT:

               

            Below is the new function:

               

            void nRF24_WriteRegister(const NRF_REGISTER_t reg, const uint8_t data)
            {
            #if !defined(CY_SCB_SPI_H) // UDB Block
                
                SPI_ClearRxBuffer();
                SPI_ClearTxBuffer();
                
                SS_Write(0);
                SPI_WriteTxData(NRF_W_REGISTER_CMD | reg);
                SPI_WriteTxData(data);
                
                while(0 == (SPI_ReadTxStatus() & SPI_STS_SPI_IDLE));
                SS_Write(1);
                
            #else // SCB Block
                
                SPI_SpiUartClearRxBuffer();
                SPI_SpiUartClearTxBuffer();
                
                SS_Write(0); 
                SPI_SpiUartWriteTxData(NRF_W_REGISTER_CMD | reg);
                SPI_SpiUartWriteTxData(data);
                   
                while( SPI_SpiIsBusBusy() );
                SS_Write(1); 
            #endif
            }

               

             

               

            The SCB datasheet says that the SPI_SpiIsBusBusy() function works based on the /SS line (now absent) so i can't rely on it (see attached image), maybe now i can use the SCB_SpiUartGetRxBufferSize function and wait until the RxBuffer have 2 byte on it, something like this:

               

                SS_Write(0); 
                SPI_SpiUartWriteTxData(NRF_W_REGISTER_CMD | reg);
                SPI_SpiUartWriteTxData(data);
                   
                while( SPI_SpiUartGetRxBufferSize() != 2 );
                SS_Write(1); 

               

            What do you think? hehe

               

             

               

             

               

            Carlos

            • 3. Re: [SCB SPI] "Corrupted" SPI transfers
              user_1377889

              On attached scope you see that the ss-line toggles every byte, that is not ok. Usually caused by too slow feeding with data.

                 

              Your approach using _GetRxBufferSize() will work.

                 

               

                 

              Bob

              • 4. Re: [SCB SPI] "Corrupted" SPI transfers
                user_365962704

                Hi,

                   

                It seems like it worked (see attached image), here's the new function:

                   

                void nRF24_WriteRegister(const NRF_REGISTER_t reg, const uint8_t data)
                {
                #if !defined(CY_SCB_SPI_H) // UDB Block
                    
                    SPI_ClearRxBuffer();
                    SPI_ClearTxBuffer();
                    
                    SS_Write(0);
                    SPI_WriteTxData(NRF_W_REGISTER_CMD | reg);
                    SPI_WriteTxData(data);
                    
                    while(0 == (SPI_ReadTxStatus() & SPI_STS_SPI_IDLE));
                    SS_Write(1);
                    
                #else // SCB Block
                    
                    SPI_SpiUartClearRxBuffer();
                    SPI_SpiUartClearTxBuffer();
                   
                    SS_Write(0);
                    SPI_SpiUartWriteTxData(NRF_W_REGISTER_CMD | reg);
                    SPI_SpiUartWriteTxData(data);

                   


                    while( SPI_SpiUartGetRxBufferSize() != 2 );
                    SS_Write(1);
                    
                #endif
                }

                   

                 

                   

                Maybe i should take the same approach on the UDB block, but for now i will leave it like that, thanks for the help :)

                   

                 

                   

                Carlos