[rp2040] Update arduino-pico framework from 3.9.4 to 5.5.0

Update the RP2040 Arduino-Pico framework to 5.5.0 (from 3.9.4) and
the platform to v1.4.0-gcc14-arduinopico460 (GCC 14 toolchain).

Breaking changes adapted:
- pico-sdk 2.0: padsbank0_hw renamed to pads_bank0_hw
- Arduino.h now defines NOPIN as a global macro (SerialPIO::NOPIN removed)
- WiFi: cyw43_tcpip_link_status() no longer works because the Arduino
  framework's __wrap_cyw43_cb_tcpip_init is a no-op (the SDK's internal
  netif is never initialized). Switched to cyw43_wifi_link_status() for
  radio state + WiFi.status()/WiFi.connected() for IP-level state.
- WiFi: Use beginNoBlock() instead of begin() to avoid 20s+ blocking
- WiFi: Use WiFi.disconnect() for proper lwIP/DHCP cleanup
This commit is contained in:
J. Nick Koston
2026-02-26 10:54:35 -10:00
parent a05d0202e6
commit ec132fb081
6 changed files with 37 additions and 27 deletions

View File

@@ -1 +1 @@
5eb1e5852765114ad06533220d3160b6c23f5ccefc4de41828699de5dfff5ad6
b97e16a84153b2a4cfc51137cd6121db3c32374504b2bea55144413b3e573052

View File

@@ -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),
}

View File

@@ -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);

View File

@@ -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())

View File

@@ -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<bool> sta, optional<bool> 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) {

View File

@@ -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 =