Skip to content

Commit 1c63358

Browse files
committed
Double I2C read in one transaction skips a clock pulse (#5528)
See #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 1c14e9e commit 1c63358

File tree

1 file changed

+38
-14
lines changed

1 file changed

+38
-14
lines changed

cores/esp8266/core_esp8266_si2c.cpp

+38-14
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ class Twi
113113
return (GPI & (1 << twi_scl)) != 0;
114114
}
115115

116+
// ICACHE_RAM_ATTR used to have a constant delay.
117+
void ICACHE_RAM_ATTR twi_wait_clockStretchLimit(void);
118+
119+
// Generate a clock "valley" (at the end of a segment, just before a repeated start)
120+
void twi_scl_valley(void);
121+
116122
public:
117123
void setClock(unsigned int freq);
118124
void setClockStretchLimit(uint32_t limit);
@@ -268,12 +274,11 @@ bool Twi::write_start(void)
268274

269275
bool Twi::write_stop(void)
270276
{
271-
uint32_t i = 0;
272277
SCL_LOW();
273278
SDA_LOW();
274279
delay(twi_dcount);
275280
SCL_HIGH();
276-
while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit); // Clock stretching
281+
twi_wait_clockStretchLimit();
277282
delay(twi_dcount);
278283
SDA_HIGH();
279284
delay(twi_dcount);
@@ -282,7 +287,6 @@ bool Twi::write_stop(void)
282287

283288
bool Twi::write_bit(bool bit)
284289
{
285-
uint32_t i = 0;
286290
SCL_LOW();
287291
if (bit)
288292
{
@@ -294,19 +298,18 @@ bool Twi::write_bit(bool bit)
294298
}
295299
delay(twi_dcount + 1);
296300
SCL_HIGH();
297-
while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching
301+
twi_wait_clockStretchLimit();
298302
delay(twi_dcount);
299303
return true;
300304
}
301305

302306
bool Twi::read_bit(void)
303307
{
304-
uint32_t i = 0;
305308
SCL_LOW();
306309
SDA_HIGH();
307310
delay(twi_dcount + 2);
308311
SCL_HIGH();
309-
while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching
312+
twi_wait_clockStretchLimit();
310313
bool bit = SDA_READ();
311314
delay(twi_dcount);
312315
return bit;
@@ -364,14 +367,18 @@ unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned
364367
if (sendStop)
365368
{
366369
write_stop();
370+
}
371+
else
372+
{
373+
twi_scl_valley();
374+
twi_wait_clockStretchLimit();
375+
// TD-er: Also twi_delay here?
376+
// delay(twi_dcount);
367377
}
368378
i = 0;
369379
while (SDA_READ() == 0 && (i++) < 10)
370380
{
371-
SCL_LOW();
372-
delay(twi_dcount);
373-
SCL_HIGH();
374-
unsigned int t = 0; while (SCL_READ() == 0 && (t++) < twi_clockStretchLimit); // twi_clockStretchLimit
381+
twi_scl_valley();
375382
delay(twi_dcount);
376383
}
377384
return 0;
@@ -401,13 +408,17 @@ unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned
401408
{
402409
write_stop();
403410
}
411+
else
412+
{
413+
twi_scl_valley();
414+
twi_wait_clockStretchLimit();
415+
// TD-er: Also twi_delay here?
416+
// delay(twi_dcount);
417+
}
404418
i = 0;
405419
while (SDA_READ() == 0 && (i++) < 10)
406420
{
407-
SCL_LOW();
408-
delay(twi_dcount);
409-
SCL_HIGH();
410-
unsigned int t = 0; while (SCL_READ() == 0 && (t++) < twi_clockStretchLimit); // twi_clockStretchLimit
421+
twi_scl_valley();
411422
delay(twi_dcount);
412423
}
413424
return 0;
@@ -628,6 +639,19 @@ void ICACHE_RAM_ATTR Twi::onTwipEvent(uint8_t status)
628639
}
629640
}
630641

642+
void ICACHE_RAM_ATTR Twi::twi_wait_clockStretchLimit(void)
643+
{
644+
uint32_t t=0;
645+
while(SCL_READ() == 0 && (t++) < twi_clockStretchLimit); // Clock stretching
646+
}
647+
648+
void Twi::twi_scl_valley(void)
649+
{
650+
SCL_LOW();
651+
delay(twi_dcount);
652+
SCL_HIGH();
653+
}
654+
631655
void ICACHE_RAM_ATTR Twi::onTimer(void *unused)
632656
{
633657
(void)unused;

0 commit comments

Comments
 (0)