22
22
#include " twi.h"
23
23
#include " pins_arduino.h"
24
24
#include " wiring_private.h"
25
+ #include " PolledTimeout.h"
25
26
26
27
27
28
@@ -122,9 +123,12 @@ class Twi
122
123
// Handle the case where a slave needs to stretch the clock with a time-limited busy wait
123
124
inline void WAIT_CLOCK_STRETCH ()
124
125
{
125
- for (unsigned int t = 0 ; !SCL_READ () && (t < twi_clockStretchLimit); t++)
126
- {
127
- /* noop */
126
+ esp8266::polledTimeout::oneShotFastUs timeout (twi_clockStretchLimit);
127
+ esp8266::polledTimeout::periodicFastUs yieldTimeout (5000 );
128
+ while (!timeout && !SCL_READ ()) // outer loop is stretch duration up to stretch limit
129
+ {
130
+ if (yieldTimeout) // inner loop yields every 5ms
131
+ yield ();
128
132
}
129
133
}
130
134
@@ -245,7 +249,7 @@ void Twi::init(unsigned char sda, unsigned char scl)
245
249
pinMode (twi_sda, INPUT_PULLUP);
246
250
pinMode (twi_scl, INPUT_PULLUP);
247
251
twi_setClock (preferred_si2c_clock);
248
- twi_setClockStretchLimit (230 ); // default value is 230 uS
252
+ twi_setClockStretchLimit (150000L ); // default value is 150 mS
249
253
}
250
254
251
255
void Twi::setAddress (uint8_t address)
@@ -444,6 +448,7 @@ unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned
444
448
445
449
uint8_t Twi::status ()
446
450
{
451
+ WAIT_CLOCK_STRETCH (); // wait for a slow slave to finish
447
452
if (!SCL_READ ())
448
453
{
449
454
return I2C_SCL_HELD_LOW; // SCL held low by another device, no procedure available to recover
@@ -463,11 +468,6 @@ uint8_t Twi::status()
463
468
return I2C_SDA_HELD_LOW; // I2C bus error. SDA line held low by slave/another_master after n bits.
464
469
}
465
470
466
- if (!write_start ())
467
- {
468
- return I2C_SDA_HELD_LOW_AFTER_INIT; // line busy. SDA again held low by another device. 2nd master?
469
- }
470
-
471
471
return I2C_OK;
472
472
}
473
473
0 commit comments