@typecad/framework-zephyr 1.0.0-alpha.10 → 1.0.0-alpha.12
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.d.ts +25 -0
- package/dist/display/profiles.js +30 -0
- package/dist/display/touch-adapter.d.ts +3 -4
- package/dist/display/touch-adapter.js +119 -16
- package/dist/display/ui-adapter.js +308 -139
- package/dist/doctor.d.ts +3 -3
- package/dist/doctor.js +56 -29
- package/dist/dt-config/kconfig.d.ts +8 -1
- package/dist/dt-config/kconfig.js +40 -5
- package/dist/dt-config/overlay.d.ts +18 -1
- package/dist/dt-config/overlay.js +124 -26
- package/dist/framework.manifest.d.ts +29 -28
- package/dist/framework.manifest.js +46 -17
- 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/ble.js +3 -1
- 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.d.ts +4 -0
- package/dist/strategy.js +275 -35
- 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/index.js +39 -9
- package/dist/toolchain/scaffold.js +7 -2
- package/dist/toolchain/west-discover.d.ts +11 -3
- package/dist/toolchain/west-discover.js +84 -7
- 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 +53 -0
- package/src/display/touch-adapter.ts +119 -15
- package/src/display/ui-adapter.ts +311 -139
- package/src/doctor.ts +77 -56
- package/src/dt-config/kconfig.ts +45 -6
- package/src/dt-config/overlay.ts +159 -29
- package/src/framework.manifest.ts +47 -17
- package/src/index.ts +6 -0
- package/src/licenses.ts +425 -0
- package/src/lowering/ble.ts +3 -1
- 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 +271 -35
- package/src/toolchain/compat.ts +154 -145
- package/src/toolchain/env-check.ts +285 -0
- package/src/toolchain/index.ts +40 -9
- package/src/toolchain/scaffold.ts +7 -2
- package/src/toolchain/west-discover.ts +92 -9
- package/src/toolchain/west-spawn.ts +15 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Filesystem lowering — Zephyr FS API (littlefs on the storage partition)
|
|
3
|
+
//
|
|
4
|
+
// HAL `fs.*` (begin/read_text/write_text/exists/remove) maps onto Zephyr's
|
|
5
|
+
// <zephyr/fs/fs.h>. A littlefs filesystem is mounted at "/lfs" on the board's
|
|
6
|
+
// `storage_partition` fixed-partition (the same partition the ZMS settings
|
|
7
|
+
// backend uses for preferences — a program should not use both surfaces at
|
|
8
|
+
// once without dedicating separate partitions). The mount is lazy: it formats
|
|
9
|
+
// + remounts on first use when the partition is unformatted.
|
|
10
|
+
//
|
|
11
|
+
// The HAL paths are treated as paths WITHIN the filesystem: the shim joins the
|
|
12
|
+
// mount point, so fs.read_text("/data.txt") reads "/lfs/data.txt". This keeps
|
|
13
|
+
// the mount point an implementation detail.
|
|
14
|
+
//
|
|
15
|
+
// Requires Kconfig CONFIG_FILE_SYSTEM + CONFIG_FILE_SYSTEM_LITTLEFS (+ FLASH /
|
|
16
|
+
// FLASH_MAP) — emitted by the scaffold when the program uses fs.* — and the
|
|
17
|
+
// storage_partition node (added by the overlay).
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
/**
|
|
20
|
+
* Emit the littlefs mount + the typed helper API the lowering calls into.
|
|
21
|
+
* Called from shimLines when the program uses the filesystem. The helpers are
|
|
22
|
+
* `static` so multiple TUs that carry the shim (guarded by the include guard)
|
|
23
|
+
* do not collide.
|
|
24
|
+
*/
|
|
25
|
+
export function fsInitLines() {
|
|
26
|
+
return [
|
|
27
|
+
'// CUTTLEFISH_FS_BEGIN',
|
|
28
|
+
'static struct fs_mount_t __tc_fs_mp;',
|
|
29
|
+
'static bool __tc_fs_mounted = false;',
|
|
30
|
+
'',
|
|
31
|
+
'FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(__tc_fs_data);',
|
|
32
|
+
'static struct fs_mount_t __tc_fs_mp_init = {',
|
|
33
|
+
' .type = FS_LITTLEFS,',
|
|
34
|
+
' .fs_data = &__tc_fs_data,',
|
|
35
|
+
' .storage_dev = (void *)FIXED_PARTITION_ID(storage_partition),',
|
|
36
|
+
' .mnt_point = "/lfs",',
|
|
37
|
+
'};',
|
|
38
|
+
'',
|
|
39
|
+
'static void __tc_fs_ensure_mount(void) {',
|
|
40
|
+
' if (__tc_fs_mounted) return;',
|
|
41
|
+
' __tc_fs_mp = __tc_fs_mp_init;',
|
|
42
|
+
' int rc = fs_mount(&__tc_fs_mp);',
|
|
43
|
+
' if (rc == -ENODATA || rc == -EINVAL) {',
|
|
44
|
+
' // Unformatted partition — format it for littlefs, then remount.',
|
|
45
|
+
' (void)fs_mkfs(FS_LITTLEFS, static_cast<uintptr_t>(FIXED_PARTITION_ID(storage_partition)), NULL, 0);',
|
|
46
|
+
' (void)fs_mount(&__tc_fs_mp);',
|
|
47
|
+
' }',
|
|
48
|
+
' __tc_fs_mounted = true;',
|
|
49
|
+
'}',
|
|
50
|
+
'',
|
|
51
|
+
'// Join the mount point with the user path (paths are within the FS).',
|
|
52
|
+
'static const char* __tc_fs_path(const char* p) {',
|
|
53
|
+
' static char buf[128];',
|
|
54
|
+
' if (!p) return "/lfs";',
|
|
55
|
+
' const char* s = (p[0] == \'/\') ? p + 1 : p;',
|
|
56
|
+
' (void)snprintf(buf, sizeof(buf), "/lfs/%s", s);',
|
|
57
|
+
' return buf;',
|
|
58
|
+
'}',
|
|
59
|
+
'',
|
|
60
|
+
'static bool __tc_fs_begin(void) { __tc_fs_ensure_mount(); return true; }',
|
|
61
|
+
'',
|
|
62
|
+
'static const char* __tc_fs_read_text(const char* path) {',
|
|
63
|
+
' __tc_fs_ensure_mount();',
|
|
64
|
+
' static char buf[256];',
|
|
65
|
+
' buf[0] = 0;',
|
|
66
|
+
' struct fs_file_t f;',
|
|
67
|
+
' fs_file_t_init(&f);',
|
|
68
|
+
' if (fs_open(&f, __tc_fs_path(path), FS_O_READ) == 0) {',
|
|
69
|
+
' (void)fs_read(&f, buf, sizeof(buf) - 1);',
|
|
70
|
+
' buf[sizeof(buf) - 1] = 0;',
|
|
71
|
+
' (void)fs_close(&f);',
|
|
72
|
+
' }',
|
|
73
|
+
' return buf;',
|
|
74
|
+
'}',
|
|
75
|
+
'',
|
|
76
|
+
'static void __tc_fs_write_text(const char* path, const char* content) {',
|
|
77
|
+
' __tc_fs_ensure_mount();',
|
|
78
|
+
' struct fs_file_t f;',
|
|
79
|
+
' fs_file_t_init(&f);',
|
|
80
|
+
' if (fs_open(&f, __tc_fs_path(path), FS_O_WRITE | FS_O_CREATE | FS_O_TRUNC) == 0) {',
|
|
81
|
+
' (void)fs_write(&f, content, (content ? strlen(content) : 0));',
|
|
82
|
+
' (void)fs_close(&f);',
|
|
83
|
+
' }',
|
|
84
|
+
'}',
|
|
85
|
+
'',
|
|
86
|
+
'static bool __tc_fs_exists(const char* path) {',
|
|
87
|
+
' __tc_fs_ensure_mount();',
|
|
88
|
+
' struct fs_dirent ent;',
|
|
89
|
+
' return fs_stat(__tc_fs_path(path), &ent) == 0;',
|
|
90
|
+
'}',
|
|
91
|
+
'',
|
|
92
|
+
'static bool __tc_fs_remove(const char* path) {',
|
|
93
|
+
' __tc_fs_ensure_mount();',
|
|
94
|
+
' return fs_unlink(__tc_fs_path(path)) == 0;',
|
|
95
|
+
'}',
|
|
96
|
+
'// CUTTLEFISH_FS_END',
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Resolve a HAL fs.* op to Zephyr C++.
|
|
101
|
+
* Returns `{ code }` — each op's code is the body of the HAL FS class method.
|
|
102
|
+
*/
|
|
103
|
+
export function lowerFs(op) {
|
|
104
|
+
const o = op;
|
|
105
|
+
switch (op.operation) {
|
|
106
|
+
case 'fs.begin':
|
|
107
|
+
// No payload (the op carries only its discriminator).
|
|
108
|
+
return { code: 'return __tc_fs_begin();' };
|
|
109
|
+
case 'fs.read_text':
|
|
110
|
+
return { code: `return __tc_fs_read_text(${o.path});` };
|
|
111
|
+
case 'fs.write_text':
|
|
112
|
+
return { code: `__tc_fs_write_text(${o.path}, ${o.content});` };
|
|
113
|
+
case 'fs.exists':
|
|
114
|
+
return { code: `return __tc_fs_exists(${o.path});` };
|
|
115
|
+
case 'fs.remove':
|
|
116
|
+
return { code: `return __tc_fs_remove(${o.path});` };
|
|
117
|
+
default:
|
|
118
|
+
throw new Error(`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
119
|
+
`Open an issue or use rawCpp() to emit it manually.`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
2
|
+
import type { ZephyrChipDescriptor } from '../chips/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Emit the per-instance counter device handles + frequency/callback state.
|
|
5
|
+
* Called from shimLines when the program uses hardware timers.
|
|
6
|
+
*/
|
|
7
|
+
export declare function hwtimerInitLines(chip: ZephyrChipDescriptor): string[];
|
|
8
|
+
/**
|
|
9
|
+
* Resolve a HAL hwtimer.* op to Zephyr C++.
|
|
10
|
+
* Returns `{ code }` for statement ops.
|
|
11
|
+
*/
|
|
12
|
+
export declare function lowerHwtimer(op: HALOpIR, chip: ZephyrChipDescriptor): {
|
|
13
|
+
code?: string;
|
|
14
|
+
expression?: string;
|
|
15
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Hardware-timer lowering — Zephyr counter API
|
|
3
|
+
//
|
|
4
|
+
// HAL `hwtimer.*` (instance → frequency/overflow/start/stop) maps onto Zephyr's
|
|
5
|
+
// counter driver (<zephyr/drivers/counter.h>). A chip declares the counter
|
|
6
|
+
// devices it exposes (e.g. nRF RTC1 — RTC0 is kernel-owned) via
|
|
7
|
+
// `hwtimer.controllers[instance].nodeLabel`.
|
|
8
|
+
//
|
|
9
|
+
// Frequency model: a Zephyr counter has a fixed clock; the HAL
|
|
10
|
+
// set_frequency(hz) is realized as a top value of counter_freq/hz with an alarm
|
|
11
|
+
// callback (the on_overflow handler). start() arms both the top value and the
|
|
12
|
+
// callback so the call order (setFrequency → onOverflow → start, or any
|
|
13
|
+
// permutation) is handled uniformly.
|
|
14
|
+
//
|
|
15
|
+
// Targets without a free counter omit `hwtimer`; usage lowers to a comment and
|
|
16
|
+
// profileDiagnostics flags it. The JS setInterval/setTimeout polyfill
|
|
17
|
+
// (k_timer) is a separate surface and is unaffected.
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
/** Per-instance emitted symbol stems. */
|
|
20
|
+
function devVar(instance) {
|
|
21
|
+
return `__tc_hw_dev_${instance}`;
|
|
22
|
+
}
|
|
23
|
+
function hzVar(instance) {
|
|
24
|
+
return `__tc_hw_hz_${instance}`;
|
|
25
|
+
}
|
|
26
|
+
function cbVar(instance) {
|
|
27
|
+
return `__tc_hw_cb_${instance}`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Emit the per-instance counter device handles + frequency/callback state.
|
|
31
|
+
* Called from shimLines when the program uses hardware timers.
|
|
32
|
+
*/
|
|
33
|
+
export function hwtimerInitLines(chip) {
|
|
34
|
+
const controllers = chip.hwtimer?.controllers ?? [];
|
|
35
|
+
if (controllers.length === 0)
|
|
36
|
+
return [];
|
|
37
|
+
const lines = ['// CUTTLEFISH_HWTIMER_BEGIN'];
|
|
38
|
+
controllers.forEach((c, i) => {
|
|
39
|
+
lines.push(`static const struct device* ${devVar(i)} = DEVICE_DT_GET(DT_NODELABEL(${c.nodeLabel}));`, `static uint32_t ${hzVar(i)} = 1;`, `static counter_top_callback_t ${cbVar(i)} = NULL;`);
|
|
40
|
+
});
|
|
41
|
+
lines.push('// CUTTLEFISH_HWTIMER_END');
|
|
42
|
+
return lines;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolve a HAL hwtimer.* op to Zephyr C++.
|
|
46
|
+
* Returns `{ code }` for statement ops.
|
|
47
|
+
*/
|
|
48
|
+
export function lowerHwtimer(op, chip) {
|
|
49
|
+
const o = op;
|
|
50
|
+
const controllers = chip.hwtimer?.controllers ?? [];
|
|
51
|
+
// No counter on this target. Comment + (in profileDiagnostics) a clear error.
|
|
52
|
+
if (controllers.length === 0) {
|
|
53
|
+
return { code: `/* hwtimer instance ${o.instance}: no counter device on ${chip.id} */` };
|
|
54
|
+
}
|
|
55
|
+
const instance = typeof o.instance === 'number' ? o.instance : parseInt(String(o.instance), 10);
|
|
56
|
+
if (isNaN(instance) || instance < 0 || instance >= controllers.length) {
|
|
57
|
+
return { code: `/* hwtimer instance ${o.instance}: out of range on ${chip.id} */` };
|
|
58
|
+
}
|
|
59
|
+
switch (op.operation) {
|
|
60
|
+
case 'hwtimer.set_frequency':
|
|
61
|
+
return { code: `${hzVar(instance)} = ${o.hz};` };
|
|
62
|
+
case 'hwtimer.on_overflow':
|
|
63
|
+
return { code: `${cbVar(instance)} = (${o.handler});` };
|
|
64
|
+
case 'hwtimer.start':
|
|
65
|
+
// Arm the top value (counter_freq / desired_hz) + the overflow callback,
|
|
66
|
+
// then start the counter. Doing both here handles any call order — the
|
|
67
|
+
// HAL typical sequence (setFrequency → onOverflow → start) and permutations.
|
|
68
|
+
return {
|
|
69
|
+
code: [
|
|
70
|
+
`{`,
|
|
71
|
+
` uint32_t __f = counter_get_frequency(${devVar(instance)});`,
|
|
72
|
+
` uint32_t __top = __f ? (__f / ${hzVar(instance)}) : 0U;`,
|
|
73
|
+
` if (__top > 0U) { (void)counter_set_top_value(${devVar(instance)}, __top, ${cbVar(instance)}, NULL); }`,
|
|
74
|
+
` (void)counter_start(${devVar(instance)});`,
|
|
75
|
+
`}`,
|
|
76
|
+
].join(' '),
|
|
77
|
+
};
|
|
78
|
+
case 'hwtimer.stop':
|
|
79
|
+
return { code: `(void)counter_stop(${devVar(instance)});` };
|
|
80
|
+
default:
|
|
81
|
+
throw new Error(`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
82
|
+
`Open an issue or use rawCpp() to emit it manually.`);
|
|
83
|
+
}
|
|
84
|
+
}
|
package/dist/lowering/index.d.ts
CHANGED
|
@@ -18,7 +18,10 @@ import { lowerMqtt } from './mqtt.js';
|
|
|
18
18
|
import { lowerPreferences } from './preferences.js';
|
|
19
19
|
import { lowerBoard } from './board.js';
|
|
20
20
|
import { lowerRandom } from './random.js';
|
|
21
|
-
|
|
21
|
+
import { lowerDac } from './dac.js';
|
|
22
|
+
import { lowerFs } from './fs.js';
|
|
23
|
+
import { lowerHwtimer } from './hwtimer.js';
|
|
24
|
+
export { lowerGpio, lowerTiming, lowerAdc, lowerPwm, lowerI2c, lowerSpi, lowerUart, lowerInterrupt, lowerWdt, lowerPower, lowerTone, lowerPulseOrShift, lowerBle, lowerWifi, lowerHttp, lowerMqtt, lowerPreferences, lowerBoard, lowerRandom, lowerDac, lowerFs, lowerHwtimer, };
|
|
22
25
|
/**
|
|
23
26
|
* Lower a HAL op to Zephyr C++. Returns undefined for unsupported categories
|
|
24
27
|
* (mirrors lowerHalOp in framework-esp32/src/lowering/index.ts).
|
package/dist/lowering/index.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
//
|
|
4
4
|
// Routes a HALOpIR to the per-category lowering module by category prefix
|
|
5
5
|
// (e.g. 'gpio.write' → lowerGpio). Returns undefined for categories the
|
|
6
|
-
// framework does not lower (display/
|
|
7
|
-
//
|
|
6
|
+
// framework does not lower (display/mdns/ota/rmt/
|
|
7
|
+
// capacitive/temp/espnow/crypto/i2s/twai/usb/eth/pcnt/mcpwm — see
|
|
8
8
|
// the manifest), so the transpiler falls back and the manifest validator
|
|
9
9
|
// cross-checks the unsupported categories. (board.* is registered below but is
|
|
10
10
|
// a dead-letter — its values are constant-folded at IR-build time.)
|
|
@@ -36,7 +36,10 @@ import { lowerMqtt } from './mqtt.js';
|
|
|
36
36
|
import { lowerPreferences } from './preferences.js';
|
|
37
37
|
import { lowerBoard } from './board.js';
|
|
38
38
|
import { lowerRandom } from './random.js';
|
|
39
|
-
|
|
39
|
+
import { lowerDac } from './dac.js';
|
|
40
|
+
import { lowerFs } from './fs.js';
|
|
41
|
+
import { lowerHwtimer } from './hwtimer.js';
|
|
42
|
+
export { lowerGpio, lowerTiming, lowerAdc, lowerPwm, lowerI2c, lowerSpi, lowerUart, lowerInterrupt, lowerWdt, lowerPower, lowerTone, lowerPulseOrShift, lowerBle, lowerWifi, lowerHttp, lowerMqtt, lowerPreferences, lowerBoard, lowerRandom, lowerDac, lowerFs, lowerHwtimer, };
|
|
40
43
|
/**
|
|
41
44
|
* Lower a HAL op to Zephyr C++. Returns undefined for unsupported categories
|
|
42
45
|
* (mirrors lowerHalOp in framework-esp32/src/lowering/index.ts).
|
|
@@ -51,6 +54,8 @@ export function lowerHalOp(op) {
|
|
|
51
54
|
return lowerAdc(op, chip);
|
|
52
55
|
if (op.operation.startsWith('pwm.'))
|
|
53
56
|
return lowerPwm(op, chip);
|
|
57
|
+
if (op.operation.startsWith('dac.'))
|
|
58
|
+
return lowerDac(op, chip);
|
|
54
59
|
if (op.operation.startsWith('i2c.'))
|
|
55
60
|
return lowerI2c(op, chip);
|
|
56
61
|
if (op.operation.startsWith('spi.'))
|
|
@@ -61,6 +66,8 @@ export function lowerHalOp(op) {
|
|
|
61
66
|
return lowerInterrupt(op, chip);
|
|
62
67
|
if (op.operation.startsWith('wdt.'))
|
|
63
68
|
return lowerWdt(op);
|
|
69
|
+
if (op.operation.startsWith('hwtimer.'))
|
|
70
|
+
return lowerHwtimer(op, chip);
|
|
64
71
|
if (op.operation.startsWith('power.'))
|
|
65
72
|
return lowerPower(op);
|
|
66
73
|
if (op.operation.startsWith('tone.'))
|
|
@@ -80,6 +87,8 @@ export function lowerHalOp(op) {
|
|
|
80
87
|
return lowerMqtt(op);
|
|
81
88
|
if (op.operation.startsWith('preferences.'))
|
|
82
89
|
return lowerPreferences(op);
|
|
90
|
+
if (op.operation.startsWith('fs.'))
|
|
91
|
+
return lowerFs(op);
|
|
83
92
|
// board.resolve is constant-folded at IR-build time; lowerBoard is the
|
|
84
93
|
// dead-letter reached only on an unresolvable path.
|
|
85
94
|
if (op.operation.startsWith('board.'))
|
package/dist/strategy.d.ts
CHANGED
|
@@ -78,6 +78,10 @@ export declare class ZephyrStrategy implements PlatformStrategy {
|
|
|
78
78
|
passthroughMacroNames(): ReadonlySet<string>;
|
|
79
79
|
apiReservedEnumNames(): ReadonlySet<string>;
|
|
80
80
|
apiReservedEnumGuard(): string;
|
|
81
|
+
isrUnsafeOperations(): Map<string, {
|
|
82
|
+
reason: string;
|
|
83
|
+
severity: 'warning' | 'info';
|
|
84
|
+
}>;
|
|
81
85
|
ambientTypeDeclarations(): string[];
|
|
82
86
|
needsIostream(): boolean;
|
|
83
87
|
needsStdString(): boolean;
|