I2c scan recovery reset fix (#4724)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
gcopeland 2023-04-26 15:00:37 -05:00 committed by Jesse Hills
parent 0f1e186189
commit e14ce3d950
No known key found for this signature in database
GPG key ID: BEAAE804EFD8E83A
2 changed files with 16 additions and 6 deletions

View file

@ -3,6 +3,7 @@
#include "i2c_bus_arduino.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
#include "esphome/core/application.h"
#include <Arduino.h>
#include <cstring>
@ -227,10 +228,14 @@ void ArduinoI2CBus::recover_() {
// When SCL is kept LOW at this point, we might be looking at a device
// that applies clock stretching. Wait for the release of the SCL line,
// but not forever. There is no specification for the maximum allowed
// time. We'll stick to 500ms here.
auto wait = 20;
// time. We yield and reset the WDT, so as to avoid triggering reset.
// No point in trying to recover the bus by forcing a uC reset. Bus
// should recover in a few ms or less else not likely to recovery at
// all.
auto wait = 250;
while (wait-- && digitalRead(scl_pin_) == LOW) { // NOLINT
delay(25);
App.feed_wdt();
delayMicroseconds(half_period_usec * 2);
}
if (digitalRead(scl_pin_) == LOW) { // NOLINT
ESP_LOGE(TAG, "Recovery failed: SCL is held LOW during clock pulse cycle");

View file

@ -4,6 +4,7 @@
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
#include "esphome/core/application.h"
#include <cstring>
#include <cinttypes>
@ -273,10 +274,14 @@ void IDFI2CBus::recover_() {
// When SCL is kept LOW at this point, we might be looking at a device
// that applies clock stretching. Wait for the release of the SCL line,
// but not forever. There is no specification for the maximum allowed
// time. We'll stick to 500ms here.
auto wait = 20;
// time. We yield and reset the WDT, so as to avoid triggering reset.
// No point in trying to recover the bus by forcing a uC reset. Bus
// should recover in a few ms or less else not likely to recovery at
// all.
auto wait = 250;
while (wait-- && gpio_get_level(scl_pin) == 0) {
delay(25);
App.feed_wdt();
delayMicroseconds(half_period_usec * 2);
}
if (gpio_get_level(scl_pin) == 0) {
ESP_LOGE(TAG, "Recovery failed: SCL is held LOW during clock pulse cycle");