Skip to content

Commit eb85c68

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.
1 parent a23864a commit eb85c68

File tree

1 file changed

+31
-9
lines changed

1 file changed

+31
-9
lines changed

cores/esp8266/core_esp8266_si2c.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ class Twi
127127
}
128128
}
129129

130-
130+
// Generate a clock "valley" (at the end of a segment, just before a repeated start)
131+
void twi_scl_valley(void);
131132
public:
132133
void setClock(unsigned int freq);
133134
void setClockStretchLimit(uint32_t limit);
@@ -383,14 +384,18 @@ unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned
383384
if (sendStop)
384385
{
385386
write_stop();
387+
}
388+
else
389+
{
390+
twi_scl_valley();
391+
twi_wait_clockStretchLimit();
392+
// TD-er: Also twi_delay here?
393+
// delay(twi_dcount);
386394
}
387395
i = 0;
388396
while (!SDA_READ() && (i++) < 10)
389397
{
390-
SCL_LOW();
391-
busywait(twi_dcount);
392-
SCL_HIGH();
393-
WAIT_CLOCK_STRETCH();
398+
twi_scl_valley();
394399
busywait(twi_dcount);
395400
}
396401
return 0;
@@ -420,13 +425,17 @@ unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned
420425
{
421426
write_stop();
422427
}
428+
else
429+
{
430+
twi_scl_valley();
431+
twi_wait_clockStretchLimit();
432+
// TD-er: Also twi_delay here?
433+
// delay(twi_dcount);
434+
}
423435
i = 0;
424436
while (!SDA_READ() && (i++) < 10)
425437
{
426-
SCL_LOW();
427-
busywait(twi_dcount);
428-
SCL_HIGH();
429-
WAIT_CLOCK_STRETCH();
438+
twi_scl_valley();
430439
busywait(twi_dcount);
431440
}
432441
return 0;
@@ -647,6 +656,19 @@ void ICACHE_RAM_ATTR Twi::onTwipEvent(uint8_t status)
647656
}
648657
}
649658

659+
void ICACHE_RAM_ATTR Twi::twi_wait_clockStretchLimit(void)
660+
{
661+
uint32_t t=0;
662+
while(SCL_READ() == 0 && (t++) < twi_clockStretchLimit); // Clock stretching
663+
}
664+
665+
void Twi::twi_scl_valley(void)
666+
{
667+
SCL_LOW();
668+
busywait(twi_dcount);
669+
SCL_HIGH();
670+
}
671+
650672
void ICACHE_RAM_ATTR Twi::onTimer(void *unused)
651673
{
652674
(void)unused;

0 commit comments

Comments
 (0)