Hi,
I think, I run into the I2C-Erratum USCI30. But the Workaround doesn't work.
I use Master Repeated Receive with UCB0.
The Symptoms are ( s Picture):
- SCL clocks endlessy
- No Interrupt any more
The green Signal shows the duration of the Interrupt-Routine.
The delay comes from the Workaround ( waiting for SCL == LOW). The error comes during the reading of bytes.
Do you have any hint?
I've appended the ISR.
regards,
Steffen
#pragma vector = USCI_B0_VECTOR
__interrupt void I2C_B0_ISR(void) {
bool test = true;
int i;
int count;
switch (__even_in_range(UCB0IV, 12)) {
case USCI_I2C_UCNACKIFG: /* NAK interrupt. */
i2c[0].state = STATE_NACK;
UCB0CTL1 |= UCTXSTP;
break;
case USCI_I2C_UCRXIFG: /* RX interrupt. */
/* Read byte, decrement counter. */
/*
UCSI30
other bytes follow the workaround:
Code flow for workaround
(1) Enter RX ISR for reading receiving bytes
(2) Check if UCSCLLOW.UCBxSTAT == 1
(3) If no, repeat step 2 until set
(4) If yes, repeat step 2 for a time period > 3 x t (BitClock) where t (BitClock) = 1/ f
(BitClock)
(5) If window of 3 x t(BitClock) cycles has elapsed, it is safe to read UCBxRXBUF
*/
if (--i2c[0].length) {
test = true;
while (test) {
test = false;
while ((UCB0STAT & UCSCLLOW)!= UCSCLLOW )
;
// High
for (i = 0; i < 7; i++) {
__delay_cycles(15); // BR / 2 = 0x1E / 2 ;
if ((UCB0STAT & UCSCLLOW)!= UCSCLLOW) { // Low
test = true;
break;
}
}
}
*i2c[0].data = UCB0RXBUF;
/* If only one byte left, prepare stop signal. */
if (i2c[0].length == 1) {
UCB0CTL1 |= UCTXSTP;
}
i2c[0].data++;
} else {
*i2c[0].data = UCB0RXBUF;
i2c[0].state = STATE_READY;
}
break;
case USCI_I2C_UCTXIFG:
/* TX interrupt. */
if (i2c[0].state == STATE_WRITING) {
if (!i2c[0].slave_reg_written) {
UCB0TXBUF = i2c[0].slave_reg;
i2c[0].slave_reg_written = 1;
} else if (i2c[0].length) {
/* Send next byte, increment pointer. */
UCB0TXBUF = *(i2c[0].data);
i2c[0].data++;
i2c[0].length--;
} else {
UCB0CTL1 |= UCTXSTP;
UCB0IFG &= ~UCTXIFG;
i2c[0].state = STATE_READY;
}
} else if (i2c[0].state == STATE_READING) {
if (!i2c[0].slave_reg_written) {
UCB0TXBUF = i2c[0].slave_reg;
i2c[0].slave_reg_written = 1;
} else {
/* Repeated start, switch to RX mode. */
UCB0CTL1 &= ~UCTR;
UCB0CTL1 |= UCTXSTT;
/* If single byte, prepare stop signal immediately. */
if (i2c[0].length == 1) {
/* Well, not IMMEDIATELY. First we need to make sure
* the start signal got sent.
*/
while (UCB0CTL1 & UCTXSTT)
;
UCB0CTL1 |= UCTXSTP;
}
}
}
break;
case USCI_I2C_UCALIFG:
/* Arbitration lost interrupt. */
SNASSERT(33);
break;
default:
break;
}
__bic_SR_register_on_exit(LPM0_bits);
}








