From aeb8e9413b138a4954ee2fa3e4259b74cb27321d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 4 Apr 2026 10:21:28 -1000 Subject: [PATCH] Clear latched MCP23xxx interrupts during setup, fix uint8_t truncation - MCP23008/MCP23S08: Read GPIO register before attaching ISR to clear any latched interrupt from a previous MCU run (chip may stay powered) - MCP23017/MCP23S17: Read both GPIOA and GPIOB to clear latched state - PI4IOE5V6408: Add explicit static_cast for ~mode_mask_ to avoid implicit int-to-uint8_t truncation --- esphome/components/mcp23008/mcp23008.cpp | 5 +++++ esphome/components/mcp23017/mcp23017.cpp | 6 ++++++ esphome/components/mcp23s08/mcp23s08.cpp | 5 +++++ esphome/components/mcp23s17/mcp23s17.cpp | 6 ++++++ esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp | 2 +- 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/esphome/components/mcp23008/mcp23008.cpp b/esphome/components/mcp23008/mcp23008.cpp index 5f73e03f6f..b7a4276c46 100644 --- a/esphome/components/mcp23008/mcp23008.cpp +++ b/esphome/components/mcp23008/mcp23008.cpp @@ -23,6 +23,11 @@ void MCP23008::setup() { this->write_reg(mcp23x08_base::MCP23X08_IOCON, iocon | IOCON_ODR); } + // Clear any latched interrupt by reading GPIO before attaching ISR + if (this->interrupt_pin_ != nullptr) { + uint8_t val; + this->read_reg(mcp23x08_base::MCP23X08_GPIO, &val); + } this->setup_interrupt_pin_(); } diff --git a/esphome/components/mcp23017/mcp23017.cpp b/esphome/components/mcp23017/mcp23017.cpp index 212c15ccf2..b1775f2402 100644 --- a/esphome/components/mcp23017/mcp23017.cpp +++ b/esphome/components/mcp23017/mcp23017.cpp @@ -33,6 +33,12 @@ void MCP23017::setup() { this->write_reg(mcp23x17_base::MCP23X17_IOCONB, iocon | iocon_flags); } + // Clear any latched interrupt by reading GPIO before attaching ISR + if (this->interrupt_pin_ != nullptr) { + uint8_t val; + this->read_reg(mcp23x17_base::MCP23X17_GPIOA, &val); + this->read_reg(mcp23x17_base::MCP23X17_GPIOB, &val); + } this->setup_interrupt_pin_(); } diff --git a/esphome/components/mcp23s08/mcp23s08.cpp b/esphome/components/mcp23s08/mcp23s08.cpp index 983c1aa600..2291381646 100644 --- a/esphome/components/mcp23s08/mcp23s08.cpp +++ b/esphome/components/mcp23s08/mcp23s08.cpp @@ -35,6 +35,11 @@ void MCP23S08::setup() { this->write_reg(mcp23x08_base::MCP23X08_IOCON, IOCON_SEQOP | IOCON_HAEN | IOCON_ODR); } + // Clear any latched interrupt by reading GPIO before attaching ISR + if (this->interrupt_pin_ != nullptr) { + uint8_t val; + this->read_reg(mcp23x08_base::MCP23X08_GPIO, &val); + } this->setup_interrupt_pin_(); } diff --git a/esphome/components/mcp23s17/mcp23s17.cpp b/esphome/components/mcp23s17/mcp23s17.cpp index db9a34e230..f27b55c6f6 100644 --- a/esphome/components/mcp23s17/mcp23s17.cpp +++ b/esphome/components/mcp23s17/mcp23s17.cpp @@ -51,6 +51,12 @@ void MCP23S17::setup() { this->write_reg(mcp23x17_base::MCP23X17_IOCONB, iocon_flags); } + // Clear any latched interrupt by reading GPIO before attaching ISR + if (this->interrupt_pin_ != nullptr) { + uint8_t val; + this->read_reg(mcp23x17_base::MCP23X17_GPIOA, &val); + this->read_reg(mcp23x17_base::MCP23X17_GPIOB, &val); + } this->setup_interrupt_pin_(); } diff --git a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp index 69de399729..610015bbe6 100644 --- a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +++ b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp @@ -162,7 +162,7 @@ bool PI4IOE5V6408Component::write_gpio_modes_() { // Enable interrupts for input pins when interrupt pin is configured // (input pins have mode_mask_ bit cleared) if (this->interrupt_pin_ != nullptr && - !this->write_byte(PI4IOE5V6408_REGISTER_INTERRUPT_ENABLE_MASK, ~this->mode_mask_)) { + !this->write_byte(PI4IOE5V6408_REGISTER_INTERRUPT_ENABLE_MASK, static_cast(~this->mode_mask_))) { this->status_set_warning(LOG_STR("Failed to write interrupt enable mask")); return false; }