From 055d2c8ca80acbef33b64d488586a2ea0788edfd Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sun, 4 Jan 2026 21:07:40 +0000 Subject: [PATCH] firmware/ev3: erase 2 sectors at one time Change from erasing 1 sector at a time to erasing 2 sectors at a time. This works around a USB issue where commands that don't take long to execute can receive an incorrect response. The point of erasing 2 sectors at a time is that when we write the data to the sectors that we just erased, the last (partial) chunk of data is now twice as large, which makes it take twice as long to write. This seems to be long enough to avoid the USB issue. --- src/firmware/sagas.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/firmware/sagas.ts b/src/firmware/sagas.ts index 93865685..32fcc348 100644 --- a/src/firmware/sagas.ts +++ b/src/firmware/sagas.ts @@ -1225,9 +1225,17 @@ function* handleFlashEV3(action: ReturnType): Generator const sectorSize = 64 * 1024; // flash memory sector size const maxPayloadSize = 1018; // maximum payload size for EV3 commands - for (let i = 0; i < action.firmware.byteLength; i += sectorSize) { - const sectorData = action.firmware.slice(i, i + sectorSize); - assert(sectorData.byteLength <= sectorSize, 'sector data too large'); + // HACK: Ideally, we would erase one sector at a time to minimize required + // alignment and make the progress indicator smoother. However, there is a + // bug triggered, e.g. by USB 3.0 on Windows, that causes bad replies from + // certain commands. This bug happens sometimes when the payload size is + // 384 bytes (triggered by 65536 % 1018 = 384). To work around this, we + // always erase two sectors to make the last chunk be twice as big + // (131072 % 1018 = 768). + const eraseSize = sectorSize * 2; // flash memory sector size + + for (let i = 0; i < action.firmware.byteLength; i += eraseSize) { + const sectorData = action.firmware.slice(i, i + eraseSize); const erasePayload = new DataView(new ArrayBuffer(8)); erasePayload.setUint32(0, i, true);