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.
Hello there,
We have a setup with the MCU I2C module configured in master mode, 400 kbps, RM=0 and is connected to the TI TCA6424A I/O expander device. Bus signal is perfect and somehow our setup works rather well, except that during multi-hours operation, the BB bit in the status register don't want to release from busy for about 0.5% to 0.6% of the time.
Before confirming BB=1 is a problem, there is a timeout of 2ms, which is very long. When BB doesn't want to release itself, we perform I2CMDR_bit.nIRS = 0; then I2CMDR_bit.nIRS = 1; and we're good to go again, until the next occurrence, after which the next checking is always bus released, which means that the BB=1 would never occur in a consecutive manner.
Just an idea for the number of accesses, the checking to the BB bit is performed 3 times each 50ms (20 Hz), every time when a new write or read operation is about to initiated.
It happens for both read or write to the device. Below is the called functions before each write or read operation:
void SetTxMode(u8 count) { I2CCNT = count; //method 1: working fine except bus busy problem I2CMDR_bit.MST = 1; // master mode I2CMDR_bit.TRX = 1; // transmit mode I2CMDR_bit.STT = 1; // send START condition + slave address + TRX state I2CMDR_bit.STP = 1; // send STOP condition once I2CCNT reaches 0 } void SetRxMode(u8 count) { I2CCNT = count; //method 1: working fine except bus busy problem I2CMDR_bit.MST = 1; // master mode I2CMDR_bit.TRX = 0; // receive mode I2CMDR_bit.STT = 1; // send START condition + slave address + TRX state I2CMDR_bit.STP = 1; // send STOP condition once I2CCNT reaches 0 }
We're in this since many months now. Could anyone help please?
After a START condition and before a subsequent STOP condition, the I2C bus is considered busy, and the bus busy (BB) bit of I2CSTR is 1. Between a STOP condition and the next START condition, the bus is considered free, and BB is 0. BB is cleared to 0 after the reception of a STOP condition.
When BB=1 happens, what is the value of other bit in STR register, for example SCD bit, AL bit? Have you probed the bus to see what the waveforms look like when this issue occurs?
Hi QJ,
I didn't probe the bus signal but the MCU I2C module is dedicated to one single I/O expander, so nobody else is sharing the bus, TX is only 1 register byte/cycle of 50ms with 1 check on BB, and RX is 2 bytes/cycle with 1 check on BB before writing op code and 1 check on BB before sending 2-byte data for a total of 3 checks on BB per 50ms.
Another note: although the occurrences never come in consecutively, but when it does happen, it tends to happen many times within a short period of time ...
When that happens, SCD=1 and AL=0. Below is the I2CSTR register contents.
SCD is 1 which means a STOP condition is generated.
When MCU is master-receiver, the master send NACK after the last byte is clocked out of the slave (TCA6424A). The TCA6424A release the data line allowing the master (MCU) to generate a STOP condition.
I don't know how hard to capture the I2C waveform when the error occurs. It would be helpful to how SCL and SDA look like: if the SDA is released, or if there is a glitch on the I2C SCL line, or if the SCL is generated properly for NACK bit and STOP.
Hello QJ,
Thank you for the suggestions. I've fixed the problem of BB and this must be a hard-to-find one. Let me explain.
I2CMDR_bit.STT = 1; // send START condition + slave address + TRX state I2CMDR_bit.STP = 1; // send STOP condition once I2CCNT reaches 0
The problem lies between those two lines of code (bitfield write) when the CPU was interrupted in-between by a FIQ/IRQ, and the I2C module has time to do its things (by sending out the start condition+address and set back STT=0), but the CPU came back from ISR and assume that the STT remains at 1, therefore triggers a new start condition at the end of the current operation (after stop condition)
The detailed explanation is below:
Between the software writing I2CMDR_bit.STT and writing I2CMDR_bit.STP, there should be a delay or check to ensure that the START condition has been executed so STT=0 before writing STP=1. Otherwise in the event where the MCU was interrupted by FIQ/IRQ between those two lines, the I2C would have time to execute the START condition and set STT=0 in the internal I2CMDR register of the I2C module, but the bitfield-write of STP=1 using IAR-created-bitfield-structure didn't have the opportunity to readback the current I2CMDR value so it forces a second write to STT=1 (while the internal I2C STT=0). The behavior is that when the current I2C bus write has ended (the STP bit would be cleared), another START condition is then generated and nobody would stop it, causing the I2C bus hung (BB=1).
Thank you again!
Good capture. Thanks Chuck. But I don't understand why I2CMDR_bit.STP = 1 can set STT bit.
This is because bit write is not supported to the TI MCU I2CMDR register. IAR's compiler would have to write twice the same register for those two instructions, by ORing the previous register contents.
In this case when the STP is written, the previous register contents still have the STT=1, hence the problem for the second start condition.
Hope that helps.