@typecad/framework-zephyr 1.0.0-alpha.10 → 1.0.0-alpha.11
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/dist/chips/esp32.js +12 -0
- package/dist/chips/types.d.ts +30 -0
- package/dist/chips/xiao-ble.js +6 -0
- package/dist/display/gfx.d.ts +12 -3
- package/dist/display/gfx.js +130 -17
- package/dist/display/profiles.js +13 -0
- package/dist/display/ui-adapter.js +6 -0
- package/dist/doctor.d.ts +3 -3
- package/dist/doctor.js +56 -29
- package/dist/dt-config/kconfig.d.ts +3 -0
- package/dist/dt-config/kconfig.js +18 -0
- package/dist/dt-config/overlay.js +5 -0
- package/dist/framework.manifest.js +37 -14
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/licenses.d.ts +59 -0
- package/dist/licenses.js +347 -0
- package/dist/lowering/dac.d.ts +15 -0
- package/dist/lowering/dac.js +69 -0
- package/dist/lowering/fs.d.ts +16 -0
- package/dist/lowering/fs.js +121 -0
- package/dist/lowering/hwtimer.d.ts +15 -0
- package/dist/lowering/hwtimer.js +84 -0
- package/dist/lowering/index.d.ts +4 -1
- package/dist/lowering/index.js +12 -3
- package/dist/strategy.js +186 -14
- package/dist/toolchain/compat.js +10 -1
- package/dist/toolchain/env-check.d.ts +93 -0
- package/dist/toolchain/env-check.js +190 -0
- package/dist/toolchain/scaffold.js +3 -0
- package/dist/toolchain/west-discover.d.ts +11 -3
- package/dist/toolchain/west-discover.js +80 -6
- package/dist/toolchain/west-spawn.js +15 -0
- package/package.json +4 -4
- package/src/chips/esp32.ts +12 -0
- package/src/chips/types.ts +29 -0
- package/src/chips/xiao-ble.ts +6 -0
- package/src/display/gfx.ts +135 -19
- package/src/display/profiles.ts +13 -0
- package/src/display/ui-adapter.ts +5 -0
- package/src/doctor.ts +77 -56
- package/src/dt-config/kconfig.ts +19 -0
- package/src/dt-config/overlay.ts +5 -0
- package/src/framework.manifest.ts +38 -14
- package/src/index.ts +6 -0
- package/src/licenses.ts +425 -0
- package/src/lowering/dac.ts +82 -0
- package/src/lowering/fs.ts +127 -0
- package/src/lowering/hwtimer.ts +101 -0
- package/src/lowering/index.ts +9 -2
- package/src/strategy.ts +180 -14
- package/src/toolchain/compat.ts +154 -145
- package/src/toolchain/env-check.ts +285 -0
- package/src/toolchain/scaffold.ts +3 -0
- package/src/toolchain/west-discover.ts +88 -8
- package/src/toolchain/west-spawn.ts +15 -0
package/src/display/profiles.ts
CHANGED
|
@@ -56,6 +56,19 @@ export const ZEPHYR_DISPLAY_PROFILES: Record<string, ZephyrDisplayProfile> = {
|
|
|
56
56
|
rotation: 1,
|
|
57
57
|
backlight: 'backlight',
|
|
58
58
|
},
|
|
59
|
+
'ssd1306-zephyr': {
|
|
60
|
+
// Monochrome OLED (SSD1306-class, 128x64, 1bpp). Driven through Zephyr's
|
|
61
|
+
// generic display API (the ssd1306 driver + a DT display node). The GFX
|
|
62
|
+
// runtime (gfx.ts mono branch) keeps a full page-framebuffer and pushes it
|
|
63
|
+
// on display_flush — the standard model for page-buffered OLEDs. Direct
|
|
64
|
+
// display.* ops only (no @typecad/ui CuttlefishGFX rendering on mono).
|
|
65
|
+
driver: 'ssd1306-zephyr',
|
|
66
|
+
dtLabel: 'display0',
|
|
67
|
+
width: 128,
|
|
68
|
+
height: 64,
|
|
69
|
+
colorFormat: 'mono',
|
|
70
|
+
rotation: 0,
|
|
71
|
+
},
|
|
59
72
|
};
|
|
60
73
|
|
|
61
74
|
/** The default profile used when resolveDisplayOp is probed without a display.init. */
|
|
@@ -551,6 +551,11 @@ static inline void display_targetPrint(CuttlefishDisplayTarget* t, const char* s
|
|
|
551
551
|
export const zephyrDisplayAdapterGenerator: DisplayAdapterGenerator = (display) => {
|
|
552
552
|
const profile = ZEPHYR_DISPLAY_PROFILES[display.driver];
|
|
553
553
|
if (!profile) return undefined as unknown as DisplayAdapterCode;
|
|
554
|
+
// The UI adapter is RGB565/SPI (TFT) only. Monochrome panels (OLED) use the
|
|
555
|
+
// direct display.* GFX runtime (gfx.ts mono branch) — there is no
|
|
556
|
+
// CuttlefishGFX UI rendering path for mono. Decline so cuttlefish does not
|
|
557
|
+
// emit an incompatible RGB565 adapter for a mono profile.
|
|
558
|
+
if (profile.colorFormat === 'mono') return undefined as unknown as DisplayAdapterCode;
|
|
554
559
|
return zephyrUiDisplayAdapter(profile, {
|
|
555
560
|
scanlineSync: display.scanlineSync,
|
|
556
561
|
miso: display.spiPins?.miso,
|
package/src/doctor.ts
CHANGED
|
@@ -1,56 +1,77 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// @typecad/framework-zephyr — Zephyr environment doctor
|
|
3
|
-
//
|
|
4
|
-
// `cuttlefish doctor` (Zephyr framework) — verify the
|
|
5
|
-
//
|
|
6
|
-
// the configured board target
|
|
7
|
-
// environment is OK, non-zero otherwise. Mirrors framework-arduino's
|
|
8
|
-
// shape (dispatched via the framework's `doctor` export)
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
ui.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// @typecad/framework-zephyr — Zephyr environment doctor
|
|
3
|
+
//
|
|
4
|
+
// `cuttlefish doctor` (Zephyr framework) — verify west (the Zephyr build tool)
|
|
5
|
+
// is installed + responsive, the Zephyr RTOS is inside the framework's declared
|
|
6
|
+
// compat range, and the configured board target exists in the checkout. Exits 0
|
|
7
|
+
// if the environment is OK, non-zero otherwise. Mirrors framework-arduino's
|
|
8
|
+
// doctor shape (dispatched via the framework's `doctor` export) and reuses
|
|
9
|
+
// checkZephyrEnv so the detection logic can be shared with the build/test gates.
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
import * as ui from '@typecad/cuttlefish/utils/ui';
|
|
13
|
+
import { loadCuttlefishConfig } from '@typecad/cuttlefish/config-loader';
|
|
14
|
+
import { checkZephyrEnv } from './toolchain/env-check.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Verify west is installed + responsive, the Zephyr RTOS is inside the supported
|
|
18
|
+
* range, and the configured board target exists in the checkout. Sets
|
|
19
|
+
* process.exitCode = 1 on failure. Thin presenter over checkZephyrEnv.
|
|
20
|
+
*/
|
|
21
|
+
export function runDoctor(): void {
|
|
22
|
+
ui.printHeader();
|
|
23
|
+
ui.printStep('Checking Zephyr environment...');
|
|
24
|
+
|
|
25
|
+
const config = loadCuttlefishConfig(process.cwd());
|
|
26
|
+
const buildTarget = config?.buildTarget;
|
|
27
|
+
|
|
28
|
+
const result = checkZephyrEnv(buildTarget);
|
|
29
|
+
const c = result.check;
|
|
30
|
+
|
|
31
|
+
// west (the Zephyr build tool) — the analog of arduino-cli presence.
|
|
32
|
+
if (c.westFound) {
|
|
33
|
+
const ver = c.westVersion ?? 'found';
|
|
34
|
+
const src = c.westSource ? ` (${c.westSource})` : '';
|
|
35
|
+
ui.printInfo(`west ............. ${ver} ✓${src}`);
|
|
36
|
+
} else {
|
|
37
|
+
ui.printError('west ............. NOT FOUND');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Zephyr RTOS version + declared compat range.
|
|
41
|
+
ui.printInfo(`ZEPHYR_BASE ...... ${c.zephyrBase ?? '(not set)'}`);
|
|
42
|
+
ui.printInfo(`Zephyr version .. ${c.zephyrVersion ?? 'unknown (could not read ZEPHYR_BASE/VERSION)'}`);
|
|
43
|
+
ui.printInfo(`Supported range . ${c.compatRange ?? '(none declared)'}`);
|
|
44
|
+
|
|
45
|
+
if (c.compatStatus === 'out-of-range') {
|
|
46
|
+
ui.printError(`Zephyr ${c.zephyrVersion} is OUTSIDE the supported range (${c.compatRange}).`);
|
|
47
|
+
} else if (c.compatStatus === 'undetectable') {
|
|
48
|
+
ui.printWarning('Could not detect the Zephyr version (is ZEPHYR_BASE set?) — compat check skipped.');
|
|
49
|
+
} else {
|
|
50
|
+
ui.printInfo('Zephyr compat ... OK');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Board target — the analog of the Arduino core presence check.
|
|
54
|
+
if (buildTarget) {
|
|
55
|
+
const resolved = c.resolvedBoardTarget ?? buildTarget;
|
|
56
|
+
const arrow = resolved === buildTarget ? '' : ` → ${resolved}`;
|
|
57
|
+
if (c.boardTargetSupported === false) {
|
|
58
|
+
ui.printError(`Board target .... ${buildTarget}${arrow} NOT found in this Zephyr checkout`);
|
|
59
|
+
ui.printInfo(' → check the board id, or run: west boards');
|
|
60
|
+
} else if (c.boardTargetSupported === undefined) {
|
|
61
|
+
ui.printInfo(`Board target .... ${buildTarget}${arrow}`);
|
|
62
|
+
ui.printInfo('(could not verify board presence — no ZEPHYR_BASE boards/ tree found)');
|
|
63
|
+
} else {
|
|
64
|
+
ui.printInfo(`Board target .... ${buildTarget}${arrow}`);
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
ui.printInfo('(no buildTarget in cuttlefish.config.ts — skipping board check)');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Exit code — mirrors framework-arduino's doctor.
|
|
71
|
+
if (result.ok) {
|
|
72
|
+
ui.printSuccess('Environment OK');
|
|
73
|
+
return; // exitCode stays unset => 0
|
|
74
|
+
}
|
|
75
|
+
for (const line of result.messages) ui.printInfo(line);
|
|
76
|
+
process.exitCode = 1;
|
|
77
|
+
}
|
package/src/dt-config/kconfig.ts
CHANGED
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
export interface KconfigUsage {
|
|
12
12
|
usesAdc?: boolean;
|
|
13
13
|
usesPwm?: boolean;
|
|
14
|
+
usesDac?: boolean;
|
|
15
|
+
usesFS?: boolean;
|
|
16
|
+
usesHwtimer?: boolean;
|
|
14
17
|
usesI2c?: boolean;
|
|
15
18
|
usesSpi?: boolean;
|
|
16
19
|
usesUart?: boolean;
|
|
@@ -49,9 +52,12 @@ export function resolveKconfigFragments(
|
|
|
49
52
|
|
|
50
53
|
if (usage.usesAdc) m.set('CONFIG_ADC', 'y');
|
|
51
54
|
if (usage.usesPwm) m.set('CONFIG_PWM', 'y');
|
|
55
|
+
if (usage.usesDac) m.set('CONFIG_DAC', 'y');
|
|
52
56
|
if (usage.usesI2c) m.set('CONFIG_I2C', 'y');
|
|
53
57
|
if (usage.usesSpi) m.set('CONFIG_SPI', 'y');
|
|
54
58
|
if (usage.usesWdt) m.set('CONFIG_WATCHDOG', 'y');
|
|
59
|
+
// Hardware timers via the counter driver.
|
|
60
|
+
if (usage.usesHwtimer) m.set('CONFIG_COUNTER', 'y');
|
|
55
61
|
if (usage.usesDisplay) {
|
|
56
62
|
m.set('CONFIG_DISPLAY', 'y');
|
|
57
63
|
m.set('CONFIG_SPI', 'y');
|
|
@@ -257,6 +263,19 @@ export function resolveKconfigFragments(
|
|
|
257
263
|
m.set('CONFIG_SETTINGS', 'y');
|
|
258
264
|
m.set('CONFIG_SETTINGS_ZMS', 'y');
|
|
259
265
|
}
|
|
266
|
+
// Filesystem: littlefs on the storage partition. CONFIG_FILE_SYSTEM_LITTLEFS
|
|
267
|
+
// selects the littlefs backend but NOT FLASH/FLASH_MAP (the partition lookup
|
|
268
|
+
// needs them), so all three are set explicitly — same shape as the
|
|
269
|
+
// preferences/ZMS block. The overlay points the storage_partition at the FS
|
|
270
|
+
// (see dt-config/overlay.ts). NOTE: a program using BOTH fs.* and
|
|
271
|
+
// preferences.* shares the one storage_partition between littlefs and ZMS —
|
|
272
|
+
// dedicate separate partitions if both are needed (the manifest flags this).
|
|
273
|
+
if (usage.usesFS) {
|
|
274
|
+
m.set('CONFIG_FLASH', 'y');
|
|
275
|
+
m.set('CONFIG_FLASH_MAP', 'y');
|
|
276
|
+
m.set('CONFIG_FILE_SYSTEM', 'y');
|
|
277
|
+
m.set('CONFIG_FILE_SYSTEM_LITTLEFS', 'y');
|
|
278
|
+
}
|
|
260
279
|
// usesUart: the board enables the console UART by default; the overlay (not
|
|
261
280
|
// Kconfig) is where a UART node would be enabled, so no symbol here.
|
|
262
281
|
// Random: <zephyr/random/random.h> sys_rand_get is backed by the random
|
package/src/dt-config/overlay.ts
CHANGED
|
@@ -84,6 +84,11 @@ export function generateOverlay(
|
|
|
84
84
|
if (usage.usesUart && chip.uart) {
|
|
85
85
|
for (const c of chip.uart.controllers) block(c.nodeLabel);
|
|
86
86
|
}
|
|
87
|
+
// DAC: enable the chip's DAC device node when the program uses dac.*. The
|
|
88
|
+
// lowering references DEVICE_DT_GET(DT_NODELABEL(<dac.device>)).
|
|
89
|
+
if (usage.usesDac && chip.dac) {
|
|
90
|
+
block(chip.dac.device);
|
|
91
|
+
}
|
|
87
92
|
if (display) {
|
|
88
93
|
// Emit a full display DT node definition. Boards like the ESP32 devkit
|
|
89
94
|
// have no display node in their base DT, so a bare `&display0 { status }`
|
|
@@ -113,9 +113,13 @@ export default defineFrameworkManifest({
|
|
|
113
113
|
},
|
|
114
114
|
},
|
|
115
115
|
dac: {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
// ESP32 DAC (2× 8-bit channels on GPIO25/26) via the Zephyr DAC driver
|
|
117
|
+
// (dac_channel_setup + dac_write_value). nRF52840 / ESP32-S3 have no DAC;
|
|
118
|
+
// usage there lowers to a comment and profileDiagnostics flags it
|
|
119
|
+
// (zephyr-dac-pin-unavailable).
|
|
120
|
+
supported: true,
|
|
121
|
+
partialCoverage: true,
|
|
122
|
+
ops: { 'dac.write': 'supported' },
|
|
119
123
|
},
|
|
120
124
|
interrupts: {
|
|
121
125
|
supported: true,
|
|
@@ -287,7 +291,7 @@ export default defineFrameworkManifest({
|
|
|
287
291
|
supported: true,
|
|
288
292
|
partialCoverage: false,
|
|
289
293
|
unsupportedReason: undefined,
|
|
290
|
-
drivers: ['ili9341-zephyr', 'st7796-zephyr'],
|
|
294
|
+
drivers: ['ili9341-zephyr', 'st7796-zephyr', 'ssd1306-zephyr'],
|
|
291
295
|
colorFormat: 'rgb565',
|
|
292
296
|
ops: {
|
|
293
297
|
'display.init': 'supported',
|
|
@@ -370,10 +374,17 @@ export default defineFrameworkManifest({
|
|
|
370
374
|
},
|
|
371
375
|
},
|
|
372
376
|
fs: {
|
|
373
|
-
|
|
374
|
-
|
|
377
|
+
// littlefs on the board's storage_partition, via <zephyr/fs/fs.h>. The
|
|
378
|
+
// shim mounts at /lfs lazily (formats on first use) and the HAL paths are
|
|
379
|
+
// treated as paths within the filesystem. Requires CONFIG_FILE_SYSTEM +
|
|
380
|
+
// CONFIG_FILE_SYSTEM_LITTLEFS (emitted by the scaffold when fs.* is used)
|
|
381
|
+
// and the storage_partition node.
|
|
382
|
+
supported: true,
|
|
375
383
|
partialCoverage: false,
|
|
376
|
-
ops:
|
|
384
|
+
ops: {
|
|
385
|
+
'fs.begin': 'supported', 'fs.read_text': 'supported', 'fs.write_text': 'supported',
|
|
386
|
+
'fs.exists': 'supported', 'fs.remove': 'supported',
|
|
387
|
+
},
|
|
377
388
|
},
|
|
378
389
|
mdns: {
|
|
379
390
|
supported: false,
|
|
@@ -410,10 +421,17 @@ export default defineFrameworkManifest({
|
|
|
410
421
|
ops: { 'temp.read': 'unsupported' },
|
|
411
422
|
},
|
|
412
423
|
hwtimer: {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
424
|
+
// Hardware timers via the Zephyr counter driver (<zephyr/drivers/counter.h>).
|
|
425
|
+
// set_frequency → top value (counter_freq/hz) + on_overflow callback;
|
|
426
|
+
// start arms both; stop halts. A chip declares its free counters
|
|
427
|
+
// (e.g. nRF RTC1; RTC0 is kernel-owned). This is distinct from the JS
|
|
428
|
+
// setInterval/setTimeout k_timer polyfill, which is unaffected.
|
|
429
|
+
supported: true,
|
|
430
|
+
partialCoverage: true,
|
|
431
|
+
ops: {
|
|
432
|
+
'hwtimer.set_frequency': 'supported', 'hwtimer.on_overflow': 'supported',
|
|
433
|
+
'hwtimer.start': 'supported', 'hwtimer.stop': 'supported',
|
|
434
|
+
},
|
|
417
435
|
},
|
|
418
436
|
capacitive: {
|
|
419
437
|
// FT6336U capacitive touch is handled via the strategy-owned touch adapter
|
|
@@ -481,6 +499,8 @@ export default defineFrameworkManifest({
|
|
|
481
499
|
polyfills: {
|
|
482
500
|
emitted: [
|
|
483
501
|
{ id: 'cuttlefish_halt', domain: 'standard', notes: 'Mapped to a k_msleep halt loop (exceptions disabled)' },
|
|
502
|
+
{ id: 'string_methods', domain: 'embedded', notes: 'STL-free __tc_* string helpers (const char*, inline ASCII case conv, <cstring> only)' },
|
|
503
|
+
{ id: 'static_array', domain: 'embedded', notes: 'STL-free __tc_StaticArray<T,N> wrapper for no-<vector> mutated/struct array literals' },
|
|
484
504
|
{ id: 'timer_methods', domain: 'embedded', notes: 'k_timer + k_work pool (system workqueue); callbacks run in thread context' },
|
|
485
505
|
{ id: 'async_runtime', domain: 'embedded', notes: 'Heap-free static Promise/microtask runtime (generateStaticAsyncRuntime), pumped in loop()' },
|
|
486
506
|
],
|
|
@@ -537,9 +557,9 @@ export default defineFrameworkManifest({
|
|
|
537
557
|
// pure string-snapshot tests (no hardware); they are the safety net that
|
|
538
558
|
// catches regressions like silent pull-resistor / interrupt no-ops.
|
|
539
559
|
halResolutionTests: [
|
|
540
|
-
'adc', 'ble', 'board', 'dac', '
|
|
541
|
-
'
|
|
542
|
-
'uart', 'wdt', 'worker',
|
|
560
|
+
'adc', 'ble', 'board', 'dac', 'fs', 'gpio', 'http', 'hwtimer', 'i2c',
|
|
561
|
+
'interrupts', 'mqtt', 'power', 'preferences', 'pulse', 'pwm', 'random',
|
|
562
|
+
'spi', 'timing', 'tone', 'uart', 'wdt', 'worker',
|
|
543
563
|
],
|
|
544
564
|
},
|
|
545
565
|
|
|
@@ -555,4 +575,8 @@ export default defineFrameworkManifest({
|
|
|
555
575
|
// `cuttlefish doctor` prints the detected Zephyr version + compat result and
|
|
556
576
|
// previews how the configured board target resolves for that version.
|
|
557
577
|
doctor: { available: true },
|
|
578
|
+
|
|
579
|
+
// `cuttlefish licenses` enumerates the Zephyr kernel + west manifest projects
|
|
580
|
+
// and resolves each one's SPDX license (mirrors framework-arduino).
|
|
581
|
+
licenses: { available: true },
|
|
558
582
|
});
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,12 @@ export { Toolchain } from './toolchain/index.js';
|
|
|
16
16
|
// mod.doctor (see framework-package.ts).
|
|
17
17
|
export { runDoctor as doctor } from './doctor.js';
|
|
18
18
|
|
|
19
|
+
// `cuttlefish licenses` — enumerate the Zephyr kernel + west manifest projects
|
|
20
|
+
// and resolve each one's SPDX license. Re-exported under the dispatcher-facing
|
|
21
|
+
// alias `licenses` so the loader picks it up as mod.licenses (see
|
|
22
|
+
// framework-package.ts). Mirrors framework-arduino's presenter.
|
|
23
|
+
export { runLicensesPresenter as licenses } from './licenses.js';
|
|
24
|
+
|
|
19
25
|
// Chip descriptor registry (for downstream tooling / additional boards).
|
|
20
26
|
export {
|
|
21
27
|
chipForTarget,
|