diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 0ce1117262..5cae67db13 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -48,7 +48,7 @@ from esphome.coroutine import CoroPriority, coroutine_with_priority import esphome.final_validate as fv from esphome.helpers import copy_file_if_changed, rmtree, write_file_if_changed from esphome.types import ConfigType -from esphome.writer import clean_cmake_cache +from esphome.writer import clean_build, clean_cmake_cache from .boards import BOARDS, STANDARD_BOARDS from .const import ( # noqa @@ -2195,6 +2195,7 @@ def _write_sdkconfig(): if write_file_if_changed(internal_path, contents): # internal changed, update real one write_file_if_changed(sdk_path, contents) + clean_build(clear_pio_cache=False) def _write_idf_component_yml(): diff --git a/esphome/components/gpio_expander/cached_gpio.h b/esphome/components/gpio_expander/cached_gpio.h index eeff98cb6e..782efe0f2d 100644 --- a/esphome/components/gpio_expander/cached_gpio.h +++ b/esphome/components/gpio_expander/cached_gpio.h @@ -5,6 +5,7 @@ #include #include #include +#include "esphome/core/application.h" #include "esphome/core/hal.h" namespace esphome::gpio_expander { @@ -32,6 +33,15 @@ class CachedGpioExpander { /// @param pin Pin number to read /// @return Pin state bool digital_read(P pin) { + // Invalidate cache once per loop iteration so we always get a fresh + // hardware read on the first access each loop, while still caching + // within the same iteration for other pins in the same bank. + const uint32_t now = App.get_loop_component_start_time(); + if (now != this->last_loop_time_) { + this->last_loop_time_ = now; + this->reset_pin_cache_(); + } + const P bank = pin / BANK_SIZE; const T pin_mask = (1 << (pin % BANK_SIZE)); // Check if specific pin cache is valid @@ -68,7 +78,7 @@ class CachedGpioExpander { /// @param value Pin state to write (true = HIGH, false = LOW) virtual void digital_write_hw(P pin, bool value) = 0; - /// @brief Invalidate cache. This function should be called in component loop(). + /// @brief Invalidate all cached pin states, forcing the next digital_read() to read from hardware. void reset_pin_cache_() { memset(this->read_cache_valid_, 0x00, CACHE_SIZE_BYTES); } static constexpr uint16_t BITS_PER_BYTE = 8; @@ -76,6 +86,7 @@ class CachedGpioExpander { static constexpr size_t BANKS = N / BANK_SIZE; static constexpr size_t CACHE_SIZE_BYTES = BANKS * sizeof(T); + uint32_t last_loop_time_{0}; T read_cache_valid_[BANKS]{0}; }; diff --git a/esphome/components/mcp23016/mcp23016.cpp b/esphome/components/mcp23016/mcp23016.cpp index fbdb6903b8..1a7507f7ab 100644 --- a/esphome/components/mcp23016/mcp23016.cpp +++ b/esphome/components/mcp23016/mcp23016.cpp @@ -26,10 +26,6 @@ void MCP23016::setup() { this->write_reg_(MCP23016_IODIR1, 0xFFFF); } -void MCP23016::loop() { - // Invalidate cache at the start of each loop - this->reset_pin_cache_(); -} bool MCP23016::digital_read_hw(uint8_t pin) { return this->read_reg_(MCP23016_GP1, &this->input_mask_); } bool MCP23016::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); } diff --git a/esphome/components/mcp23016/mcp23016.h b/esphome/components/mcp23016/mcp23016.h index 494bc9c197..4ab9a81597 100644 --- a/esphome/components/mcp23016/mcp23016.h +++ b/esphome/components/mcp23016/mcp23016.h @@ -30,7 +30,6 @@ class MCP23016 : public Component, public i2c::I2CDevice, public gpio_expander:: MCP23016() = default; void setup() override; - void loop() override; void pin_mode(uint8_t pin, gpio::Flags flags); float get_setup_priority() const override; diff --git a/esphome/components/mcp23xxx_base/mcp23xxx_base.h b/esphome/components/mcp23xxx_base/mcp23xxx_base.h index fb992466d5..955f581744 100644 --- a/esphome/components/mcp23xxx_base/mcp23xxx_base.h +++ b/esphome/components/mcp23xxx_base/mcp23xxx_base.h @@ -17,8 +17,6 @@ template class MCP23XXXBase : public Component, public gpio_expander: void set_open_drain_ints(const bool value) { this->open_drain_ints_ = value; } float get_setup_priority() const override { return setup_priority::IO; } - void loop() override { this->reset_pin_cache_(); } - protected: // read a given register virtual bool read_reg(uint8_t reg, uint8_t *value) = 0; diff --git a/esphome/components/pca6416a/pca6416a.cpp b/esphome/components/pca6416a/pca6416a.cpp index f393af88ce..66d4e1782d 100644 --- a/esphome/components/pca6416a/pca6416a.cpp +++ b/esphome/components/pca6416a/pca6416a.cpp @@ -51,11 +51,6 @@ void PCA6416AComponent::setup() { this->status_has_error()); } -void PCA6416AComponent::loop() { - // Invalidate cache at the start of each loop - this->reset_pin_cache_(); -} - void PCA6416AComponent::dump_config() { if (this->has_pullup_) { ESP_LOGCONFIG(TAG, "PCAL6416A:"); diff --git a/esphome/components/pca6416a/pca6416a.h b/esphome/components/pca6416a/pca6416a.h index 138a51cc20..a60d65271d 100644 --- a/esphome/components/pca6416a/pca6416a.h +++ b/esphome/components/pca6416a/pca6416a.h @@ -16,7 +16,6 @@ class PCA6416AComponent : public Component, /// Check i2c availability and setup masks void setup() override; - void loop() override; /// Helper function to set the pin mode of a pin. void pin_mode(uint8_t pin, gpio::Flags flags); diff --git a/esphome/components/pca9554/pca9554.cpp b/esphome/components/pca9554/pca9554.cpp index adc7bc0fb5..ceb264472b 100644 --- a/esphome/components/pca9554/pca9554.cpp +++ b/esphome/components/pca9554/pca9554.cpp @@ -36,12 +36,6 @@ void PCA9554Component::setup() { this->status_has_error()); } -void PCA9554Component::loop() { - // Invalidate the cache at the start of each loop. - // The actual read will happen on demand when digital_read() is called - this->reset_pin_cache_(); -} - void PCA9554Component::dump_config() { ESP_LOGCONFIG(TAG, "PCA9554:\n" diff --git a/esphome/components/pca9554/pca9554.h b/esphome/components/pca9554/pca9554.h index 1d877f9ce2..799cbfede7 100644 --- a/esphome/components/pca9554/pca9554.h +++ b/esphome/components/pca9554/pca9554.h @@ -16,8 +16,6 @@ class PCA9554Component : public Component, /// Check i2c availability and setup masks void setup() override; - /// Invalidate cache at start of each loop - void loop() override; /// Helper function to set the pin mode of a pin. void pin_mode(uint8_t pin, gpio::Flags flags); diff --git a/esphome/components/pcf8574/pcf8574.cpp b/esphome/components/pcf8574/pcf8574.cpp index d3ec31436d..55afeba4f6 100644 --- a/esphome/components/pcf8574/pcf8574.cpp +++ b/esphome/components/pcf8574/pcf8574.cpp @@ -16,10 +16,6 @@ void PCF8574Component::setup() { this->write_gpio_(); this->read_gpio_(); } -void PCF8574Component::loop() { - // Invalidate the cache at the start of each loop - this->reset_pin_cache_(); -} void PCF8574Component::dump_config() { ESP_LOGCONFIG(TAG, "PCF8574:\n" diff --git a/esphome/components/pcf8574/pcf8574.h b/esphome/components/pcf8574/pcf8574.h index b039173789..861fc1014c 100644 --- a/esphome/components/pcf8574/pcf8574.h +++ b/esphome/components/pcf8574/pcf8574.h @@ -20,8 +20,6 @@ class PCF8574Component : public Component, /// Check i2c availability and setup masks void setup() override; - /// Invalidate cache at start of each loop - void loop() override; /// Helper function to set the pin mode of a pin. void pin_mode(uint8_t pin, gpio::Flags flags); diff --git a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp index 9247e114f0..11053df6e2 100644 --- a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +++ b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp @@ -60,8 +60,6 @@ void PI4IOE5V6408Component::pin_mode(uint8_t pin, gpio::Flags flags) { this->write_gpio_modes_(); } -void PI4IOE5V6408Component::loop() { this->reset_pin_cache_(); } - bool PI4IOE5V6408Component::read_gpio_outputs_() { if (this->is_failed()) return false; diff --git a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.h b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.h index 4dc31201ce..b069167423 100644 --- a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.h +++ b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.h @@ -18,7 +18,6 @@ class PI4IOE5V6408Component : public Component, float get_setup_priority() const override; void dump_config() override; - void loop() override; /// Indicate if the component should reset the state during setup void set_reset(bool reset) { this->reset_ = reset; } diff --git a/esphome/components/sx1509/sx1509.cpp b/esphome/components/sx1509/sx1509.cpp index 1cdae76eaf..e7238f0fa1 100644 --- a/esphome/components/sx1509/sx1509.cpp +++ b/esphome/components/sx1509/sx1509.cpp @@ -39,9 +39,6 @@ void SX1509Component::dump_config() { } void SX1509Component::loop() { - // Reset cache at the start of each loop - this->reset_pin_cache_(); - if (this->has_keypad_) { if (millis() - this->last_loop_timestamp_ < min_loop_period_) return; diff --git a/esphome/components/tca9555/tca9555.cpp b/esphome/components/tca9555/tca9555.cpp index 79c5253898..fba92d92bb 100644 --- a/esphome/components/tca9555/tca9555.cpp +++ b/esphome/components/tca9555/tca9555.cpp @@ -43,8 +43,6 @@ void TCA9555Component::pin_mode(uint8_t pin, gpio::Flags flags) { // Write GPIO to enable input mode this->write_gpio_modes_(); } -void TCA9555Component::loop() { this->reset_pin_cache_(); } - bool TCA9555Component::read_gpio_outputs_() { if (this->is_failed()) return false; diff --git a/esphome/components/tca9555/tca9555.h b/esphome/components/tca9555/tca9555.h index 9f7273b1e7..47a1e3702c 100644 --- a/esphome/components/tca9555/tca9555.h +++ b/esphome/components/tca9555/tca9555.h @@ -22,8 +22,6 @@ class TCA9555Component : public Component, void dump_config() override; - void loop() override; - protected: bool digital_read_hw(uint8_t pin) override; bool digital_read_cache(uint8_t pin) override;