@mikrojs/firmware 0.21.1-next.20260927212749 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/mikrojs/CMakeLists.txt +2 -2
- package/components/mikrojs/Kconfig +73 -1
- package/components/mikrojs/include/mikrojs_esp32.h +4 -3
- package/components/mikrojs/mik_ble.cpp +15 -4
- package/components/mikrojs/mik_ble_c_shim.c +10 -0
- package/components/mikrojs/mik_ble_c_shim.h +9 -0
- package/components/mikrojs/mik_deploy.cpp +92 -10
- package/components/mikrojs/mik_gpio.cpp +6 -1
- package/components/mikrojs/mik_http.cpp +10 -4
- package/components/mikrojs/mik_http_server.cpp +2 -0
- package/components/mikrojs/mik_i2s.cpp +17 -0
- package/components/mikrojs/mik_logfile.cpp +0 -7
- package/components/mikrojs/mik_main.cpp +130 -98
- package/components/mikrojs/mik_pwm.cpp +28 -1
- package/components/mikrojs/mik_serial_io.cpp +35 -23
- package/components/mikrojs/mik_sntp.cpp +2 -0
- package/components/mikrojs/mik_uart.cpp +41 -0
- package/components/mikrojs/mik_wifi.cpp +1 -0
- package/components/mikrojs/platform_esp32.cpp +76 -2
- package/dist/boards.d.ts +73 -12
- package/dist/boards.d.ts.map +1 -1
- package/dist/boards.js +137 -60
- package/dist/boards.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/sdkconfig.defaults +2 -0
- package/components/mikrojs/include/mem.h +0 -3
- package/components/mikrojs/include/mik_color.h +0 -3
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#include "mikrojs/platform.h"
|
|
2
2
|
#include "mikrojs_esp32.h"
|
|
3
3
|
|
|
4
|
+
#include <esp_attr.h>
|
|
4
5
|
#include <esp_log.h>
|
|
5
6
|
#include <esp_heap_caps.h>
|
|
6
7
|
#include <esp_mac.h>
|
|
8
|
+
#include <esp_netif.h>
|
|
7
9
|
#include <nanocbor/nanocbor.h>
|
|
8
10
|
#include <nvs.h>
|
|
9
11
|
#include <esp_random.h>
|
|
@@ -64,13 +66,72 @@ static void esp32_feed_watchdog(void) {
|
|
|
64
66
|
}
|
|
65
67
|
#endif
|
|
66
68
|
|
|
69
|
+
/* When the loop task last blocked. A wake already pending ends a wait at once,
|
|
70
|
+
* so a producer that wakes faster than a pass (a fast GPIO signal) could keep
|
|
71
|
+
* the task from blocking, and IDLE, which the task watchdog checks, would
|
|
72
|
+
* starve. Like mik__maybe_yield, sleep one tick per second of that. */
|
|
73
|
+
static int64_t s_last_block_us = 0;
|
|
74
|
+
|
|
67
75
|
static void esp32_yield(void) {
|
|
68
|
-
/* Every cooperative yield feeds the TWDT: between jobs
|
|
69
|
-
* loop
|
|
76
|
+
/* Every cooperative yield feeds the TWDT: between jobs and when the
|
|
77
|
+
* serve loop has work due now. */
|
|
70
78
|
#if CONFIG_ESP_TASK_WDT_EN
|
|
71
79
|
esp_task_wdt_reset();
|
|
72
80
|
#endif
|
|
73
81
|
vTaskDelay(1);
|
|
82
|
+
s_last_block_us = esp_timer_get_time();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* The task that blocks in esp32_wait (the main task), bound on its first
|
|
86
|
+
* wait. Producers on other tasks and in ISRs notify it. */
|
|
87
|
+
static TaskHandle_t s_loop_task = nullptr;
|
|
88
|
+
|
|
89
|
+
/* Wakes use notification index 1. Index 0 is the one ulTaskNotifyTake, driver
|
|
90
|
+
* code and pthread_join use, and native code on the JS task may block on it. */
|
|
91
|
+
#define MIK__WAKE_INDEX 1
|
|
92
|
+
static_assert(configTASK_NOTIFICATION_ARRAY_ENTRIES > MIK__WAKE_INDEX,
|
|
93
|
+
"the loop's wake needs a second task notification: set "
|
|
94
|
+
"CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2 in sdkconfig, or delete sdkconfig "
|
|
95
|
+
"and re-run `mikro idf set-target` so sdkconfig.defaults applies");
|
|
96
|
+
|
|
97
|
+
static void esp32_wait(int64_t timeout_us) {
|
|
98
|
+
if (!s_loop_task) {
|
|
99
|
+
/* Bind and return: a wake that raced this first call is not lost. */
|
|
100
|
+
s_loop_task = xTaskGetCurrentTaskHandle();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
#if CONFIG_ESP_TASK_WDT_EN
|
|
104
|
+
esp_task_wdt_reset();
|
|
105
|
+
#endif
|
|
106
|
+
/* Whole ticks, rounded up; FreeRTOS counts from the current partial tick,
|
|
107
|
+
* so the wait can still end up to one tick early and the next pass waits
|
|
108
|
+
* the remainder. */
|
|
109
|
+
TickType_t ticks = (TickType_t)((timeout_us + portTICK_PERIOD_MS * 1000 - 1) /
|
|
110
|
+
(portTICK_PERIOD_MS * 1000));
|
|
111
|
+
if (ticks == 0) ticks = 1;
|
|
112
|
+
if (ulTaskNotifyTakeIndexed(MIK__WAKE_INDEX, pdTRUE, 0) == 0) {
|
|
113
|
+
ulTaskNotifyTakeIndexed(MIK__WAKE_INDEX, pdTRUE, ticks);
|
|
114
|
+
s_last_block_us = esp_timer_get_time();
|
|
115
|
+
} else if (esp_timer_get_time() - s_last_block_us >= 1000 * 1000) {
|
|
116
|
+
vTaskDelay(1);
|
|
117
|
+
s_last_block_us = esp_timer_get_time();
|
|
118
|
+
}
|
|
119
|
+
#if CONFIG_ESP_TASK_WDT_EN
|
|
120
|
+
esp_task_wdt_reset();
|
|
121
|
+
#endif
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
static void esp32_wake(void) {
|
|
125
|
+
if (s_loop_task) xTaskNotifyGiveIndexed(s_loop_task, MIK__WAKE_INDEX);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* IRAM: called from handlers that run while the flash cache is off (the
|
|
129
|
+
* GPIO and UART ISRs are installed with ESP_INTR_FLAG_IRAM). */
|
|
130
|
+
void IRAM_ATTR MIK_WakeFromISR(void) {
|
|
131
|
+
if (!s_loop_task) return;
|
|
132
|
+
BaseType_t woken = pdFALSE;
|
|
133
|
+
vTaskNotifyGiveIndexedFromISR(s_loop_task, MIK__WAKE_INDEX, &woken);
|
|
134
|
+
portYIELD_FROM_ISR(woken);
|
|
74
135
|
}
|
|
75
136
|
|
|
76
137
|
static size_t esp32_get_free_system_mem(void) {
|
|
@@ -330,6 +391,16 @@ static void esp32_log(int level, const char* tag, const char* fmt, ...) {
|
|
|
330
391
|
mik__console_write(buf, total + 1);
|
|
331
392
|
}
|
|
332
393
|
|
|
394
|
+
/* Start lwip's tcpip thread. esp_netif_init is idempotent (INVALID_STATE
|
|
395
|
+
* on a second call); the wifi and http modules run it too and share the
|
|
396
|
+
* result. */
|
|
397
|
+
static void esp32_net_init(void) {
|
|
398
|
+
esp_err_t err = esp_netif_init();
|
|
399
|
+
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
|
|
400
|
+
ESP_LOGE("mikrojs", "esp_netif_init failed: %s", esp_err_to_name(err));
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
333
404
|
static const MIKPlatform esp32_platform = {
|
|
334
405
|
.get_boot_us = esp32_get_boot_us,
|
|
335
406
|
.get_rtc_us = esp32_get_rtc_us,
|
|
@@ -337,6 +408,8 @@ static const MIKPlatform esp32_platform = {
|
|
|
337
408
|
.restart = esp32_restart,
|
|
338
409
|
.deep_sleep_us = esp32_deep_sleep_us,
|
|
339
410
|
.yield = esp32_yield,
|
|
411
|
+
.wait = esp32_wait,
|
|
412
|
+
.wake = esp32_wake,
|
|
340
413
|
#if CONFIG_ESP_TASK_WDT_EN
|
|
341
414
|
.feed_watchdog = esp32_feed_watchdog,
|
|
342
415
|
#else
|
|
@@ -361,6 +434,7 @@ static const MIKPlatform esp32_platform = {
|
|
|
361
434
|
.get_device_name = esp32_get_device_name,
|
|
362
435
|
.set_device_name = esp32_set_device_name,
|
|
363
436
|
.get_reset_reason = esp32_get_reset_reason,
|
|
437
|
+
.net_init = esp32_net_init,
|
|
364
438
|
};
|
|
365
439
|
|
|
366
440
|
/*
|
package/dist/boards.d.ts
CHANGED
|
@@ -43,6 +43,18 @@ export interface FirmwareExport {
|
|
|
43
43
|
target: string;
|
|
44
44
|
file: string;
|
|
45
45
|
}
|
|
46
|
+
/** A board that runs one of the generic images, as its firmware.json says.
|
|
47
|
+
* `mikro flash` flashes that image with the board's name written into it. */
|
|
48
|
+
export interface GenericBoard {
|
|
49
|
+
name: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
/** The generic board whose image it runs: `esp32-generic`. */
|
|
52
|
+
firmware: string;
|
|
53
|
+
specifier: string;
|
|
54
|
+
key: string;
|
|
55
|
+
packageName: string;
|
|
56
|
+
packageDir: string;
|
|
57
|
+
}
|
|
46
58
|
/** The full image's folder in the board's, and its name for `--features`. */
|
|
47
59
|
export declare const FULL_IMAGE = "full";
|
|
48
60
|
/** A board's name in file and artifact names: `@acme/pi` becomes `acme-pi`. */
|
|
@@ -52,31 +64,40 @@ export declare function boardFileName(name: string): string;
|
|
|
52
64
|
* or `mikro-fw-<chip>` for firmware without a name. The chip is left out when
|
|
53
65
|
* the name already ends with it (`seeed-xiao-esp32c6`) or is `<chip>-generic`,
|
|
54
66
|
* so the chip is always the last word, or the one before `generic`.
|
|
55
|
-
* `mikro fw pack` names archives this way, and
|
|
56
|
-
*
|
|
67
|
+
* `mikro fw pack` names archives this way, and the CI artifact of a build has
|
|
68
|
+
* the same name.
|
|
57
69
|
*/
|
|
58
70
|
export declare function archiveName(name: string | undefined, chip: string): string;
|
|
59
|
-
/** Whether an archive name (without `.tar.gz`) is a full image for `chip`, by
|
|
60
|
-
* the place archiveName puts the chip. A board's other images (`+no-ble`)
|
|
61
|
-
* are only ever asked for by name. */
|
|
62
|
-
export declare function isArchiveForChip(archive: string, chip: string): boolean;
|
|
63
71
|
/** The package's `firmware` exports, and the ones that can't name a board. */
|
|
64
72
|
export declare function firmwareExports(packageDir: string): {
|
|
65
73
|
entries: FirmwareExport[];
|
|
66
74
|
problems: BoardProblem[];
|
|
67
75
|
};
|
|
68
|
-
|
|
76
|
+
type ImageJson = Pick<BoardImage, 'name' | 'description' | 'chip' | 'version' | 'features'>;
|
|
77
|
+
type GenericJson = Pick<GenericBoard, 'name' | 'description' | 'firmware'>;
|
|
78
|
+
/** What an image's firmware.json says, or why it can't describe an image. */
|
|
69
79
|
export declare function readFirmwareJson(file: string): {
|
|
70
80
|
ok: true;
|
|
71
|
-
value:
|
|
81
|
+
value: ImageJson;
|
|
72
82
|
} | {
|
|
73
83
|
ok: false;
|
|
74
84
|
message: string;
|
|
75
85
|
};
|
|
76
|
-
/**
|
|
77
|
-
*
|
|
86
|
+
/** What the firmware.json of a board that runs a generic image says, or why
|
|
87
|
+
* it isn't one. */
|
|
88
|
+
export declare function readGenericBoardJson(file: string): {
|
|
89
|
+
ok: true;
|
|
90
|
+
value: GenericJson;
|
|
91
|
+
} | {
|
|
92
|
+
ok: false;
|
|
93
|
+
message: string;
|
|
94
|
+
};
|
|
95
|
+
/** The boards a package declares: those with an image of their own in
|
|
96
|
+
* `boards`, those that run a generic image in `generic`, and the `firmware`
|
|
97
|
+
* exports that are neither (not built, or not a Mikro.js firmware.json). */
|
|
78
98
|
export declare function loadBoards(packageDir: string): {
|
|
79
99
|
boards: BoardImage[];
|
|
100
|
+
generic: GenericBoard[];
|
|
80
101
|
problems: BoardProblem[];
|
|
81
102
|
};
|
|
82
103
|
/**
|
|
@@ -130,6 +151,31 @@ export interface BoardConfig {
|
|
|
130
151
|
/** Images to build besides the full one, each with features switched off
|
|
131
152
|
* or on: `[{ble: false}, {ble: false, wifi: false}]`. */
|
|
132
153
|
images?: readonly ImageFeatures[];
|
|
154
|
+
/** Only for a board on the generic firmware (GenericBoardConfig). */
|
|
155
|
+
firmware?: never;
|
|
156
|
+
}
|
|
157
|
+
/** The generic boards, one per chip: the firmware a board on the generic
|
|
158
|
+
* firmware runs. */
|
|
159
|
+
declare const GENERIC_FIRMWARE: ("esp32-generic" | "esp32c3-generic" | "esp32c5-generic" | "esp32c6-generic" | "esp32s3-generic")[];
|
|
160
|
+
export type GenericFirmware = (typeof GENERIC_FIRMWARE)[number];
|
|
161
|
+
/** A board in boards.config.ts that runs one of the generic images, such as a
|
|
162
|
+
* board whose drivers are all JavaScript. `mikro flash` writes its name into
|
|
163
|
+
* the image. */
|
|
164
|
+
export interface GenericBoardConfig {
|
|
165
|
+
/** The generic board whose image it runs: `esp32-generic`. */
|
|
166
|
+
firmware: GenericFirmware;
|
|
167
|
+
/** The name the device reports as sys.board.name. Default: the specifier of
|
|
168
|
+
* the board's export. */
|
|
169
|
+
name?: string;
|
|
170
|
+
/** Shown when `mikro flash` asks which board to flash. Default: the
|
|
171
|
+
* package's description. */
|
|
172
|
+
description?: string;
|
|
173
|
+
chip?: never;
|
|
174
|
+
sdkconfig?: never;
|
|
175
|
+
partitions?: never;
|
|
176
|
+
nativeModules?: never;
|
|
177
|
+
project?: never;
|
|
178
|
+
images?: never;
|
|
133
179
|
}
|
|
134
180
|
/** boards.config.ts: the boards a package builds, keyed by the export that
|
|
135
181
|
* declares each, `.` or `./<board>`. */
|
|
@@ -138,7 +184,7 @@ export interface BoardsConfig {
|
|
|
138
184
|
* board at `.`, `<dist>/<board>/full/` for the others, and each other image
|
|
139
185
|
* in a folder beside `full/`. Default: `dist-fw`. */
|
|
140
186
|
dist?: string;
|
|
141
|
-
boards: Record<string, BoardConfig>;
|
|
187
|
+
boards: Record<string, BoardConfig | GenericBoardConfig>;
|
|
142
188
|
}
|
|
143
189
|
/** A board from boards.config.ts, with defaults filled in and paths resolved. */
|
|
144
190
|
export interface ConfiguredBoard {
|
|
@@ -161,6 +207,19 @@ export interface ConfiguredBoard {
|
|
|
161
207
|
/** The images besides the full one. */
|
|
162
208
|
images: ConfiguredImage[];
|
|
163
209
|
}
|
|
210
|
+
/** A board from boards.config.ts that runs a generic image. `mikro fw build`
|
|
211
|
+
* writes its firmware.json to `target`, which names the generic board. */
|
|
212
|
+
export interface ConfiguredGenericBoard {
|
|
213
|
+
key: string;
|
|
214
|
+
specifier: string;
|
|
215
|
+
name: string;
|
|
216
|
+
description?: string;
|
|
217
|
+
firmware: GenericFirmware;
|
|
218
|
+
/** The generic board's chip. */
|
|
219
|
+
chip: Chip;
|
|
220
|
+
target: string;
|
|
221
|
+
boardDir: string;
|
|
222
|
+
}
|
|
164
223
|
/** An image from `images` in boards.config.ts. */
|
|
165
224
|
export interface ConfiguredImage {
|
|
166
225
|
/** `no-ble`: the image's folder in the board's, and its name everywhere else. */
|
|
@@ -175,10 +234,12 @@ export interface ConfiguredImage {
|
|
|
175
234
|
* and everything wrong with it: fields that don't check out, files it names
|
|
176
235
|
* that don't exist, names a device can't take, and `exports` that don't match
|
|
177
236
|
* (a board without its `firmware` export, one pointing elsewhere, or a
|
|
178
|
-
* `firmware` export the config doesn't have).
|
|
237
|
+
* `firmware` export the config doesn't have). Boards with an image of their own
|
|
238
|
+
* are in `boards`, boards that run a generic image in `generic`.
|
|
179
239
|
*/
|
|
180
240
|
export declare function checkBoardsConfig(packageDir: string, config: unknown): {
|
|
181
241
|
boards: ConfiguredBoard[];
|
|
242
|
+
generic: ConfiguredGenericBoard[];
|
|
182
243
|
problems: BoardProblem[];
|
|
183
244
|
};
|
|
184
245
|
//# sourceMappingURL=boards.d.ts.map
|
package/dist/boards.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boards.d.ts","sourceRoot":"","sources":["../src/boards.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAC,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"boards.d.ts","sourceRoot":"","sources":["../src/boards.ts"],"names":[],"mappings":"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"}
|
package/dist/boards.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
22
22
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
23
23
|
import { array, enumOf, object, optional, string, validate } from '@mikrojs/schema';
|
|
24
|
-
import { chips } from "./index.js";
|
|
24
|
+
import { CHIPS, chips } from "./index.js";
|
|
25
25
|
/** The form of a board name: a package name, optionally with /<board>. The
|
|
26
26
|
* device keeps it in a 64-byte buffer, and a registry checks the same form
|
|
27
27
|
* (docs/registry-spec.md, "Board names"). */
|
|
@@ -34,6 +34,13 @@ const FirmwareJson = object({
|
|
|
34
34
|
version: string(),
|
|
35
35
|
features: optional(array(string())),
|
|
36
36
|
});
|
|
37
|
+
/** The firmware.json of a board that runs a generic image: no image of its
|
|
38
|
+
* own, the generic board's name in `firmware`. */
|
|
39
|
+
const GenericFirmwareJson = object({
|
|
40
|
+
name: string(),
|
|
41
|
+
description: optional(string()),
|
|
42
|
+
firmware: string(),
|
|
43
|
+
});
|
|
37
44
|
/** An image name: what it leaves out (`no-ble`) or adds, joined with `+`. */
|
|
38
45
|
const IMAGE_NAME_RE = /^(no-)?[a-z0-9]+(\+(no-)?[a-z0-9]+)*$/;
|
|
39
46
|
/** The full image's folder in the board's, and its name for `--features`. */
|
|
@@ -47,8 +54,8 @@ export function boardFileName(name) {
|
|
|
47
54
|
* or `mikro-fw-<chip>` for firmware without a name. The chip is left out when
|
|
48
55
|
* the name already ends with it (`seeed-xiao-esp32c6`) or is `<chip>-generic`,
|
|
49
56
|
* so the chip is always the last word, or the one before `generic`.
|
|
50
|
-
* `mikro fw pack` names archives this way, and
|
|
51
|
-
*
|
|
57
|
+
* `mikro fw pack` names archives this way, and the CI artifact of a build has
|
|
58
|
+
* the same name.
|
|
52
59
|
*/
|
|
53
60
|
export function archiveName(name, chip) {
|
|
54
61
|
if (name === undefined)
|
|
@@ -58,14 +65,6 @@ export function archiveName(name, chip) {
|
|
|
58
65
|
? `mikro-fw-${fileName}`
|
|
59
66
|
: `mikro-fw-${fileName}-${chip}`;
|
|
60
67
|
}
|
|
61
|
-
/** Whether an archive name (without `.tar.gz`) is a full image for `chip`, by
|
|
62
|
-
* the place archiveName puts the chip. A board's other images (`+no-ble`)
|
|
63
|
-
* are only ever asked for by name. */
|
|
64
|
-
export function isArchiveForChip(archive, chip) {
|
|
65
|
-
return (archive.startsWith('mikro-fw-') &&
|
|
66
|
-
!archive.includes('+') &&
|
|
67
|
-
(archive.endsWith(`-${chip}`) || archive === `mikro-fw-${chip}-generic`));
|
|
68
|
-
}
|
|
69
68
|
function readPackageJson(packageDir) {
|
|
70
69
|
const file = join(packageDir, 'package.json');
|
|
71
70
|
try {
|
|
@@ -120,18 +119,24 @@ export function firmwareExports(packageDir) {
|
|
|
120
119
|
}
|
|
121
120
|
return { entries, problems };
|
|
122
121
|
}
|
|
123
|
-
/**
|
|
124
|
-
|
|
122
|
+
/** A firmware.json's content, or why it can't be read. */
|
|
123
|
+
function readJson(file) {
|
|
125
124
|
if (!existsSync(file))
|
|
126
125
|
return { ok: false, message: `not built: ${file} does not exist` };
|
|
127
|
-
let json;
|
|
128
126
|
try {
|
|
129
|
-
|
|
127
|
+
return { ok: true, value: JSON.parse(readFileSync(file, 'utf8')) };
|
|
130
128
|
}
|
|
131
129
|
catch (e) {
|
|
132
130
|
return { ok: false, message: `${file} is not valid JSON: ${e.message}` };
|
|
133
131
|
}
|
|
134
|
-
|
|
132
|
+
}
|
|
133
|
+
/** Whether a firmware.json is a generic board's: no image, a `firmware` instead. */
|
|
134
|
+
function isGenericJson(json) {
|
|
135
|
+
return isObject(json) && Object.hasOwn(json, 'firmware');
|
|
136
|
+
}
|
|
137
|
+
/** `json` checked against `schema` and the board-name form, or why it isn't. */
|
|
138
|
+
function checkedJson(schema, json, file) {
|
|
139
|
+
const invalid = validate(schema, json, '');
|
|
135
140
|
if (invalid) {
|
|
136
141
|
const { message, path } = invalid.error;
|
|
137
142
|
return { ok: false, message: `${file}${path ? ` (${path.slice(1)})` : ''}: ${message}` };
|
|
@@ -143,16 +148,35 @@ export function readFirmwareJson(file) {
|
|
|
143
148
|
message: `${file}: "${value.name}" is not a board name (at most ${MAX_BOARD_NAME_LENGTH} characters, the form of a package name with an optional /<board>)`,
|
|
144
149
|
};
|
|
145
150
|
}
|
|
146
|
-
return {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
};
|
|
151
|
+
return { ok: true, value };
|
|
152
|
+
}
|
|
153
|
+
function imageJson(json, file) {
|
|
154
|
+
if (isGenericJson(json)) {
|
|
155
|
+
return { ok: false, message: `${file} is a board that runs a generic image, not an image` };
|
|
156
|
+
}
|
|
157
|
+
const read = checkedJson(FirmwareJson, json, file);
|
|
158
|
+
if (!read.ok)
|
|
159
|
+
return read;
|
|
160
|
+
const { name, description, chip, version, features } = read.value;
|
|
161
|
+
return { ok: true, value: { name, description, chip, version, features } };
|
|
162
|
+
}
|
|
163
|
+
function genericJson(json, file) {
|
|
164
|
+
const read = checkedJson(GenericFirmwareJson, json, file);
|
|
165
|
+
if (!read.ok)
|
|
166
|
+
return read;
|
|
167
|
+
const { name, description, firmware } = read.value;
|
|
168
|
+
return { ok: true, value: { name, description, firmware } };
|
|
169
|
+
}
|
|
170
|
+
/** What an image's firmware.json says, or why it can't describe an image. */
|
|
171
|
+
export function readFirmwareJson(file) {
|
|
172
|
+
const json = readJson(file);
|
|
173
|
+
return json.ok ? imageJson(json.value, file) : json;
|
|
174
|
+
}
|
|
175
|
+
/** What the firmware.json of a board that runs a generic image says, or why
|
|
176
|
+
* it isn't one. */
|
|
177
|
+
export function readGenericBoardJson(file) {
|
|
178
|
+
const json = readJson(file);
|
|
179
|
+
return json.ok ? genericJson(json.value, file) : json;
|
|
156
180
|
}
|
|
157
181
|
/** A board's other images: the folders beside its full image's `full/`
|
|
158
182
|
* folder, named like an image, that hold an image of the same board. */
|
|
@@ -176,25 +200,40 @@ function siblingImages(dir, name, chip) {
|
|
|
176
200
|
}
|
|
177
201
|
return images.sort((a, b) => a.name.localeCompare(b.name));
|
|
178
202
|
}
|
|
179
|
-
/** The boards a package declares
|
|
180
|
-
*
|
|
203
|
+
/** The boards a package declares: those with an image of their own in
|
|
204
|
+
* `boards`, those that run a generic image in `generic`, and the `firmware`
|
|
205
|
+
* exports that are neither (not built, or not a Mikro.js firmware.json). */
|
|
181
206
|
export function loadBoards(packageDir) {
|
|
182
207
|
const { entries, problems } = firmwareExports(packageDir);
|
|
183
|
-
const
|
|
184
|
-
const packageName = (
|
|
208
|
+
const pkg = readPackageJson(packageDir);
|
|
209
|
+
const packageName = (pkg.ok ? pkg.value.name : undefined) ?? packageDir;
|
|
185
210
|
const boards = [];
|
|
211
|
+
const generic = [];
|
|
186
212
|
for (const { key, specifier, file } of entries) {
|
|
187
|
-
const
|
|
188
|
-
if (
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
213
|
+
const json = readJson(file);
|
|
214
|
+
if (!json.ok) {
|
|
215
|
+
problems.push({ specifier, message: json.message });
|
|
216
|
+
}
|
|
217
|
+
else if (isGenericJson(json.value)) {
|
|
218
|
+
const read = genericJson(json.value, file);
|
|
219
|
+
if (read.ok)
|
|
220
|
+
generic.push({ ...read.value, specifier, key, packageName, packageDir });
|
|
221
|
+
else
|
|
222
|
+
problems.push({ specifier, message: read.message });
|
|
192
223
|
}
|
|
193
224
|
else {
|
|
194
|
-
|
|
225
|
+
const read = imageJson(json.value, file);
|
|
226
|
+
if (read.ok) {
|
|
227
|
+
const dir = dirname(file);
|
|
228
|
+
const images = siblingImages(dir, read.value.name, read.value.chip);
|
|
229
|
+
boards.push({ ...read.value, images, specifier, key, packageName, packageDir, dir });
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
problems.push({ specifier, message: read.message });
|
|
233
|
+
}
|
|
195
234
|
}
|
|
196
235
|
}
|
|
197
|
-
return { boards, problems };
|
|
236
|
+
return { boards, generic, problems };
|
|
198
237
|
}
|
|
199
238
|
/** Whether npm publishes `path` (relative to the package) under this `files`
|
|
200
239
|
* list. Glob entries are taken as covering it: they need npm's matcher. */
|
|
@@ -224,7 +263,7 @@ export function checkBoardPackage(packageDir) {
|
|
|
224
263
|
return [{ specifier: packageDir, message: read.message }];
|
|
225
264
|
const pkg = read.value;
|
|
226
265
|
const { entries } = firmwareExports(packageDir);
|
|
227
|
-
const { boards, problems } = loadBoards(packageDir);
|
|
266
|
+
const { boards, generic, problems } = loadBoards(packageDir);
|
|
228
267
|
const packageName = pkg.name ?? packageDir;
|
|
229
268
|
for (const { specifier, target, file } of entries) {
|
|
230
269
|
const inPackage = relative(packageDir, dirname(file));
|
|
@@ -265,7 +304,7 @@ export function checkBoardPackage(packageDir) {
|
|
|
265
304
|
}
|
|
266
305
|
}
|
|
267
306
|
const byName = new Map();
|
|
268
|
-
for (const board of boards) {
|
|
307
|
+
for (const board of [...boards, ...generic]) {
|
|
269
308
|
const other = byName.get(board.name);
|
|
270
309
|
if (other) {
|
|
271
310
|
problems.push({
|
|
@@ -309,6 +348,12 @@ export function sortImageName(name) {
|
|
|
309
348
|
.sort((a, b) => feature(a).localeCompare(feature(b)))
|
|
310
349
|
.join('+');
|
|
311
350
|
}
|
|
351
|
+
/** The generic boards, one per chip: the firmware a board on the generic
|
|
352
|
+
* firmware runs. */
|
|
353
|
+
const GENERIC_FIRMWARE = CHIPS.map((chip) => `${chip}-generic`);
|
|
354
|
+
function isGenericFirmware(name) {
|
|
355
|
+
return GENERIC_FIRMWARE.includes(name);
|
|
356
|
+
}
|
|
312
357
|
const DEFAULT_DIST = 'dist-fw';
|
|
313
358
|
const BOARD_KEYS = [
|
|
314
359
|
'chip',
|
|
@@ -320,6 +365,7 @@ const BOARD_KEYS = [
|
|
|
320
365
|
'project',
|
|
321
366
|
'images',
|
|
322
367
|
];
|
|
368
|
+
const GENERIC_BOARD_KEYS = ['firmware', 'name', 'description'];
|
|
323
369
|
/** `./<board>`: one segment, in the form of a board name's last part. */
|
|
324
370
|
const SUBPATH_RE = /^\.\/[a-z0-9]([a-z0-9.-]*[a-z0-9])?$/;
|
|
325
371
|
function isStringArray(value) {
|
|
@@ -334,18 +380,21 @@ function exportsSnippet(boards) {
|
|
|
334
380
|
* and everything wrong with it: fields that don't check out, files it names
|
|
335
381
|
* that don't exist, names a device can't take, and `exports` that don't match
|
|
336
382
|
* (a board without its `firmware` export, one pointing elsewhere, or a
|
|
337
|
-
* `firmware` export the config doesn't have).
|
|
383
|
+
* `firmware` export the config doesn't have). Boards with an image of their own
|
|
384
|
+
* are in `boards`, boards that run a generic image in `generic`.
|
|
338
385
|
*/
|
|
339
386
|
export function checkBoardsConfig(packageDir, config) {
|
|
340
387
|
const read = readPackageJson(packageDir);
|
|
341
|
-
if (!read.ok)
|
|
342
|
-
return { boards: [], problems: [{ specifier: packageDir, message: read.message }] };
|
|
388
|
+
if (!read.ok) {
|
|
389
|
+
return { boards: [], generic: [], problems: [{ specifier: packageDir, message: read.message }] };
|
|
390
|
+
}
|
|
343
391
|
const pkg = read.value;
|
|
344
392
|
const packageName = pkg.name ?? packageDir;
|
|
345
393
|
const problems = [];
|
|
346
394
|
// Stops at a problem that leaves nothing to check, keeping the ones found so far
|
|
347
395
|
const fail = (message) => ({
|
|
348
396
|
boards: [],
|
|
397
|
+
generic: [],
|
|
349
398
|
problems: [...problems, { specifier: packageName, message }],
|
|
350
399
|
});
|
|
351
400
|
if (pkg.name === undefined)
|
|
@@ -375,6 +424,7 @@ export function checkBoardsConfig(packageDir, config) {
|
|
|
375
424
|
return fail('boards.config.ts: a package has one board at "." or boards at "./<board>", not both');
|
|
376
425
|
}
|
|
377
426
|
const boards = [];
|
|
427
|
+
const generic = [];
|
|
378
428
|
for (const [key, board] of Object.entries(config.boards)) {
|
|
379
429
|
const sub = key.slice(2);
|
|
380
430
|
const specifier = key === '.' ? packageName : `${packageName}/${sub}`;
|
|
@@ -388,20 +438,55 @@ export function checkBoardsConfig(packageDir, config) {
|
|
|
388
438
|
problem('expected an object');
|
|
389
439
|
continue;
|
|
390
440
|
}
|
|
441
|
+
const { name, description } = board;
|
|
442
|
+
if (name !== undefined && typeof name !== 'string')
|
|
443
|
+
problem('"name" must be a string');
|
|
444
|
+
if (description !== undefined && typeof description !== 'string') {
|
|
445
|
+
problem('"description" must be a string');
|
|
446
|
+
}
|
|
447
|
+
const boardName = typeof name === 'string' ? name : specifier;
|
|
448
|
+
if (!BOARD_NAME_RE.test(boardName) || boardName.length > MAX_BOARD_NAME_LENGTH) {
|
|
449
|
+
problem(`"${boardName}" is not a board name (at most ${MAX_BOARD_NAME_LENGTH} characters, the ` +
|
|
450
|
+
'form of a package name with an optional /<board>)' +
|
|
451
|
+
(typeof name === 'string' ? '' : '; set "name"'));
|
|
452
|
+
}
|
|
453
|
+
const target = `./${distPath}/${key === '.' ? '' : `${sub}/`}${FULL_IMAGE}/firmware.json`;
|
|
454
|
+
const boardDir = key === '.' ? distDir : join(distDir, sub);
|
|
455
|
+
const boardDescription = typeof description === 'string' ? description : pkg.description;
|
|
456
|
+
if (Object.hasOwn(board, 'firmware')) {
|
|
457
|
+
const { firmware } = board;
|
|
458
|
+
for (const field of Object.keys(board)) {
|
|
459
|
+
if (GENERIC_BOARD_KEYS.includes(field))
|
|
460
|
+
continue;
|
|
461
|
+
problem(BOARD_KEYS.includes(field)
|
|
462
|
+
? `a board that runs a generic image gets "${field}" from it; leave out "${field}"`
|
|
463
|
+
: `unknown field "${field}"`);
|
|
464
|
+
}
|
|
465
|
+
if (!isGenericFirmware(firmware)) {
|
|
466
|
+
problem(`"firmware" must be one of ${GENERIC_FIRMWARE.join(', ')}`);
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
generic.push({
|
|
470
|
+
key,
|
|
471
|
+
specifier,
|
|
472
|
+
name: boardName,
|
|
473
|
+
description: boardDescription,
|
|
474
|
+
firmware,
|
|
475
|
+
chip: CHIPS[GENERIC_FIRMWARE.indexOf(firmware)],
|
|
476
|
+
target,
|
|
477
|
+
boardDir,
|
|
478
|
+
});
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
391
481
|
for (const field of Object.keys(board)) {
|
|
392
482
|
if (!BOARD_KEYS.includes(field))
|
|
393
483
|
problem(`unknown field "${field}"`);
|
|
394
484
|
}
|
|
395
|
-
const { chip,
|
|
485
|
+
const { chip, sdkconfig, partitions, nativeModules, project, images } = board;
|
|
396
486
|
if (typeof chip !== 'string' || !chips.includes(chip)) {
|
|
397
487
|
problem(`"chip" must be one of ${chips.join(', ')}`);
|
|
398
488
|
continue;
|
|
399
489
|
}
|
|
400
|
-
if (name !== undefined && typeof name !== 'string')
|
|
401
|
-
problem('"name" must be a string');
|
|
402
|
-
if (description !== undefined && typeof description !== 'string') {
|
|
403
|
-
problem('"description" must be a string');
|
|
404
|
-
}
|
|
405
490
|
if (sdkconfig !== undefined && typeof sdkconfig !== 'string' && !isStringArray(sdkconfig)) {
|
|
406
491
|
problem('"sdkconfig" must be a path or a list of paths');
|
|
407
492
|
}
|
|
@@ -458,19 +543,11 @@ export function checkBoardsConfig(packageDir, config) {
|
|
|
458
543
|
if (!existsSync(resolve(packageDir, file)))
|
|
459
544
|
problem(`${file} does not exist`);
|
|
460
545
|
}
|
|
461
|
-
const boardName = typeof name === 'string' ? name : specifier;
|
|
462
|
-
if (!BOARD_NAME_RE.test(boardName) || boardName.length > MAX_BOARD_NAME_LENGTH) {
|
|
463
|
-
problem(`"${boardName}" is not a board name (at most ${MAX_BOARD_NAME_LENGTH} characters, the ` +
|
|
464
|
-
'form of a package name with an optional /<board>)' +
|
|
465
|
-
(typeof name === 'string' ? '' : '; set "name"'));
|
|
466
|
-
}
|
|
467
|
-
const target = `./${distPath}/${key === '.' ? '' : `${sub}/`}${FULL_IMAGE}/firmware.json`;
|
|
468
|
-
const boardDir = key === '.' ? distDir : join(distDir, sub);
|
|
469
546
|
boards.push({
|
|
470
547
|
key,
|
|
471
548
|
specifier,
|
|
472
549
|
name: boardName,
|
|
473
|
-
description:
|
|
550
|
+
description: boardDescription,
|
|
474
551
|
chip: chip,
|
|
475
552
|
sdkconfig: (typeof sdkconfig === 'string'
|
|
476
553
|
? [sdkconfig]
|
|
@@ -486,7 +563,7 @@ export function checkBoardsConfig(packageDir, config) {
|
|
|
486
563
|
});
|
|
487
564
|
}
|
|
488
565
|
const byName = new Map();
|
|
489
|
-
for (const board of boards) {
|
|
566
|
+
for (const board of [...boards, ...generic]) {
|
|
490
567
|
const other = byName.get(board.name);
|
|
491
568
|
if (other) {
|
|
492
569
|
problems.push({
|
|
@@ -499,7 +576,7 @@ export function checkBoardsConfig(packageDir, config) {
|
|
|
499
576
|
// The exports must declare exactly the configured boards, where the config
|
|
500
577
|
// puts their images.
|
|
501
578
|
const targets = firmwareTargets(pkg.exports);
|
|
502
|
-
const missing = boards.filter((board) => {
|
|
579
|
+
const missing = [...boards, ...generic].filter((board) => {
|
|
503
580
|
const target = targets.get(board.key);
|
|
504
581
|
return (typeof target !== 'string' ||
|
|
505
582
|
resolve(packageDir, target) !== resolve(packageDir, board.target));
|
|
@@ -527,6 +604,6 @@ export function checkBoardsConfig(packageDir, config) {
|
|
|
527
604
|
message: `add these to "exports" in package.json (next to any other conditions of the same export):\n${exportsSnippet(missing)}`,
|
|
528
605
|
});
|
|
529
606
|
}
|
|
530
|
-
return { boards, problems };
|
|
607
|
+
return { boards, generic, problems };
|
|
531
608
|
}
|
|
532
609
|
//# sourceMappingURL=boards.js.map
|