kanflo / esp-open-rtos-driver-i2c

I2C driver for esp-open-rtos
MIT License
12 stars 3 forks source link

[Enhancement] -- Provide "bus reset" functionality #4

Open jeffsf opened 6 years ago

jeffsf commented 6 years ago

Regrettably, I2C devices can hang the bus.

At least as I understand it, the master can "force a reset" by clocking at least 9 times.

I first found out about this "35 year old 'well known secret'" at https://community.nxp.com/thread/316813 (TomE post on Feb 28, 2017):

http://www.nxp.com/documents/user_manual/UM10204.pdf

If you read section "3.1.16 Bus Clear" it tells you to assert the "Reset Pins" of all the I2C devices. The whole point of I2C is to minimise the number of bus pins, so almost no devices have Reset pins. But then it gives the advice that "everybody knows", which is:

If the data line (SDA) is stuck LOW, the master should send nine clock pulses. The device that held the bus LOW should release it sometime within those nine clocks.

Another reference that seems clear and reputable is http://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686_0.pdf

The method is quite simple. It is the master’s job to recover the bus and restore control to the main program. When the master detects the SDA line stuck in the low state, it merely needs to send some additional clocks and generate a STOP condition. How many clocks will be needed? The number will vary with the number of bits that remain to be sent by the slave. The maximum would be 9. This number is derived from the worst-case scenario, the case where the processor was reset just after sending an ACK to the slave. Now the slave is ready to send 8 data bits and receive 1 ACK (or NAK in the case of a bus recovery).

The procedure is as follows: 1) Master tries to assert a Logic 1 on the SDA line 2) Master still sees a Logic 0 and then generates a clock pulse on SCL (1-0-1 transition) 3) Master examines SDA. If SDA = 0, go to Step 2; if SDA = 1, go to Step 4 4) Generate a STOP condition

At least for me, I'm not sure that the complication of checking to see if SDA has gone high is "required" to save a couple of ~100 kHz clock cycles. I certainly don't expect the code to determine if the bus is hung! I'd be happy with i2c_bus_reset() or the like.

kanflo commented 6 years ago

Thanks for the tidbit. This driver was merged into ESP Open RTOS a few years ago and has seen much improvement over there. Feel free to move this enhancement to EOR as it attracts much more traffic.