-
Notifications
You must be signed in to change notification settings - Fork 7k
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
reduce speed of I2C master bus reset routine and release SDA #2493
Conversation
Did you find it was necessary to slow it to 100Khz or just enough to overcome capacitive effect? I think signal should also be Start, 9 clocks, Start, Stop |
@jeremyherbert I agree with the speed reduction you propose(I stole it and added it to my pr #2496), but I think the reset code needs to handle interrupted reads. |
@negativekelvin In this case, I needed to slow it down so the chip would be within spec (although at the max frequency, the bus capacitance did prevent the clocks from being generated). It worked at a fair bit above 100kHz, but I think this is out of spec. The other option is to store the user specified clock rate somewhere other than the I2C registers (like a static global) and then use that to compute the correct delay. To be honest, I think that the latter is a better solution, but I didn't want to submit a pull request with new global variables given that I do not know what the rules are around them in this codebase. @stickbreaker I'm not sure I fully understand the issue with interrupted reads. I just followed the I2C spec which says that if SDA is stuck low, send 9 clocks. Obviously if SDA is stuck low because the ESP32 is holding it low as a GPIO (as is the case at the moment), the clocks won't do anything to release it ;) When performing a read from the slave, according to the I2C spec the NACK will cause the slave to release the line (if it still has the ability to) because it isn't possible to generate a stop without it being released:
If the NACK doesn't allow the master to generate the STOP, then the slave device is probably seriously broken and needs to be hard-reset anyway, so no amount of clocks will help. |
@negativekelvin one more thing I realised; it's not possible to generate an initial start condition if the SDA line is stuck low ? Also I didn't add the stop sequence (and by definition, there also needs to be a start before it, because SDA is high once released). I will add it and squash it into the old commit. I don't really mind which pull request gets added though, as long as the problem is fixed :) |
You are right but you can still generate the rising clock edge and it shouldn't hurt to try to generate the first start and the second start should work. |
@jeremyherbert in my experience with 24LCxx EEPROMS, The NAK will not stop the EEPROM from outputting the next byte when it sees the clock signal. I wrote the current I2C driver for the Arduino-ESP32 repo, during my testing of I2C bus recovery I discovered these I2C devices would hold the bus forever as long as a STOP or START was not issued. A NAK did not release the bus. When I reset the ESP32 while it was transacting a READ operation, a 9 bit manual stimulation of the SCL pin with SDA high would not cause the EEPROM to release SDA. The only way to get the 24LCxx EEPROMS to drop out of READ mode was to generate a valid STOP or START. This behavior also applied to the 9 axis MPU9250. Before I figured out the need to synchronize with NAK or a 1 bit, I had to power cycle the EEPROM to reliably exit READ mode after a reboot. This only occurred because the data in my EEPROM had a big block of ZEROS, and the MPU9250 also had a block of ZEROS in its fifo/registers. I was testing with READS of 64k-1, so I usually reset the ESP32 while it was in the middle of one of these block reads. Unless the data being read out happened to end at a 1bit, the existing reset code could not generate a STOP. If the I2C hardware peripheral was initialized with SDA low, the peripheral would lockup in a BUS_BUSY state and never manipulate SDA and SCL.
Yes, but the reset code needs to synchronize with the NAK to generate the STOP.
You can regenerate the clock rate by directly reading uint32_t old_count = (i2c->dev->scl_low_period.period+i2c->dev->scl_high_period.period);
if(old_count>0) {
result = APB_CLK_FREQ / old_count;
This is the arduino-esp32 code to clear a stuck i2c bus checkLineState() With my implementation of i2c, I have found it is not necessary to actually generate the STOP. It is enough just to get SDA and SCL HIGH then start the peripheral. The peripheral's first action will be to generate a START. Chuck. |
@stickbreaker what you are saying makes sense to me now, thank you. Although that behaviour does appear to violate the I2C standard (I think?) I'm sure there are devices out there which do not meet it. As far as the |
@jeremyherbert I missed the line 582 significance. I think your use of a fixed 100khz freq is satisfactory. I guess if someone designs a board with such weak pullups and high capacitance that it cannot support the minimum i2c freq, they can change a constant and re-compile. Chuck. |
Thanks for contributing this fix, @jeremyherbert . This commit has been cherry-picked with some other I2C fixes and should be merged to master shortly. |
I am stealing this delay coding from @jeremyherbert #2493 pr. 2. Change Bus Reset to handle interrupted READ sequences. The current code does not handle interrupted READ cycles. If a SLAVE device was in a read operation when the bus was interrupted, the SLAVE device is controlling SDA. The only bit during the 9 clock cycles of a byte READ the MASTER(ESP32) is guaranteed control over, is during the ACK bit period. If the SLAVE is sending a stream of ZERO bytes, it will only release SDA during the ACK bit period. The master(ESP32) cannot generate a STOP unless SDA is HIGH. So, this reset code synchronizes the bit stream with, Either, the ACK bit, Or a 1 bit. 3. fix typo correct `sda_id` to `sda_io` in `i2c_master_clear_bus()` @ryan-ma found it. This typo was generated when I manually edited this patch on GitHub, I should have done a Copy/Paste operation!
I am stealing this delay coding from @jeremyherbert #2493 pr. 2. Change Bus Reset to handle interrupted READ sequences. The current code does not handle interrupted READ cycles. If a SLAVE device was in a read operation when the bus was interrupted, the SLAVE device is controlling SDA. The only bit during the 9 clock cycles of a byte READ the MASTER(ESP32) is guaranteed control over, is during the ACK bit period. If the SLAVE is sending a stream of ZERO bytes, it will only release SDA during the ACK bit period. The master(ESP32) cannot generate a STOP unless SDA is HIGH. So, this reset code synchronizes the bit stream with, Either, the ACK bit, Or a 1 bit. 3. fix typo correct `sda_id` to `sda_io` in `i2c_master_clear_bus()` @ryan-ma found it. This typo was generated when I manually edited this patch on GitHub, I should have done a Copy/Paste operation!
… SDA closes #2494 closes #2493 closes #2496 1. Change bus reset to handle interrupted READ sequences. 2. Slow down I2C to 100khz during reset 3. If a SLAVE device was in a read operation when the bus was interrupted, the SLAVE device is controlling SDA.The only bit during the 9 clock cycles of a byte READ the MASTER(ESP32) is guaranteed control over, is during the ACK bit period. If the SLAVE is sending a stream of ZERO bytes, it will only release SDA during the ACK bit period. The master(ESP32) cannot generate a STOP unless SDA is HIGH. So, this reset code synchronizes the bit stream with, Either, the ACK bit, Or a 1 bit.
I am stealing this delay coding from @jeremyherbert #2493 pr. 2. Change Bus Reset to handle interrupted READ sequences. The current code does not handle interrupted READ cycles. If a SLAVE device was in a read operation when the bus was interrupted, the SLAVE device is controlling SDA. The only bit during the 9 clock cycles of a byte READ the MASTER(ESP32) is guaranteed control over, is during the ACK bit period. If the SLAVE is sending a stream of ZERO bytes, it will only release SDA during the ACK bit period. The master(ESP32) cannot generate a STOP unless SDA is HIGH. So, this reset code synchronizes the bit stream with, Either, the ACK bit, Or a 1 bit. 3. fix typo correct `sda_id` to `sda_io` in `i2c_master_clear_bus()` @ryan-ma found it. This typo was generated when I manually edited this patch on GitHub, I should have done a Copy/Paste operation!
… SDA closes #2494 closes #2493 closes #2496 1. Change bus reset to handle interrupted READ sequences. 2. Slow down I2C to 100khz during reset 3. If a SLAVE device was in a read operation when the bus was interrupted, the SLAVE device is controlling SDA.The only bit during the 9 clock cycles of a byte READ the MASTER(ESP32) is guaranteed control over, is during the ACK bit period. If the SLAVE is sending a stream of ZERO bytes, it will only release SDA during the ACK bit period. The master(ESP32) cannot generate a STOP unless SDA is HIGH. So, this reset code synchronizes the bit stream with, Either, the ACK bit, Or a 1 bit.
… SDA closes espressif/esp-idf#2494 closes espressif/esp-idf#2493 closes espressif/esp-idf#2496 1. Change bus reset to handle interrupted READ sequences. 2. Slow down I2C to 100khz during reset 3. If a SLAVE device was in a read operation when the bus was interrupted, the SLAVE device is controlling SDA.The only bit during the 9 clock cycles of a byte READ the MASTER(ESP32) is guaranteed control over, is during the ACK bit period. If the SLAVE is sending a stream of ZERO bytes, it will only release SDA during the ACK bit period. The master(ESP32) cannot generate a STOP unless SDA is HIGH. So, this reset code synchronizes the bit stream with, Either, the ACK bit, Or a 1 bit.
… SDA closes espressif/esp-idf#2494 closes espressif/esp-idf#2493 closes espressif/esp-idf#2496 1. Change bus reset to handle interrupted READ sequences. 2. Slow down I2C to 100khz during reset 3. If a SLAVE device was in a read operation when the bus was interrupted, the SLAVE device is controlling SDA.The only bit during the 9 clock cycles of a byte READ the MASTER(ESP32) is guaranteed control over, is during the ACK bit period. If the SLAVE is sending a stream of ZERO bytes, it will only release SDA during the ACK bit period. The master(ESP32) cannot generate a STOP unless SDA is HIGH. So, this reset code synchronizes the bit stream with, Either, the ACK bit, Or a 1 bit.
The I2C master reset has two major issues I have discovered:
This pull request sets the clock rate to 100kHz (the standard "slow" I2C clock rate) and releases the SDA line during the reset. At this stage, it is not possible to use the clock rate that the user has provided when configuring the I2C port, because this variable is lost when the I2C controller is reset on
i2c.c
line 582.