diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 777c846371..767da3f33e 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -5eb1e5852765114ad06533220d3160b6c23f5ccefc4de41828699de5dfff5ad6 +b97e16a84153b2a4cfc51137cd6121db3c32374504b2bea55144413b3e573052 diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 3a1ea16fa3..23f12e651f 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -91,18 +91,18 @@ def _parse_platform_version(value): # The default/recommended arduino framework version # - https://github.com/earlephilhower/arduino-pico/releases # - https://api.registry.platformio.org/v3/packages/earlephilhower/tool/framework-arduinopico -RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 9, 4) +RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(5, 5, 0) # The raspberrypi platform version to use for arduino frameworks # - https://github.com/maxgerhardt/platform-raspberrypi/tags -RECOMMENDED_ARDUINO_PLATFORM_VERSION = "v1.2.0-gcc12" +RECOMMENDED_ARDUINO_PLATFORM_VERSION = "v1.4.0-gcc14-arduinopico460" def _arduino_check_versions(value): value = value.copy() lookups = { - "dev": (cv.Version(3, 9, 4), "https://github.com/earlephilhower/arduino-pico"), - "latest": (cv.Version(3, 9, 4), None), + "dev": (cv.Version(5, 5, 0), "https://github.com/earlephilhower/arduino-pico"), + "latest": (cv.Version(5, 5, 0), None), "recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None), } diff --git a/esphome/components/rp2040/gpio.cpp b/esphome/components/rp2040/gpio.cpp index 2b1699f888..4b3c98104c 100644 --- a/esphome/components/rp2040/gpio.cpp +++ b/esphome/components/rp2040/gpio.cpp @@ -106,7 +106,7 @@ void IRAM_ATTR ISRInternalGPIOPin::pin_mode(gpio::Flags flags) { sio_hw->gpio_oe_set = arg->mask; } else if (flags & gpio::FLAG_INPUT) { sio_hw->gpio_oe_clr = arg->mask; - hw_write_masked(&padsbank0_hw->io[arg->pin], + hw_write_masked(&pads_bank0_hw->io[arg->pin], (bool_to_bit(flags & gpio::FLAG_PULLUP) << PADS_BANK0_GPIO0_PUE_LSB) | (bool_to_bit(flags & gpio::FLAG_PULLDOWN) << PADS_BANK0_GPIO0_PDE_LSB), PADS_BANK0_GPIO0_PUE_BITS | PADS_BANK0_GPIO0_PDE_BITS); diff --git a/esphome/components/uart/uart_component_rp2040.cpp b/esphome/components/uart/uart_component_rp2040.cpp index 0c6834055c..faf8f4d90f 100644 --- a/esphome/components/uart/uart_component_rp2040.cpp +++ b/esphome/components/uart/uart_component_rp2040.cpp @@ -115,8 +115,8 @@ void RP2040UartComponent::setup() { if (tx_hw == -1 || rx_hw == -1 || tx_hw != rx_hw) { ESP_LOGV(TAG, "Using SerialPIO"); - pin_size_t tx = this->tx_pin_ == nullptr ? SerialPIO::NOPIN : this->tx_pin_->get_pin(); - pin_size_t rx = this->rx_pin_ == nullptr ? SerialPIO::NOPIN : this->rx_pin_->get_pin(); + pin_size_t tx = this->tx_pin_ == nullptr ? NOPIN : this->tx_pin_->get_pin(); + pin_size_t rx = this->rx_pin_ == nullptr ? NOPIN : this->rx_pin_->get_pin(); auto *serial = new SerialPIO(tx, rx, this->rx_buffer_size_); // NOLINT(cppcoreguidelines-owning-memory) serial->begin(this->baud_rate_, config); if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted()) diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 1baf21e2b2..7200325d1b 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -24,11 +24,8 @@ static bool s_sta_had_ip = false; // NOLINT(cppcoreguidelines-avoid-non- static size_t s_scan_result_count = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) bool WiFiComponent::wifi_mode_(optional sta, optional ap) { - if (sta.has_value()) { - if (sta.value()) { - cyw43_wifi_set_up(&cyw43_state, CYW43_ITF_STA, true, CYW43_COUNTRY_WORLDWIDE); - } - } + // STA mode is enabled by WiFi.beginNoBlock() via cyw43_arch_enable_sta_mode(), + // so we don't need to call cyw43_wifi_set_up() directly for STA. bool ap_state = false; if (ap.has_value()) { @@ -78,8 +75,13 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { return false; #endif - auto ret = WiFi.begin(ap.ssid_.c_str(), ap.password_.c_str()); - if (ret != WL_CONNECTED) + // Use beginNoBlock to avoid WiFi.begin()'s additional 2x timeout wait loop on top of + // CYW43::begin()'s internal blocking join. CYW43::begin() blocks for up to 10 seconds + // (default timeout) to complete the join - this is required because the LwipIntfDev netif + // setup depends on begin() succeeding. beginNoBlock() skips the outer wait loop, saving + // up to 20 additional seconds of blocking per attempt. + auto ret = WiFi.beginNoBlock(ap.ssid_.c_str(), ap.password_.c_str()); + if (ret == WL_IDLE_STATUS) return false; return true; @@ -116,13 +118,19 @@ const char *get_disconnect_reason_str(uint8_t reason) { } WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { - int status = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA); + // Use cyw43_wifi_link_status instead of cyw43_tcpip_link_status because the Arduino + // framework's __wrap_cyw43_cb_tcpip_init is a no-op — the SDK's internal netif + // (cyw43_state.netif[]) is never initialized. cyw43_tcpip_link_status checks that netif's + // flags and would only fall through to cyw43_wifi_link_status when the flags aren't set. + // Using cyw43_wifi_link_status directly gives us the actual WiFi radio join state. + int status = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); switch (status) { case CYW43_LINK_JOIN: - case CYW43_LINK_NOIP: + // WiFi joined, check if we have an IP address via the Arduino framework's WiFi class + if (WiFi.status() == WL_CONNECTED) { + return WiFiSTAConnectStatus::CONNECTED; + } return WiFiSTAConnectStatus::CONNECTING; - case CYW43_LINK_UP: - return WiFiSTAConnectStatus::CONNECTED; case CYW43_LINK_FAIL: case CYW43_LINK_BADAUTH: return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED; @@ -167,7 +175,6 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { ESP_LOGV(TAG, "cyw43_wifi_scan failed"); } return err == 0; - return true; } #ifdef USE_WIFI_AP @@ -212,8 +219,10 @@ network::IPAddress WiFiComponent::wifi_soft_ap_ip() { return {(const ip_addr_t * #endif // USE_WIFI_AP bool WiFiComponent::wifi_disconnect_() { - int err = cyw43_wifi_leave(&cyw43_state, CYW43_ITF_STA); - return err == 0; + // Use Arduino WiFi.disconnect() instead of raw cyw43_wifi_leave() to properly + // clean up the lwIP netif, DHCP client, and internal Arduino state. + WiFi.disconnect(); + return true; } bssid_t WiFiComponent::wifi_bssid() { @@ -269,9 +278,10 @@ void WiFiComponent::wifi_loop_() { // Poll for connection state changes // The arduino-pico WiFi library doesn't have event callbacks like ESP8266/ESP32, - // so we need to poll the link status to detect state changes - auto status = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA); - bool is_connected = (status == CYW43_LINK_UP); + // so we need to poll the link status to detect state changes. + // Use WiFi.connected() which checks both the WiFi link and IP address via the + // Arduino framework's own netif (not the SDK's uninitialized one). + bool is_connected = WiFi.connected(); // Detect connection state change if (is_connected && !s_sta_was_connected) { diff --git a/platformio.ini b/platformio.ini index e35dce2228..16a1b18211 100644 --- a/platformio.ini +++ b/platformio.ini @@ -193,10 +193,10 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script extends = common:arduino board_build.filesystem_size = 0.5m -platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.2.0-gcc12 +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.4.0-gcc14-arduinopico460 platform_packages = ; earlephilhower/framework-arduinopico@~1.20602.0 ; Cannot use the platformio package until old releases stop getting deleted - earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/3.9.4/rp2040-3.9.4.zip + earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/5.5.0/rp2040-5.5.0.zip framework = arduino lib_deps =