5 Replies Latest reply on Jan 7, 2020 1:18 PM by MoTa_728816

    SPI only returns 0xffff

    Rova_1179706

      Dear community,

       

       

      For a couple of days I'm trying to extract data from a sensor. I tried using the examples and application notes but could not get it working. I tried it with DMA and interrupts but quickly decided it was too difficult.

       

      The waveforms look good and the Logic analyser displays the correct information. The image below shows a single read-transaction. I only need the second value 0xA800.

       

      main loop

          for(;;)
          {
              UART_PutString("Start Loop:\r\n");
              clearErrors();
              for( int i =0; i < 10; i++){
                  printf("%x\r\n", readSPIWord(0x24));
              }
              
              CyDelay(1000);
          }
      

       

      functions

      void clearErrors(){
          //Write bit + 1E address + 07 data
          SPI_Write(0x1E07 & SPI_WRITE_BITMASK);
          //Write bit + 1F address + 0x46 keycode
          SPI_Write(0x1F46 & SPI_WRITE_BITMASK);
      }
      

       

      uint16 readSPIWord(uint8 address)
      {
          uint16 readword;
          SPI_Write(address << 8);
          while(SPI_IsBusBusy());
          SPI_ClearRxFifo();
          SPI_Write(0x0000);
          while(SPI_IsBusBusy());
          readword = SPI_Read();
          return (uint16)readword; 
      }
      

       

      (Wrong) Result

      Could someone point me in the correct direction?

        • 1. Re: SPI only returns 0xffff
          MoTa_728816

          Hi,

           

          A couple of things, I'd like to check

          (1) Is the MISO signal connected to the right pin?

          (2) What is the pin configuration of MISO pin?

           

          moto

          • 2. Re: SPI only returns 0xffff
            Rova_1179706

            Hi Moto,

             

            My pins are correct I think. When I put random delays at places it returns 0x0000.

            • 3. Re: SPI only returns 0xffff
              MoTa_728816

              Hi,

               

              Getting 0x0000 and 0xFFFF sounds good news.

              This means MISO is receiving both values (0 and 1).

               

              Next things I would try are

              (1) Put some delay between address write and data read.

                 (For this please refer to the datasheet of the sensor)

               

              (2) Change ss0_m to GPIO (output) and keep it low during address write and data read.

              (Same as (1), please check SPI protocol of the sensor)

               

              moto

              1 of 1 people found this helpful
              • 4. Re: SPI only returns 0xffff
                Rova_1179706

                Hi Moto,

                 

                I have succeeded in getting (the correct) data with the following code. I needed to wait until the RX FIFO was cleared entirely. Then write the two words and wait until the FIFO contains them. It feels like a hack to me.

                int main(void)
                {
                    uint8 addresses[9] = {0x1E, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x34, 0x36};
                    __enable_irq();
                    UART_Start();
                
                    /* Also calls init, sets slave to 0 and calls enables */
                    SPI_Start();
                
                    UART_PutString("Hello");
                    for(;;)
                    {
                        UART_PutString("\r\nStart Loop:\r\n");
                        clearErrors();
                        for( int i =0; i < 9; i++){
                            readSPIWord(addresses[i]);
                        }
                        CyDelay(1000);
                    }
                }
                
                
                void clearErrors(){
                    //Write bit + 1E address + 07 data
                    SPI_Write(0x1E07 | (SPI_WRITE_BITMASK << 8));
                    //Write bit + 1F address + 0x46 keycode
                    SPI_Write(0x1F46 | (SPI_WRITE_BITMASK << 8));
                }
                
                
                uint16 readSPIWord(uint8 address)
                {
                    uint16 readword1 = 0xfffe;
                    uint16 readword2 = 0xfffe;
                    uint32 fifobuffer = 0;
                    SPI_ClearRxFifo();
                    while(SPI_GetNumInRxFifo() != 0);
                
                    SPI_Write(address << 8);
                    SPI_Write(0x0000);
                
                    //Don't like this while here
                    while(SPI_GetNumInRxFifo() != 2);
                    fifobuffer = SPI_GetNumInRxFifo();
                    if(fifobuffer){
                      readword1 = SPI_Read();
                      readword2 = SPI_Read();
                    }
                
                    printf("ADD: 0x%x BUFFER: %u - VALUES:0x%x 0x%x\r\n",address, fifobuffer, readword1, readword2);
                    CyDelay(3); //Needed for printf
                    return (uint16)readword1;
                }
                

                 

                Logic Output:

                Without the printf/UART the logic analyzer output is as follows:

                This means the while-delay is not noticeable.

                 

                UART Output:

                   

                Problem:

                The while loop on line 42 will wait forever when something goes wrong with the SPI bus.

                 

                Thanks for your help, I can go on with this. Any feedback is appreciated.

                • 5. Re: SPI only returns 0xffff
                  MoTa_728816

                  Hi,

                   

                  Thank you for the good news!

                   

                  BTW, for a mission-critical application usually, we need to apply a timeout to avoid deadlock.

                   

                  something like

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

                  uint32_t timeout_limit = 20000 ; // you decide how long to wait till timeout

                   

                  ...

                   

                  uint32_t timeout_count ;

                   

                  timeout_count = 0 ;

                  while(SPI_GetNumInRxFifo() != 0) {

                  CyDelayUs(10) ; // please use appropriate delay function here

                    timeout_count++ ;

                    if (timeout_count >= timeout_limit) {

                       // timeout!

                       break ; // or return with error value

                    }

                  }

                  ...

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

                   

                  moto

                  1 of 1 people found this helpful