Tool/software: TI C/C++ Compiler
Hi there,
I identified a problem in a programs execution where periodically when the program is servicing a lot of interrupts - the 8th bit of the read byte appears to get stretched, often by ~2.5ms, or until my timeout code rescues it. The included image shows the I2C SCL, SDA then a GPIO that is toggled on/off at the boundaries of the USCI_B0_VECTOR.
Although there are a quite a few interrupts being serviced over PORT1-4/J, TA0/A1, eUSCI_A0/A1, (~40,0000/sec), I have proven that they don't correlate with the missing interrupt or clock stretching. This is evident due to the fact that the missing 8th bit still occurs in modified version of my driver which operates off of TX/RX interrupts.
The operation is simple:
/// init
UCBxIE = 0;
UCBxCTLW0 |= UCSWRST;
UCBxCTLW0 &= UCSWRST;
UCBxCTLW1 = 0;
UCBxCTLW0 |= (UCMODE_3 | UCMST | UCSYNC); /*!< I2C, Master, Sync */
UCBxCTLW0 |= UCSSEL_2; /*!< SMCLK */
UCBxBRW = 0x00A0; /*!< 100k */
UCBxIFG = 0;
UCBxCTLW0 |= UCTXSTP;
UCAxCTL1 &= ~UCSWRST;
/// enable all interrupts
UCBxIE |= (UCNACKIE | UCSTPIE | UCRXIE | UCTXIE);
/// set for rx
UCBxI2CSA = 0x1E;
UCBxTBCNT = 0;
UCBxCTLW0 &= ~UCTXSTP;
UCBxIFG = 0;
UCBxIE = (UCNACKIE | UCSTPIE | UCTXIE);
UCBxCTLW0 |= UCTR;
UCBxCTLW0 |= UCTXSTT;
/// in rx isr
void rx_iisr(void) {
char val = UCBxRXBUF;
remainingRx--;
// store data
if (remainingRx != 0 || !getExtraByte)
*rxPtr++ = val;
// set send stop at second to last byte
if (remainingRx == 1) {
UCBxCTLW0 |= UCTXSTP;
} else if (remainingRx == 0) {
UCBxIE = 0;
UCBxIFG = 0;
}
}
/// in tx isr
void tx_iisr(void) {
if (remainingTx != 0) {
// deliver data
remainingTx--;
UCBxTXBUF = *txPtr++;
} else if (remainingRx != 0) {
// switch to receiving
UCBxTBCNT = 0;
UCBxCTLW0 &= ~UCTR;
UCBxIE &= ~UCTXIE;
UCBxIE |= UCRXIE;
UCBxCTLW0 |= UCTXSTT;
} else {
// only wanted to send
UCBxCTLW0 &= ~UCTXSTT;
UCBxCTLW0 |= UCTXSTP;
UCBxIE = 0;
UCBxIFG = 0
}
}
void nack_iisr(void) { return; }
void stp_iisr(void) { return; }
The only thing I can see as being wrong is setting the count to zero while the UCSWRST bit isn't set. Of course I haven't set up code to operate solely with this I2C stuff going on but I also can't seem to show why it would miss the rx interrupt. I broke the code on the second entry in the area commented as 'switch to receiving' to inspect the peripherals and the correct interrupts are enabled, no pending interrupts, the pins are configured correctly still.
Another vital question: is the 8th bit being stretched by the master or slave (if it's obvious to anyone)? Inspecting the signals with a scope, the pull-down potential looks to be indistinguishable for both devices so I can't tell. It's not the 9th bit which is surprising.
This issue has been tripping me up for over a week now!

