Skip to content

Commit c4e66ee

Browse files
committed
firmware: Firmware must be sector size multiple.
If the EV3 firmware size is not a multiple of the sector size, the flashing process will hang. Raise an error if this happens.
1 parent c36c1ae commit c4e66ee

File tree

5 files changed

+19
-4
lines changed

5 files changed

+19
-4
lines changed

src/firmware/actions.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export enum FailToFinishReasonType {
4747
FailedToCompile = 'flashFirmware.failToFinish.reason.failedToCompile',
4848
/** The combined firmware-base.bin and main.mpy are too big. */
4949
FirmwareSize = 'flashFirmware.failToFinish.reason.firmwareSize',
50+
/** The firmware has the wrong format (e.g. is not a multiple of sector size). */
51+
FirmwareSizeNotMultipleOfSector = 'flashFirmware.failToFinish.reason.firmwareSizeNotMultipleOfSector',
5052
/** An unexpected error occurred. */
5153
Unknown = 'flashFirmware.failToFinish.reason.unknown',
5254
}
@@ -94,6 +96,9 @@ export type FailToFinishReasonBadMetadata =
9496
export type FailToFinishReasonFirmwareSize =
9597
Reason<FailToFinishReasonType.FirmwareSize>;
9698

99+
export type FailToFinishReasonFirmwareFormat =
100+
Reason<FailToFinishReasonType.FirmwareSizeNotMultipleOfSector>;
101+
97102
export type FailToFinishReasonFailedToCompile =
98103
Reason<FailToFinishReasonType.FailedToCompile>;
99104

@@ -114,6 +119,7 @@ export type FailToFinishReason =
114119
| FailToFinishReasonBadMetadata
115120
| FailToFinishReasonFirmwareSize
116121
| FailToFinishReasonFailedToCompile
122+
| FailToFinishReasonFirmwareFormat
117123
| FailToFinishReasonUnknown;
118124

119125
// High-level bootloader actions.

src/notifications/i18n.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
// Copyright (c) 2020-2022 The Pybricks Authors
2+
// Copyright (c) 2020-2025 The Pybricks Authors
33
//
44
// Notification translation keys.
55

@@ -35,6 +35,7 @@ export enum I18nId {
3535
FlashFirmwareBadMetadata = 'flashFirmware.badMetadata',
3636
FlashFirmwareCompileError = 'flashFirmware.compileError',
3737
FlashFirmwareSizeTooBig = 'flashFirmware.sizeTooBig',
38+
FlashFirmwareSizeNotMultipleOfSector = 'flashFirmware.sizeNotMultipleOfSector',
3839
FlashFirmwareUnexpectedError = 'flashFirmware.unexpectedError',
3940
ServiceWorkerUpdateMessage = 'serviceWorker.update.message',
4041
ServiceWorkerUpdateAction = 'serviceWorker.update.action',

src/notifications/sagas.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
// Copyright (c) 2021-2023 The Pybricks Authors
2+
// Copyright (c) 2021-2025 The Pybricks Authors
33

44
import type { ToastOptions, Toaster } from '@blueprintjs/core';
55
import { FirmwareReaderError, FirmwareReaderErrorCode } from '@pybricks/firmware';
@@ -95,6 +95,7 @@ test.each([
9595
),
9696
didFailToFinish(FailToFinishReasonType.FailedToCompile),
9797
didFailToFinish(FailToFinishReasonType.FirmwareSize),
98+
didFailToFinish(FailToFinishReasonType.FirmwareSizeNotMultipleOfSector),
9899
didFailToFinish(FailToFinishReasonType.Unknown, new Error('test error')),
99100
appDidCheckForUpdate(false),
100101
fileStorageDidFailToInitialize(new Error('test error')),

src/notifications/sagas.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
// Copyright (c) 2020-2023 The Pybricks Authors
2+
// Copyright (c) 2020-2025 The Pybricks Authors
33

44
// Saga for managing notifications (toasts)
55

@@ -225,6 +225,12 @@ function* showFlashFirmwareError(
225225
case FailToFinishReasonType.FailedToCompile:
226226
yield* showSingleton(Level.Error, I18nId.FlashFirmwareCompileError);
227227
break;
228+
case FailToFinishReasonType.FirmwareSizeNotMultipleOfSector:
229+
yield* showSingleton(
230+
Level.Error,
231+
I18nId.FlashFirmwareSizeNotMultipleOfSector,
232+
);
233+
break;
228234
case FailToFinishReasonType.FirmwareSize:
229235
yield* showSingleton(Level.Error, I18nId.FlashFirmwareSizeTooBig);
230236
break;

src/notifications/translations/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
"badMetadata": "The firmware.metadata.json file contains missing or invalid entries. Fix it then try again.",
3434
"compileError": "The included main.py file could not be compiled. Fix it then try again.",
3535
"sizeTooBig": "The combined firmware and main.py are too big to fit in the flash memory.",
36-
"unexpectedError": "Unexpected error while trying to install firmware: {errorMessage}"
36+
"unexpectedError": "Unexpected error while trying to install firmware: {errorMessage}",
37+
"sizeNotMultipleOfSector": "The firmware size is not a multiple of the flash memory sector size."
3738
},
3839
"mpy": {
3940
"error": "{errorMessage}"

0 commit comments

Comments
 (0)