diff --git a/editor.html b/editor.html
index c59e79f..7117e86 100644
--- a/editor.html
+++ b/editor.html
@@ -1256,19 +1256,24 @@ function _b64(u8) { let s = ""; for (let i = 0; i < u8.length; i++) s += String.
// A/B-installs + reboots. CH is small (and a multiple of 4) so a chunk fits the Pico's USB-MIDI RX buffer.
async function _pushFirmware(b64) {
_send([0xF0, 0x7D, 0x21, 0xF7]);
- if (await _ack(3000) !== true) return "handshake";
+ if (await _ack(5000) !== true) return "handshake";
const CH = 64, total = Math.ceil(b64.length / CH); let done = 0;
+ const t0 = Date.now();
for (let o = 0; o < b64.length; o += CH) {
const part = b64.slice(o, o + CH); const msg = [0xF0, 0x7D, 0x22];
for (let i = 0; i < part.length; i++) msg.push(part.charCodeAt(i)); // base64 is ASCII
msg.push(0xF7); _send(msg);
- const a = await _ack(4000);
+ // Generous per-chunk timeout: an occasional flash flush on the device can take several seconds.
+ const a = await _ack(10000);
if (a !== true) return "chunk " + (done + 1) + "/" + total + (a === false ? " rejected" : " no-ack");
- if (++done % 50 === 0) console.log("[fw] pushed", done, "/", total, "chunks");
+ if (++done % 25 === 0) {
+ const el = ((Date.now() - t0) / 1000).toFixed(1);
+ console.log("[fw] pushed " + done + " / " + total + " chunks (" + el + " s)");
+ }
}
- console.log("[fw] all", total, "chunks sent; committing...");
+ console.log("[fw] all " + total + " chunks sent; committing...");
_send([0xF0, 0x7D, 0x23, 0xF7]);
- return (await _ack(6000)) === true ? null : "verify";
+ return (await _ack(10000)) === true ? null : "verify";
}
function _pickBinary() { // offline fallback: choose an app.mpy -> Uint8Array (or null if cancelled)
return new Promise(async (res) => {
diff --git a/pico-cp/__pycache__/app.cpython-312.pyc b/pico-cp/__pycache__/app.cpython-312.pyc
index c6a226a..f1ddf6e 100644
Binary files a/pico-cp/__pycache__/app.cpython-312.pyc and b/pico-cp/__pycache__/app.cpython-312.pyc differ
diff --git a/pico-cp/app.py b/pico-cp/app.py
index 2df5f11..8a923a2 100644
--- a/pico-cp/app.py
+++ b/pico-cp/app.py
@@ -407,7 +407,7 @@ class App:
self.midi_in = usb_midi.ports[0] if (MIDI_ENABLED and usb_midi and len(usb_midi.ports) > 0) else None
self._mbuf = bytearray(64); self.midi_host = False; self.last_midi_in = 0.0
self._sx = bytearray(); self._sxon = False # USB-MIDI SysEx assembler (clock + pushed programs)
- self._fw = None # chunked firmware transfer: staging file handle
+ self._fw = None; self._fw_n = 0 # chunked firmware transfer: staging file handle + chunk counter
self.led = RGB(P_RGB)
self.spk = pwmio.PWMOut(P_SPK, frequency=1600, variable_frequency=True, duty_cycle=0)
self.spk_off = 0
@@ -1088,13 +1088,17 @@ class App:
try:
try: self._fw.close()
except Exception: pass
- self._fw = open("/app.new", "wb"); self._ack(True)
+ self._fw = open("/app.new", "wb"); self._fw_n = 0; self._ack(True)
except Exception: # read-only (editor mode) / no space
self._fw = None; self._ack(False)
elif cmd == 0x22: # DATA: a base64 chunk (multiple of 4) -> decode -> append
try:
if self._fw is None or a2b_base64 is None: raise OSError()
- self._fw.write(a2b_base64(bytes(sx[2:]))); self._ack(True)
+ self._fw.write(a2b_base64(bytes(sx[2:])))
+ self._fw.flush() # small, predictable per-chunk flush (no slow burst flushes later)
+ self._fw_n += 1
+ if self._fw_n % 50 == 0: gc.collect() # keep the heap fresh during a long push
+ self._ack(True)
except Exception:
try: self._fw.close()
except Exception: pass