Skip to content

Commit 63518a0

Browse files
committed
Double I2C read in one transaction skips a clock pulse (esp8266#5528)
See esp8266#5528 and the more elaborate [description](https://github.com/maarten-pennings/I2C-tool/blob/master/I2Ctest8266/README.md#how-to-fix) where @maarten-pennings did all the hard work, but as far as I could see, no PR was made. I also noticed some code duplication, which I moved to separate functions. According to [this documentation on I2C clock stretching](https://www.i2c-bus.org/clock-stretching/) it is not allowed to have some slave keep the clock low during transmission of a byte, only after an ack. So that's why it is not done in the while loop. But I wondered if there should be an extra delay between the sequence of pulses and the extra added clock "valley". See my comment in the code. Fixes esp8266#5528
1 parent 855b91e commit 63518a0

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

cores/esp8266/core_esp8266_si2c.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ class Twi
128128
}
129129
}
130130

131+
// Generate a clock "valley" (at the end of a segment, just before a repeated start)
132+
void twi_scl_valley(void);
131133

132134
public:
133135
void setClock(unsigned int freq);
@@ -386,13 +388,17 @@ unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned
386388
{
387389
write_stop();
388390
}
391+
else
392+
{
393+
twi_scl_valley();
394+
WAIT_CLOCK_STRETCH();
395+
// TD-er: Also busywait(twi_dcount) here?
396+
// busywait(twi_dcount);
397+
}
389398
i = 0;
390399
while (!SDA_READ() && (i++) < 10)
391400
{
392-
SCL_LOW();
393-
busywait(twi_dcount);
394-
SCL_HIGH();
395-
WAIT_CLOCK_STRETCH();
401+
twi_scl_valley();
396402
busywait(twi_dcount);
397403
}
398404
return 0;
@@ -422,13 +428,17 @@ unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned
422428
{
423429
write_stop();
424430
}
431+
else
432+
{
433+
twi_scl_valley();
434+
WAIT_CLOCK_STRETCH();
435+
// TD-er: Also busywait(twi_dcount) here?
436+
// busywait(twi_dcount);
437+
}
425438
i = 0;
426439
while (!SDA_READ() && (i++) < 10)
427440
{
428-
SCL_LOW();
429-
busywait(twi_dcount);
430-
SCL_HIGH();
431-
WAIT_CLOCK_STRETCH();
441+
twi_scl_valley();
432442
busywait(twi_dcount);
433443
}
434444
return 0;
@@ -649,6 +659,13 @@ void ICACHE_RAM_ATTR Twi::onTwipEvent(uint8_t status)
649659
}
650660
}
651661

662+
void Twi::twi_scl_valley(void)
663+
{
664+
SCL_LOW();
665+
busywait(twi_dcount);
666+
SCL_HIGH();
667+
}
668+
652669
void ICACHE_RAM_ATTR Twi::onTimer(void *unused)
653670
{
654671
(void)unused;

0 commit comments

Comments
 (0)