5 Replies Latest reply on Dec 11, 2018 12:21 AM by Yasuhito.Ito_3191501

    CyU3PSpiTransmitWords bug (SDK library 1.34)

    Yasuhito.Ito_3191501

      Hi,

      After we updated SDK version from 1.3.3 to 1.3.4, our SPI flash read code sometimes works incorrectly.

      With FX3SDKVERSION="1_3_4" , I suspect that CyU3PSpiTransmitWords() has a bug: it may abort in the middle of transmission and return success.

       

      The implementation is changed at 1.3.4 and it can be summarized as:

      1. Parameter check and setup.
      2. LOOP_A: For each words to be transmitted:
        1. Wait for FIFO empty status (TX_SPACE) with polling.
        2. Write a word to the register.
      3. Wait for transmit done interrupt bit (TX_DONE) with polling.
      4. Disable the TX.

       

      Consider the following scenario:

      1. Preempted in the middle of the transmittion loop. (LOOP_A)
      2. Normally write from CPU is fast and consuming by SPI H/W block is slow, but in this case CPU write is stopped and only SPI block is active.
      3. It is possible that SPI block completes the transmission of all data in the FIFO and raises TX_DONE interrupt.
      4. CPU returns, write the rest data, and exits the loop.
      5. Wait for TX_DONE interrupt, but it is already asserted at (3.) timing for the first half of data. Exits immediately, mistakenly.
      6. Disable the TX. Transmission aborts and returns success.

       

      Although I cannot fully confirmed yet, it seems that disabling interrupts is effective during the loop with CyU3PVicDisableAllInterrupts() - CyU3PVicEnableInterrupts() .

      Could anyone review it?

        • 1. Re: CyU3PSpiTransmitWords bug (SDK library 1.34)
          abga

          Hi,

           

          Yes this scenario may happen, so here is the fix suggested (see the bold line)

           

          for (i = 0; i < byteCount; i += wordLen)

              {

                  /* Copy data to be written into local variable. The padding required is to nearest byte.

                    Do fallthrough switch instead of using a loop.

                  */

                  temp = 0;

                  switch (wordLen)

                  {

                      case 4:

                          temp |= (data[i + 3] << 24);

                      case 3:

                          temp |= (data[i + 2] << 16);

                      case 2:

                          temp |= (data[i + 1] << 8);

                      default:

                          temp |= data[i];

                          break;

                  }

                  /* Wait for the tx_space bit in status register */

                  while ((SPI->lpp_spi_status & CY_U3P_LPP_SPI_TX_SPACE) == 0)

                  {

                      if (timeout-- == 0)

                      {

                          status = CY_U3P_ERROR_TIMEOUT;

                          break;

                      }

                  }

                  if (status != CY_U3P_SUCCESS)

                  {

                      break;

                  }

                  SPI->lpp_spi_egress_data = temp;

              }

              /* Wait for the transmit FIFO to become empty. */

              while ((SPI->lpp_spi_status & CY_U3P_LPP_SPI_TX_DONE) == 0)

              {

                  if (timeout-- == 0)

                  {

                      status = CY_U3P_ERROR_TIMEOUT;

                      break;

                  }

              }

           

          Instead of checking for TX_DONE interrupt now we are checking for TX_DONE status which will fix the issue. I am attaching the modified library please replace it with the old one in in the following path

          C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\fw_lib\1_3_4\fx3_debug

          Please make a copy of the old library before replacing.

           

          Try and let me know if you are still facing the issue.

           

          Thanks & Regards

          Abhinav Garg

          • 2. Re: CyU3PSpiTransmitWords bug (SDK library 1.34)
            Yasuhito.Ito_3191501

            With the attached library, CyU3PSpiTransmitWords() always returns CY_U3P_ERROR_TIMEOUT.  I have already tried your idea and it did not work.  TX_DONE status bit is never asserted.  (or may be asstered only for one cycle, etc.)

            The idea seems to be correct if the status bit is implemented as our expectation.  Is it possible to confirm the status bit spec and implementation with H/W team?

            • 3. Re: CyU3PSpiTransmitWords bug (SDK library 1.34)
              Yasuhito.Ito_3191501

              I have one more question.

              CyBootProgrammer.img in SDK 1.4.4 uses this library and function?

              • 4. Re: CyU3PSpiTransmitWords bug (SDK library 1.34)
                abga

                Hi,

                 

                Try with this new modified firmware library. In this library TX_Done interrupt bit is cleared blindly after writing the data in the egress register. Try to reproduce the issue with this modified library.

                 

                Thanks & Regards

                Abhinav

                • 5. Re: CyU3PSpiTransmitWords bug (SDK library 1.34)
                  Yasuhito.Ito_3191501

                  I have already tried the same idea and it was effective.  The issue cannot be reproduced with attached library and our application.

                   

                  However, the following senario can still be considered.

                  1. (n - 1) words write loop
                  2. The LAST write loop
                    1. Clear TX_DONE interrupt bit.
                    2. !!! CPU Interrupted at this timing.  (n - 1) words are transmitted and TX_DONE interrupt bit is asserted.
                    3. Write the LAST word to the egress register.
                  3. Wait for TX_DONE interrupt bit.  !!! break this loop mistakenly.

                   

                  Is it possible to guarantee that all words will be transmitted correctly even in that case?

                  If not, this fix is not acceptable for production level.