diff --git a/src/ui-touch/UITask.cpp b/src/ui-touch/UITask.cpp index 55e91cd..11eb828 100644 --- a/src/ui-touch/UITask.cpp +++ b/src/ui-touch/UITask.cpp @@ -34691,8 +34691,39 @@ static void otaWorkerRun(WiFiClient& client, HTTPClient& http) { Update.onProgress([](size_t done, size_t total) { s_ota_pct = total ? (int)((uint64_t)done * 100 / total) : 0; }); + // Copy by hand, yielding, instead of Update.writeStream(): that reads through + // Stream::timedRead, which spins without yielding until http's 20 s timeout, so a + // slow start starved IDLE0 on this core-0 worker and the 5 s task watchdog + // rebooted the device, "stuck at 0%, then a restart" (#689). Same loop as the SD + // download below: wait with vTaskDelay, give up after 15 s without data. auto* stream = http.getStreamPtr(); // NetworkClient* on arduino 3.x (P4: C6Client behind it) - const size_t written = stream ? Update.writeStream(*stream) : 0; + size_t written = 0; + { + size_t bufsz = 4096; + uint8_t* buf = (uint8_t*)heap_caps_malloc(bufsz, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (!buf) { bufsz = 1024; buf = (uint8_t*)heap_caps_malloc(bufsz, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); } + unsigned long last_data = millis(); + while (buf && stream && written < (size_t)len) { + const int avail = stream->available(); + if (avail <= 0) { + if (!http.connected() || (millis() - last_data) > 15000) break; + vTaskDelay(pdMS_TO_TICKS(10)); + continue; + } + const size_t want = ((size_t)avail > bufsz) ? bufsz : (size_t)avail; + const int n = stream->read(buf, want); + if (n <= 0) { + if ((millis() - last_data) > 15000) break; + vTaskDelay(pdMS_TO_TICKS(5)); + continue; + } + last_data = millis(); + if (Update.write(buf, (size_t)n) != (size_t)n) break; // flash write failed: reported below + written += (size_t)n; + vTaskDelay(1); // let IDLE0 (and Wi-Fi) run between blocks + } + if (buf) heap_caps_free(buf); + } http.end(); if (written != (size_t)len) { snprintf(s_ota_msg, sizeof s_ota_msg, "short read %u/%d", (unsigned)written, len);