So admittedly I am abusing the I2C bus, that's the point. I'm trying to make it fail and then self-correct.
See message #502 in the i2c_t3 thread for more context. In my slightly modified i2c_t3, I2C_AUTO_RETRY is enabled and I can see how many times resetBus has been executed.
I was running the PCA9548A_Test program (github code and readme about hardware in use), and decided I needed pullups on all the mux SDA outputs. Naturally I did this while the test was running. I triggered these errors, see below. What I expected was TIMEOUT would trigger the retry and resetBus would fix things. This did not happen, though resetBus did execute - but only once.
In the i2c_t3.cpp source code, the only applicable place ARB_LOST status gets set (sendTransmission, I am doing a write) is line 1011:
This is a single-master system. Did I mention SDA and SCL are both high during all this time? So the Teensy master is not attempting to drive SCL. Interesting TODO there...
I reset Teensy via TyQt and surprisingly it then was able to run OK with no further error in startup or init. So it seems the PCA9548A was not the culprit (makes sense: the slave can't drive either SCL or SDA high), it was apparently Teensy which thought it can't drive SCL for some reason. From the comments above it looks like mode gets changed to receive, but then Teensy should still drive the SCL, and call resetBus() if TIMEOUT happens.
TIMEOUT does repeatedly happen so why is resetBus() not called? If I understand the code around line 795, it might be because Teensy thinks it is not the master.
In the meantime I am going to add ability to call resetBus() from my test program command line interface. I'm also changing to Wire.setDefaultTimeout(10000); though 10 msec seems over long, I saw that in the i2C_t3 example code somewhere.
What's the way out of this? Have I discovered a subtle bug? Can someone smarter than I shed some light and suggest a fix?
See message #502 in the i2c_t3 thread for more context. In my slightly modified i2c_t3, I2C_AUTO_RETRY is enabled and I can see how many times resetBus has been executed.
I was running the PCA9548A_Test program (github code and readme about hardware in use), and decided I needed pullups on all the mux SDA outputs. Naturally I did this while the test was running. I triggered these errors, see below. What I expected was TIMEOUT would trigger the retry and resetBus would fix things. This did not happen, though resetBus did execute - but only once.
Code:
et:9185 Good:42391361 4616/sec
et:9186 Good:42395969 4616/sec
et:9187 Good:42400577 4616/sec
simple test in middle of write/read loop failed with return of 0x04: I2C_TIMEOUT
control write failed with return of 0x07: I2C_ARB_LOST
et:9188 Good:42401594 4616/sec bad:2 busReset: 1
control write failed with return of 0x04: I2C_TIMEOUT
control write failed with return of 0x07: I2C_ARB_LOST
et:9189 Good:42401594 4615/sec bad:4 busReset: 1
control write failed with return of 0x04: I2C_TIMEOUT
control write failed with return of 0x07: I2C_ARB_LOST
In the i2c_t3.cpp source code, the only applicable place ARB_LOST status gets set (sendTransmission, I am doing a write) is line 1011:
Code:
// check arbitration
if(status & I2C_S_ARBL)
{
i2c->currentStatus = I2C_ARB_LOST;
*(i2c->S) = I2C_S_ARBL; // clear arbl flag
// TODO: this is clearly not right, after ARBL it should drop into IMM slave mode if IAAS=1
// Right now Rx message would be ignored regardless of IAAS
*(i2c->C1) = I2C_C1_IICEN; // change to Rx mode, intr disabled (does this send STOP if ARBL flagged?)
return;
}
I reset Teensy via TyQt and surprisingly it then was able to run OK with no further error in startup or init. So it seems the PCA9548A was not the culprit (makes sense: the slave can't drive either SCL or SDA high), it was apparently Teensy which thought it can't drive SCL for some reason. From the comments above it looks like mode gets changed to receive, but then Teensy should still drive the SCL, and call resetBus() if TIMEOUT happens.
TIMEOUT does repeatedly happen so why is resetBus() not called? If I understand the code around line 795, it might be because Teensy thinks it is not the master.
In the meantime I am going to add ability to call resetBus() from my test program command line interface. I'm also changing to Wire.setDefaultTimeout(10000); though 10 msec seems over long, I saw that in the i2C_t3 example code somewhere.
What's the way out of this? Have I discovered a subtle bug? Can someone smarter than I shed some light and suggest a fix?
Last edited: