This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Missing bytes in USCI_Bx Receive Buffer Register

Other Parts Discussed in Thread: MSP430F5435

Hi,

I'm currently working with a MSP430F5435 microcontroller. It is connected to a Cypress USB controller through the I2C interface. I'm using USCI port B0. The I2C interface operates at 400 kbps. The TI microcontroller always acts as a slave on the I2C interface, the Cypress controller always being the master device. The communication pattern is the following one:

a) the Cypress microcontroller initiates an I2C write transaction to the TI F5435 microcontroller which receives a serie of 5 bytes;

b) the Cypress microcontroller initiates an I2C read transaction from the TI F5435 microcontroller which responds with a serie of 5 bytes.

The problem occurs when reading the content of the UCB0RXBUF register and copying it into a variable located in RAM. If at the same time this register is read, the last bit of a new byte is just entering on the I2C port, the TI F5435 microcontroller returns the ACK bit to acknowledge this transaction, but the byte is never transfered into the UCB0RXBUF. The only way I found to prevent this bug is to copy the content of UCB0RXBUF into a CPU register by using a local variable not declared neither static nor volatile.

Here is my interrupt code.

// Number of loops before reporting an error for false call to interrupt service routine
#define INTERRUPT_SRC_WAIT_LOOP  20U

#pragma vector=USCI_B0_VECTOR             // Priority 56
static __interrupt void UsciB0_Isr(void);

static __interrupt void UsciB0_Isr(void)
{
   BYTE byLoopCnt = 0U;
   BOOL bWakeUp   = def_FALSE;

   __delay_cycles(10U);                      // Workaround for Errata SYS7 (TI MSP430F541x Device Erratasheet Document #SLAZ046).

   while (byLoopCnt < INTERRUPT_SRC_WAIT_LOOP)
   {
      switch (UCB0IV)
      {
         case USCI_NONE:                     // Vector 0: No interrupt
            // @@@@ When operating I2C bus at 400 kbps, interrupt handler is frequently called before the interrupt vector register
            //      UCB0IV is ready. A simple retry mechanism has been added here to avoid logging a bunch of false error message.
            bWakeUp = def_TRUE;
            byLoopCnt++;
            if (byLoopCnt == INTERRUPT_SRC_WAIT_LOOP)
            {
               err_AddEntry(err_eERROR, err_eINT_USCIB0_FAULT, "False USCI B0 interrupt!", err_FILE, err_LINE, def_TRUE);
            }
            break;

         case USCI_I2C_UCALIFG:              // Vector 2: USCI_I2C_UCALIFG
            err_AddEntry(err_eERROR, err_eINT_USCIB0_FAULT, "I2C USCI_I2C_UCALIFG!", err_FILE, err_LINE, def_TRUE);
            bWakeUp   = def_TRUE;
            byLoopCnt = INTERRUPT_SRC_WAIT_LOOP;
            break;

         case USCI_I2C_UCNACKIFG:            // Vector 4: USCI_I2C_UCNACKIFG
            err_AddEntry(err_eINFO, err_eINT_USCIB0_FAULT, "I2C USCI_I2C_UCNACKIFG!", err_FILE, err_LINE, def_TRUE);
            bWakeUp   = def_TRUE;
            byLoopCnt = INTERRUPT_SRC_WAIT_LOOP;
            break;

         case USCI_I2C_UCSTTIFG:             // Vector 6: USCI_I2C_UCSTTIFG
            i2c_StartBit();
            bWakeUp   = def_TRUE;
            byLoopCnt = INTERRUPT_SRC_WAIT_LOOP;
            break;

         case USCI_I2C_UCSTPIFG:             // Vector 8: USCI_I2C_UCSTPIFG
            bWakeUp   = i2c_bStopBit();
            bWakeUp   = def_TRUE;
            byLoopCnt = INTERRUPT_SRC_WAIT_LOOP;
            break;

         case USCI_I2C_UCRXIFG:              // Vector 10: USCI_UCRXIFG
            i2c_bRxInt();
            byLoopCnt = INTERRUPT_SRC_WAIT_LOOP;
            break;

         case USCI_I2C_UCTXIFG:              // Vector 12: USCI_UCTXIFG
            i2c_TxInt();
            byLoopCnt = INTERRUPT_SRC_WAIT_LOOP;
            break;

         default:
            err_AddEntry(err_eERROR, err_eINT_USCIB0_FAULT, "Unkown USCI B0 interrupt source!", err_FILE, err_LINE, def_TRUE);
            bWakeUp   = def_TRUE;
            byLoopCnt = INTERRUPT_SRC_WAIT_LOOP;
            break;
      }
   }
   if (bWakeUp == def_TRUE)
   {
      // Wake up microcontroller on exit
      __low_power_mode_off_on_exit();
   }
}

static BYTE  g_pbyInData[cmd_BUFFER_IN_LENGTH];          // Rx Input Buffer
static UWORD g_uwInWrInx;                                // Rx Input buffer write index

BOOL i2c_bRxInt(void)
{
   BOOL bResponse = def_FALSE;
   BYTE byTemp;

   // @@@@ Must use a local variable to read data from USCI B0 Rx buffer. If byte is extracted from
   //      USCI B0 RX buffer and directly copied into another memory location, we miss some bytes
   //      received on I2C bus.
   byTemp = UCB0RXBUF;                                   // Fetch the received byte into local variable
   g_pbyInData[g_uwInWrInx] = byTemp;                    // Insert the last received byte into input buffer
   g_uwInWrInx++;
   bResponse = def_TRUE;

   return bResponse;
}

Did anyone observe the same behavior or something similar with this microcontroller or another one in another familiy? Any feedback would be greatly appreciated. Thanks!

**Attention** This is a public forum