From 155657f1ccda9d6529ce07a4ffb41996e3641f7a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 5 Apr 2026 13:26:55 -1000 Subject: [PATCH] [mcp23xxx][pi4ioe5v6408] Disable loop when all pins are outputs (#15460) --- esphome/components/mcp23x08_base/mcp23x08_base.cpp | 5 +++++ esphome/components/mcp23x17_base/mcp23x17_base.cpp | 5 +++++ esphome/components/mcp23xxx_base/mcp23xxx_base.h | 5 ++++- esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp | 10 +++++++++- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/esphome/components/mcp23x08_base/mcp23x08_base.cpp b/esphome/components/mcp23x08_base/mcp23x08_base.cpp index e4f4d50aae..197b739204 100644 --- a/esphome/components/mcp23x08_base/mcp23x08_base.cpp +++ b/esphome/components/mcp23x08_base/mcp23x08_base.cpp @@ -37,6 +37,11 @@ void MCP23X08Base::pin_mode(uint8_t pin, gpio::Flags flags) { if (this->interrupt_pin_ != nullptr && (flags & gpio::FLAG_INPUT)) { this->pin_interrupt_mode(pin, mcp23xxx_base::MCP23XXX_CHANGE); } + // Enable polling loop for input pins (not needed for interrupt-driven mode + // where the ISR handles re-enabling loop) + if (this->interrupt_pin_ == nullptr && (flags & gpio::FLAG_INPUT)) { + this->enable_loop(); + } } void MCP23X08Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) { diff --git a/esphome/components/mcp23x17_base/mcp23x17_base.cpp b/esphome/components/mcp23x17_base/mcp23x17_base.cpp index 42613053de..efed7f5f17 100644 --- a/esphome/components/mcp23x17_base/mcp23x17_base.cpp +++ b/esphome/components/mcp23x17_base/mcp23x17_base.cpp @@ -49,6 +49,11 @@ void MCP23X17Base::pin_mode(uint8_t pin, gpio::Flags flags) { if (this->interrupt_pin_ != nullptr && (flags & gpio::FLAG_INPUT)) { this->pin_interrupt_mode(pin, mcp23xxx_base::MCP23XXX_CHANGE); } + // Enable polling loop for input pins (not needed for interrupt-driven mode + // where the ISR handles re-enabling loop) + if (this->interrupt_pin_ == nullptr && (flags & gpio::FLAG_INPUT)) { + this->enable_loop(); + } } void MCP23X17Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) { diff --git a/esphome/components/mcp23xxx_base/mcp23xxx_base.h b/esphome/components/mcp23xxx_base/mcp23xxx_base.h index e77eac87e7..6efd04e246 100644 --- a/esphome/components/mcp23xxx_base/mcp23xxx_base.h +++ b/esphome/components/mcp23xxx_base/mcp23xxx_base.h @@ -35,8 +35,11 @@ template class MCP23XXXBase : public Component, public gpio_expander: this->interrupt_pin_->setup(); this->interrupt_pin_->attach_interrupt(&MCP23XXXBase::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); this->set_invalidate_on_read_(false); - this->disable_loop(); } + // Disable loop until an input pin is configured via pin_mode() + // For interrupt-driven mode, loop is re-enabled by the ISR + // For polling mode, loop is re-enabled when pin_mode() registers an input pin + this->disable_loop(); } static void IRAM_ATTR gpio_intr(MCP23XXXBase *arg) { arg->enable_loop_soon_any_context(); } diff --git a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp index 8e38e7fa1d..6e8631022a 100644 --- a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +++ b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp @@ -41,8 +41,11 @@ void PI4IOE5V6408Component::setup() { this->interrupt_pin_->setup(); this->interrupt_pin_->attach_interrupt(&PI4IOE5V6408Component::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); this->set_invalidate_on_read_(false); - this->disable_loop(); } + // Disable loop until an input pin is configured via pin_mode() + // For interrupt-driven mode, loop is re-enabled by the ISR + // For polling mode, loop is re-enabled when pin_mode() registers an input pin + this->disable_loop(); } void IRAM_ATTR PI4IOE5V6408Component::gpio_intr(PI4IOE5V6408Component *arg) { arg->enable_loop_soon_any_context(); } void PI4IOE5V6408Component::dump_config() { @@ -67,6 +70,11 @@ void PI4IOE5V6408Component::pin_mode(uint8_t pin, gpio::Flags flags) { this->pull_up_down_mask_ &= ~(1 << pin); this->pull_enable_mask_ |= 1 << pin; } + // Enable polling loop for input pins (not needed for interrupt-driven mode + // where the ISR handles re-enabling loop) + if (this->interrupt_pin_ == nullptr) { + this->enable_loop(); + } } // Write GPIO to enable input mode this->write_gpio_modes_();