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.

MSP430F5510: I2C hangup when reset is happened during I2C operation

Part Number: MSP430F5510


Tool/software:

I've implemented I2C master based on I2C examples source code. It works OK except one thing: when I make reset via debugger during I2C operation (for ex., on breakpoint inside interrupt processing), SDA remains in low state and only power cycling helps to restore operation

Here's my code:

void init_i2c() {
  UCB1CTL1 |= UCSWRST;                      // Enable SW reset
  UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
  UCB1CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
  UCB1BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
  UCB1BR1 = 0;
  UCB1I2CSA = RTC_ADDR >> 1;                // Set slave address
  UCB1IE |= UCNACKIE;                       // allow NACK interrupt
  UCB1CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
}


void i2c_write(uint8_t offset, const uint8_t *data, uint8_t size) {
  i2cbuf = (volatile uint8_t*) data;
  i2clength = size;
  i2coffset = offset;

  UCB1IFG &= ~UCRXIFG;                    // Clear USCI_B1 TX int flag
  UCB1IE |= UCTXIE;                       // Enable TX interrupt
  UCB1CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
  __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0, enable interrupts
  __no_operation();                       // Remain in LPM0 until all data
                                          // is TX'd
  while (UCB1CTL1 & UCTXSTP);             // Ensure stop condition got sent
  UCB1IE &= ~UCTXIE;                      // Disable TX interrupt
}

// USCI B1 interrupt service routine
#pragma vector = USCI_B1_VECTOR
__interrupt void USCI_B1_ISR(void)
{
  switch(__even_in_range(UCB1IV,12))
  {
  case  0: break;                           // Vector  0: No interrupts
  case  2: break;                           // Vector  2: ALIFG
  case  4:
    UCB1IFG &= ~UCNACKIFG;                  // Clear USCI_B1 NACK int flag
    __bic_SR_register_on_exit(LPM0_bits);
    break;                                  // Vector  4: NACKIFG
  case  6: break;                           // Vector  6: STTIFG
  case  8: break;                           // Vector  8: STPIFG
  case 10: break;                           // Vector 10: RXIFG
  case 12:                                  // Vector 12: TXIFG  
    if (i2clength)                          // Check TX byte counter
    {
      UCB1TXBUF = *i2cbuf++;                // Load TX buffer
      i2clength--;                          // Decrement TX byte counter
    }
    else
    {
      UCB1CTL1 |= UCTXSTP;                  // I2C stop condition if this is NOT intermediate byte and this is NOT read op
      UCB1IFG &= ~UCTXIFG;                  // Clear USCI_B1 TX int flag
      __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
    }  
  default: break;
  }
}

  • Are you sure the problem lies on MSP430?

    Can you try to use hardware reset not software reset? At here:

  • The slave is probably waiting for more clocks to complete a byte (slave-transmitter). This can (usually) be cleared with the "9 clocks" trick from I2C Spec (UM10204 rev6) Sec 3.1.16:

    1) Take the pins away from the I2C (clear the relevant PxSEL bits).

    2) Use PxOUT to send (8+1) clocks on the SCL pin.

    3) Put the PxSELn bits back.

    The first few (up to 8) clocks will allow the slave to complete its byte, and it will release SDA for the ACK cycle. The next clock cycle will look like a NACK, and the slave will get off the bus.

**Attention** This is a public forum