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!