-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
I2C stucks after clock stretching time exceeds #24
Comments
Some understanding questions from my side: a) The behaviour of 4. is OK, i.e. SCL is still low and time out exceeded. Then after that: Just to check, when you use a scope, is SCL still low, right? I assume a "yes" here. b) When does your slave continue with i2c communication, i.e. "finish" the clock stretching? Because as long as a slave pulls SCL low, the returnded error code Depending on your answer of b) : In a case, where the i2c bus is stalled, one could try a "de-stalling" or "recovery"-sequence, like described here. After such a sequence, it is expected that "In many cases this will advance the state machine of any blocked slave to a point where it accepts the next start condition again.". |
a) yes I understand that brzo_i2c behavior is correct here, but it looks like we lack functionality to reset bus to original state as described at link you pointing:
I guess brzo_i2c_reset_bus was conceived for this, but it's only stub. |
OK. I did not (yet) implement These kind of "restets" may help or may not, it depends on the slave not releasing the bus. The proper way to do is to reset all slaves on the bus, i.e. either power off the slaves or use their reset pin. In your case, would your slave release the bus after n times toggeling either SDA or SCL? |
Actually there are no issues with slaves - they just work. My workaround for now is to restart master (which in turn reinitializes i2c) and after that all work fine until next "clock-stretch timeout". |
Could you clarify your last comment a bit, I mean when you say " there are no issues with slaves - they just work"? |
yes, right |
Aha. So, if the STM32 is stalling the bus by pulling SCL low, how could the master resolve this? Will the STM32 release SCL, when the master sends a "recovery"-sequence? You wrote "My workaround for now is to restart master (which in turn reinitializes i2c)", this means you reset the esp8266? |
yes :) but I'm sure this can be avoided just be reiniting I2C pins |
Aha, we are getting closer ;-) So, we have to think what makes the STM release SCL? And/or what happens when the esp is turned off... OK, the pin is configured as open drain with pull up and STM pulls low, then by switching the esp off, there is no more vcc and hmmm.... |
No :))) you are going too deep. The case is simple: imagine that there is not i2c slave at all - the ESP i2c will stuck same. Root cause is that i2c line do not restore back at "working" state in case of clock-stretch timeout. |
I meant by this, that one could try to switch pins from "output open drain" to the initial state like after booting up. Probably this could help. You might give it a try? I.e. you would need to use those |
yes, yes, I know that I can do that way, but in my opinion library should do it by itself, i.e. we should not leave I2C bus in undefined state in case of error (or at least in case of "clock-stretch" timeout). Or at least give user easy way to reinit bus in working state back. |
Sorry, I was too short in my previous comment. I meant: Would you mind giving it a try? Because I cannot test it, since I cannot reproduce your setup here. And if it is a success, I will of course add it to the library 😄 |
Sure I give it a try, I just would like that you do it in assembly (because I can't). So, let's do that way - I will write in C, the you will make a "ASM" bomb from that :) |
You probably will laugh :) but looks like you code already have routine to reset bus. Check my pull request. I moved last lines of brzo_i2c_setup (where pins configured in assembly) into brzo_i2c_reset_bus. Now in my routines I check for brzo_i2c_end_transaction return code, and if it 8 then I call brzo_i2c_reset_bus. |
@valkuc sorry for my late reply but my other life keeps me rather busy these days :-/ I had a look at your PR. Checking for clock stretching is implemented the same way for Checking starts here after line 135. Then at line 140, we let SCL raise but leave SDA unchanged. We reach line 167 when clock stretch timout was exceeded and will jump to the exit label Thus, we might end up with the case, where the slave has finally released SCL after the timeout but SDA is still low. If you then try to use And that's why your bus reset code works, because it sets SCL and SDA to open drain and to high. So my conclusion so far is that after you get a stall you could also call If this is correct, then I will add additional statements to |
Actually I'm doing exactly what you asking to check but without reconfiguring pins again (that is done in |
OK, I just wanted to make sure. I prefer adding setting SDA to high in the case of an exceeded timeout in |
Well, if
will be done automatically it's even better than manually checking for clock stretch timeout error and calling reset bus method. |
this is an excellent write up. any progress on this hence it was in Jan already? |
I plan to fix it this week and/or the following weekend. It shouldn't be a big thing. |
I've analyzed the issue again and made changes in @valkuc Could you please test the pre_release branch with your i2c slave against this issue? |
@pasko-zh , sorry for long delay. I have checked pre_release branch and can confirm - it's working. Bus not freezing anymore. Thanks for efforts! |
@valkuc thanks a lot 👍 I will merge it then. |
Merged and new Release published. Thanks again for your support!! |
I got an issue that make I2C bus unusable after receiving code 8 from brzo_i2c_end_transaction. The SCL/SDA line remains low and makes not possible to use bus until reinit.
How to reproduce:
brzo_i2c_setup(3000)
The text was updated successfully, but these errors were encountered: