Skip to content

Commit 07b7d97

Browse files
tommagTom Magnier
andauthored
I2C lib : implement "bus recovery" feature on timeout reset (#2479)
* I2C lib : implement "bus recovery" feature on timeout reset --------- Co-authored-by: Tom Magnier <[email protected]>
1 parent 66c1f78 commit 07b7d97

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

libraries/Wire/src/Wire.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,33 @@ void TwoWire::_handleTimeout(bool reset) {
366366
} else {
367367
int prev_clkHz = _clkHz;
368368
end();
369+
370+
// Attempt bus recovery if SDA is held LOW by another device
371+
// See RP2040 datasheet "Bus clear feature" (not implemented in HW)
372+
int delay = 5; //5us LOW/HIGH -> 10us period -> 100kHz freq
373+
pinMode(_sda, INPUT_PULLUP);
374+
pinMode(_scl, INPUT_PULLUP);
375+
gpio_set_function(_scl, GPIO_FUNC_SIO);
376+
gpio_set_function(_sda, GPIO_FUNC_SIO);
377+
378+
if (digitalRead(_sda) == LOW) {
379+
int sclPulseCount = 0;
380+
while (sclPulseCount < 9 && digitalRead(_sda) == LOW) {
381+
sclPulseCount++;
382+
digitalWrite(_scl, LOW);
383+
sleep_us(delay);
384+
digitalWrite(_scl, HIGH);
385+
sleep_us(delay);
386+
}
387+
388+
if (digitalRead(_sda) == HIGH) {
389+
// Bus recovered : send a STOP
390+
digitalWrite(_sda, LOW);
391+
sleep_us(delay);
392+
digitalWrite(_sda, HIGH);
393+
}
394+
}
395+
369396
setClock(prev_clkHz);
370397
begin();
371398
}

0 commit comments

Comments
 (0)