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 "i2c_bus_arduino.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "esphome/core/helpers.h" #include "esphome/core/helpers.h"
#include "esphome/core/application.h"
#include <Arduino.h> #include <Arduino.h>
#include <cstring> #include <cstring>
@ -227,10 +228,14 @@ void ArduinoI2CBus::recover_() {
// When SCL is kept LOW at this point, we might be looking at a device // 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, // that applies clock stretching. Wait for the release of the SCL line,
// but not forever. There is no specification for the maximum allowed // but not forever. There is no specification for the maximum allowed
// time. We'll stick to 500ms here. // time. We yield and reset the WDT, so as to avoid triggering reset.
auto wait = 20; // 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 while (wait-- && digitalRead(scl_pin_) == LOW) { // NOLINT
delay(25); App.feed_wdt();
delayMicroseconds(half_period_usec * 2);
} }
if (digitalRead(scl_pin_) == LOW) { // NOLINT if (digitalRead(scl_pin_) == LOW) { // NOLINT
ESP_LOGE(TAG, "Recovery failed: SCL is held LOW during clock pulse cycle"); 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/hal.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "esphome/core/helpers.h" #include "esphome/core/helpers.h"
#include "esphome/core/application.h"
#include <cstring> #include <cstring>
#include <cinttypes> #include <cinttypes>
@ -273,10 +274,14 @@ void IDFI2CBus::recover_() {
// When SCL is kept LOW at this point, we might be looking at a device // 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, // that applies clock stretching. Wait for the release of the SCL line,
// but not forever. There is no specification for the maximum allowed // but not forever. There is no specification for the maximum allowed
// time. We'll stick to 500ms here. // time. We yield and reset the WDT, so as to avoid triggering reset.
auto wait = 20; // 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) { 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) { if (gpio_get_level(scl_pin) == 0) {
ESP_LOGE(TAG, "Recovery failed: SCL is held LOW during clock pulse cycle"); ESP_LOGE(TAG, "Recovery failed: SCL is held LOW during clock pulse cycle");