You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Wire library lockups recoverable with timeout but without hardware reset #326
#42 is about adding timeouts to the Wire library to prevent lockups. One well-diagnosed case is when noise causes the TWI hardware to think there is a second master and lock up indefinitely until the other master is done. This can only be resolved by resetting the TWI hardware.
However, there is a "jm_Wire" library that implements timeouts but not the hardware reset, which does seem to solve lockup problems for some people, making me suspect there is another failure mode that would be useful to understand better. To prevent clutter in #42, I've opened this issue to further investigate.
I think that in some cases, a timeout without reset could indeed prevent lockups, even if not actually allowing further I2C communication afterwards.
However, the following post triggered my interest, since it mentions disconnecting an I2c slave triggering a lockup, which I can't quite understand. A missing slave should result in a NAK on the address byte, which should be handled as an error by an unmodified Wire already:
In case this is useful testing data, jm_Wire.h fixed my problem mentioned above with my DS3231SN real time clock module, and I can now fully disconnect it from my Uno R3 without it blocking.
@Hyperdimensionals, could you expand a bit on this case? Does the lockup only occur when disconnecting the module at runtime, or also when it is disconnected already at powerup? Can you still reproduce it? If so, could you share the sketch that shows the problem?
I'm using an Uno R3, and a DS3231SN real time clock module with an optional battery backup. It is connected to my 2019 Macbook Pro using the Arduino software version 1.8.12.
This only happens when I unplug the VCC line to the DS3231 module with or without a battery backup. If I unplug the ground, SCL, or SDA line, the program continues running. I'm using a breadboard, and even if I unplug the entire clock module all at once, the program usually keeps running. It only seems to happen when the VCC cable is disconnected, locking up 100% of the time so far.
It blocks even if the VCC is already disconnected before runtime.
Sometimes my program will start running again when the VCC is reconnected, sometimes it will freeze further, though plugging it in and out a few times may get it running again.
I've tried this with two separate DS3231 modules that were presumably identical.
In addition to the MD_DS3231.h library, I've also tried this with another library authored by Korneliusz Jarzebski that I cannot find online (It was included in an Elegoo bundle CD), with the same results.
Replacing Wire.h with jm_Wire.h, my program continues running fine when the VCC line is disconnected. Though sometimes I have to disconnect and reconnect the line a few times for it to read the module's time properly.
Ah, when just unplugging VCC that would make sense. What I think happens is that the DS3231 module without VCC is going to pull down SDA and/or SCL. Then, when the Arduino wants to start an I2C transaction, it will see that the busy is busy, and wait for it to become available again. In this case, having a timeout at least allows the sketch to continue running, but the I²C bus will remain unusable.
In this case, resetting the TWI hardware is not actually going to be useful, since, the bus will remain blocked anyway, so it would just run into another timeout.
One slight variation is that the unplugging of VCC might pull down SCL and SDA in a particular order that looks like a start condition, making the TWI hardware lock itself up. Then, if you replug VCC and the ordering looks like a stop condition, everything will work normally again. This is probably what happens when it unfreezes after reconnecting.
If it does not look a stop condition, I can imagine the TWI hardware will remain locked up, this is probably when happens when you say it stays frozen after reconnecting, or with jm_Wire, when you have to disconnect and reconnect a few times for the time to be read again. For this case, resetting the hardware could help to unfreeze it. This theory could be tested: If you take the Wire library from #107, I would expect that it always starts reading the correct time again directly after reconnecting, without having to try multiple times.
One more addition: If you test #107, you will have to also enable the timeout by calling Wire.setWireTimeout() (or something like that, check the source), since it is not enabled by default.
Thanks for the explanation, that's helpful for an electronics newbie. I will try the library from #107 and see if it reads the correct time immediately.
I'll also note that with the Korneliusz Jarzebski DS3231 library I tried, It also froze when I unplugged the SCL and/or SDA lines, but I solved this by going in and changing instances of wire.endTransmission() to wire.endTransmission(true), but as stated it did not fix the issue for disconnecting the VCC. The MD_DS3231.h seemed to be a better made library and handled the SCL and SDA getting disconnected with the regular Wire.h alone.
The latest code in #107 doesn't do a reset of the hardware unless you ask it to. It sets a timeout flag and the user can do whatever action she pleases when Wire locks up.
Call Wire.setWireTimeoutUs(25000, false) and the library will break out of its lockups after 25ms without resetting the hardware. You can call Wire.getWireTimeoutFlag() to know if there was a timeout and call Wire.clearWireTimeoutFlag() to clear the flag once you've handled it however you choose.
Activity
Hyperdimensionals commentedon Apr 1, 2020
Hello! Here's a simplified sketch I've experienced this with, the MD_DS3231 library using Wire.h:
I'm using an Uno R3, and a DS3231SN real time clock module with an optional battery backup. It is connected to my 2019 Macbook Pro using the Arduino software version 1.8.12.
This only happens when I unplug the VCC line to the DS3231 module with or without a battery backup. If I unplug the ground, SCL, or SDA line, the program continues running. I'm using a breadboard, and even if I unplug the entire clock module all at once, the program usually keeps running. It only seems to happen when the VCC cable is disconnected, locking up 100% of the time so far.
It blocks even if the VCC is already disconnected before runtime.
Sometimes my program will start running again when the VCC is reconnected, sometimes it will freeze further, though plugging it in and out a few times may get it running again.
I've tried this with two separate DS3231 modules that were presumably identical.
In addition to the MD_DS3231.h library, I've also tried this with another library authored by Korneliusz Jarzebski that I cannot find online (It was included in an Elegoo bundle CD), with the same results.
Replacing Wire.h with jm_Wire.h, my program continues running fine when the VCC line is disconnected. Though sometimes I have to disconnect and reconnect the line a few times for it to read the module's time properly.
matthijskooijman commentedon Apr 1, 2020
Ah, when just unplugging VCC that would make sense. What I think happens is that the DS3231 module without VCC is going to pull down SDA and/or SCL. Then, when the Arduino wants to start an I2C transaction, it will see that the busy is busy, and wait for it to become available again. In this case, having a timeout at least allows the sketch to continue running, but the I²C bus will remain unusable.
In this case, resetting the TWI hardware is not actually going to be useful, since, the bus will remain blocked anyway, so it would just run into another timeout.
One slight variation is that the unplugging of VCC might pull down SCL and SDA in a particular order that looks like a start condition, making the TWI hardware lock itself up. Then, if you replug VCC and the ordering looks like a stop condition, everything will work normally again. This is probably what happens when it unfreezes after reconnecting.
If it does not look a stop condition, I can imagine the TWI hardware will remain locked up, this is probably when happens when you say it stays frozen after reconnecting, or with jm_Wire, when you have to disconnect and reconnect a few times for the time to be read again. For this case, resetting the hardware could help to unfreeze it. This theory could be tested: If you take the Wire library from #107, I would expect that it always starts reading the correct time again directly after reconnecting, without having to try multiple times.
matthijskooijman commentedon Apr 1, 2020
One more addition: If you test #107, you will have to also enable the timeout by calling
Wire.setWireTimeout()(or something like that, check the source), since it is not enabled by default.Hyperdimensionals commentedon Apr 2, 2020
Thanks for the explanation, that's helpful for an electronics newbie. I will try the library from #107 and see if it reads the correct time immediately.
I'll also note that with the Korneliusz Jarzebski DS3231 library I tried, It also froze when I unplugged the SCL and/or SDA lines, but I solved this by going in and changing instances of wire.endTransmission() to wire.endTransmission(true), but as stated it did not fix the issue for disconnecting the VCC. The MD_DS3231.h seemed to be a better made library and handled the SCL and SDA getting disconnected with the regular Wire.h alone.
greyltc commentedon May 17, 2020
The latest code in #107 doesn't do a reset of the hardware unless you ask it to. It sets a timeout flag and the user can do whatever action she pleases when Wire locks up.
Call
Wire.setWireTimeoutUs(25000, false)and the library will break out of its lockups after 25ms without resetting the hardware. You can callWire.getWireTimeoutFlag()to know if there was a timeout and callWire.clearWireTimeoutFlag()to clear the flag once you've handled it however you choose.matthijskooijman commentedon Sep 17, 2020
I think there is no further analysis to be done here, so I'm closing this issue.