@typecad/framework-zephyr 1.0.0-alpha.15 → 1.0.0-alpha.18
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/LICENSE +202 -21
- package/README.md +49 -87
- package/dist/as-built.d.ts +2 -2
- package/dist/as-built.js +2 -2
- package/dist/boardgen.d.ts +1 -9
- package/dist/boardgen.js +228 -45
- package/dist/chips/types.d.ts +1 -1
- package/dist/debug-codegen.js +1 -1
- package/dist/display/touch-adapter.js +1 -1
- package/dist/display/ui-adapter.js +549 -549
- package/dist/doctor.js +4 -4
- package/dist/dt-config/custom-board.js +2 -2
- package/dist/dt-config/kconfig.js +18 -12
- package/dist/dt-config/overlay.d.ts +2 -2
- package/dist/dt-config/overlay.js +2 -2
- package/dist/framework.manifest.d.ts +3 -3
- package/dist/framework.manifest.js +10 -7
- package/dist/index.js +5 -5
- package/dist/licenses.d.ts +2 -2
- package/dist/licenses.js +8 -8
- package/dist/lowering/fs.js +1 -1
- package/dist/lowering/gpio.js +0 -32
- package/dist/lowering/http.js +264 -32
- package/dist/lowering/i2c.js +0 -8
- package/dist/lowering/interrupts.js +6 -0
- package/dist/lowering/mqtt.js +110 -8
- package/dist/lowering/usb.js +11 -11
- package/dist/lowering/wdt.js +2 -29
- package/dist/sdk/board-catalog-sync.d.ts +1 -3
- package/dist/sdk/board-catalog-sync.js +4 -10
- package/dist/strategy.d.ts +22 -44
- package/dist/strategy.js +152 -155
- package/dist/tmp-probe.d.ts +2 -0
- package/dist/tmp-probe.js +9 -0
- package/dist/toolchain/debug-config.d.ts +50 -90
- package/dist/toolchain/debug-config.js +241 -502
- package/dist/toolchain/env-check.d.ts +1 -3
- package/dist/toolchain/env-check.js +2 -7
- package/dist/toolchain/index.d.ts +65 -2
- package/dist/toolchain/index.js +432 -55
- package/dist/toolchain/runners.d.ts +16 -0
- package/dist/toolchain/runners.js +75 -0
- package/dist/toolchain/scaffold.d.ts +1 -1
- package/dist/toolchain/scaffold.js +12 -12
- package/dist/toolchain/west-discover.d.ts +6 -0
- package/dist/toolchain/west-discover.js +36 -13
- package/dist/toolchain/west-spawn.js +8 -2
- package/installer/README.md +328 -328
- package/installer/install.sh +2 -2
- package/installer/templates/project/.typecad/activate-zephyr.ps1 +1 -1
- package/installer/templates/project/.typecad/activate-zephyr.sh +1 -1
- package/installer/templates/project/.vscode/settings.json +1 -1
- package/installer/templates/project/README.md +2 -2
- package/package.json +5 -5
- package/src/as-built.ts +206 -206
- package/src/boardgen.ts +214 -48
- package/src/chips/types.ts +567 -567
- package/src/display/touch-adapter.ts +204 -204
- package/src/display/ui-adapter.ts +781 -781
- package/src/doctor.ts +4 -4
- package/src/dt-config/custom-board.ts +2 -2
- package/src/dt-config/kconfig.ts +18 -12
- package/src/dt-config/overlay.ts +1058 -1058
- package/src/framework.manifest.ts +538 -535
- package/src/index.ts +5 -5
- package/src/licenses.ts +425 -425
- package/src/lowering/fs.ts +135 -135
- package/src/lowering/gpio.ts +0 -33
- package/src/lowering/http.ts +264 -32
- package/src/lowering/i2c.ts +0 -9
- package/src/lowering/interrupts.ts +6 -0
- package/src/lowering/mqtt.ts +109 -8
- package/src/lowering/usb.ts +221 -221
- package/src/lowering/wdt.ts +2 -25
- package/src/sdk/board-catalog-sync.ts +4 -25
- package/src/strategy.ts +2265 -2309
- package/src/toolchain/debug-config.ts +264 -514
- package/src/toolchain/env-check.ts +279 -285
- package/src/toolchain/index.ts +1703 -1286
- package/src/toolchain/runners.ts +80 -0
- package/src/toolchain/scaffold.ts +296 -296
- package/src/toolchain/west-discover.ts +35 -13
- package/src/toolchain/west-spawn.ts +174 -168
- package/dist/async/timer-polyfill.d.ts +0 -10
- package/dist/async/timer-polyfill.js +0 -95
- package/dist/chips/board-overrides.d.ts +0 -7
- package/dist/chips/board-overrides.js +0 -11
- package/dist/chips/esp32.d.ts +0 -2
- package/dist/chips/esp32.js +0 -71
- package/dist/chips/esp32s3.d.ts +0 -2
- package/dist/chips/esp32s3.js +0 -103
- package/dist/chips/soc/.d.ts +0 -2
- package/dist/chips/soc/.js +0 -129
- package/dist/chips/soc/esp32.d.ts +0 -2
- package/dist/chips/soc/esp32.js +0 -120
- package/dist/chips/soc/esp32c3.d.ts +0 -2
- package/dist/chips/soc/esp32c3.js +0 -90
- package/dist/chips/soc/esp32c6.d.ts +0 -2
- package/dist/chips/soc/esp32c6.js +0 -109
- package/dist/chips/soc/esp32s3.d.ts +0 -2
- package/dist/chips/soc/esp32s3.js +0 -189
- package/dist/chips/soc/index.d.ts +0 -2
- package/dist/chips/soc/index.js +0 -23
- package/dist/chips/soc/nrf52840.d.ts +0 -2
- package/dist/chips/soc/nrf52840.js +0 -130
- package/dist/chips/soc/rp2040.d.ts +0 -2
- package/dist/chips/soc/rp2040.js +0 -141
- package/dist/chips/soc/rp2350a.d.ts +0 -2
- package/dist/chips/soc/rp2350a.js +0 -145
- package/dist/chips/soc/samd21g18a.d.ts +0 -2
- package/dist/chips/soc/samd21g18a.js +0 -143
- package/dist/chips/soc/stm32f411xe.d.ts +0 -2
- package/dist/chips/soc/stm32f411xe.js +0 -251
- package/dist/chips/xiao-ble.d.ts +0 -2
- package/dist/chips/xiao-ble.js +0 -100
- package/dist/lowering/power.d.ts +0 -9
- package/dist/lowering/power.js +0 -60
- package/dist/lowering/pulse.d.ts +0 -7
- package/dist/lowering/pulse.js +0 -51
- package/dist/lowering/tone.d.ts +0 -10
- package/dist/lowering/tone.js +0 -63
- package/dist/lowering/worker-backing.d.ts +0 -14
- package/dist/lowering/worker-backing.js +0 -79
- package/dist/lowering/worker.d.ts +0 -6
- package/dist/lowering/worker.js +0 -14
- package/dist/sdk/board-data.generated.d.ts +0 -2
- package/dist/sdk/board-data.generated.js +0 -4
- package/dist/sdk/catalog-walker.d.ts +0 -90
- package/dist/sdk/catalog-walker.js +0 -682
- package/dist/sdk/dts-reader.d.ts +0 -83
- package/dist/sdk/dts-reader.js +0 -596
- package/src/debug-codegen.ts +0 -207
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// 1. `west` already on PATH (env already activated / global install).
|
|
12
12
|
// 2. $ZEPHYR_BASE venv: ${ZEPHYR_BASE}/../.venv/<python> -m west.
|
|
13
13
|
// 3. micromamba env from @typecad/zephyr-installer (invoked via `micromamba run`,
|
|
14
|
-
// so
|
|
14
|
+
// so typecad-hal builds work with NO manual activation).
|
|
15
15
|
// 4. Well-known workspace layouts: ~/zephyrproject/.venv, /opt/zephyrproject/.
|
|
16
16
|
// venv, etc.
|
|
17
17
|
// 5. System pythons (`python`, `python3`, `py`) via `-m west`.
|
|
@@ -142,6 +142,33 @@ export function discoverFromZephyrBase(): WestInstall | null {
|
|
|
142
142
|
};
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
/** The installer-written SDK dir for the default micromamba env, when the
|
|
146
|
+
* installer has run on this machine. Read WITHOUT requiring micromamba
|
|
147
|
+
* mode — a PATH/venv west install is enriched with it so builds spawned
|
|
148
|
+
* through it still pin the installer's SDK (otherwise Zephyr's CMake
|
|
149
|
+
* searches $HOME and can pick up a stray, older SDK). */
|
|
150
|
+
export function installerSdkDir(): string | undefined {
|
|
151
|
+
const mm = findMicromamba();
|
|
152
|
+
if (!mm) return undefined;
|
|
153
|
+
const envName = process.env.TYPECAD_ZEPHYR_ENV || 'zephyr';
|
|
154
|
+
const envDir = join(mm.rootPrefix, 'envs', envName);
|
|
155
|
+
if (!existsSync(envDir)) return undefined;
|
|
156
|
+
const sdk = readMicromambaEnvVar(envDir, 'TYPECAD_ZEPHYR_SDK_INSTALL_DIR');
|
|
157
|
+
return sdk && existsSync(sdk) ? sdk : undefined;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The micromamba env created by `@typecad/zephyr-installer`. The env's west
|
|
162
|
+
* lives at envs/<name>/bin/west (POSIX) or Scripts/west.exe (Windows). Found
|
|
163
|
+
* installs are invoked via `micromamba run -n <name> west …` (see
|
|
164
|
+
* west-spawn.ts), which sets up the env's full PATH (cmake/ninja/dtc) AND runs
|
|
165
|
+
* the activation hook (ZEPHYR_BASE / ZEPHYR_SDK_INSTALL_DIR) — so builds work
|
|
166
|
+
* with NO manual `micromamba activate`. This is what makes a fresh
|
|
167
|
+
* `typecad-hal build` succeed in any project without the user activating.
|
|
168
|
+
*
|
|
169
|
+
* Env name defaults to "zephyr"; override via TYPECAD_ZEPHYR_ENV. File-check
|
|
170
|
+
* based (no spawn) so it's cheap to run on every invocation.
|
|
171
|
+
*/
|
|
145
172
|
// ── Strategy 3: micromamba env (the @typecad/zephyr-installer install) ─────
|
|
146
173
|
|
|
147
174
|
// Locate the micromamba binary + root prefix. The installer downloads
|
|
@@ -156,18 +183,6 @@ function findMicromamba(): { exe: string; rootPrefix: string } | null {
|
|
|
156
183
|
return existsSync(exe) ? { exe, rootPrefix: root } : null;
|
|
157
184
|
}
|
|
158
185
|
|
|
159
|
-
/**
|
|
160
|
-
* The micromamba env created by `@typecad/zephyr-installer`. The env's west
|
|
161
|
-
* lives at envs/<name>/bin/west (POSIX) or Scripts/west.exe (Windows). Found
|
|
162
|
-
* installs are invoked via `micromamba run -n <name> west …` (see
|
|
163
|
-
* west-spawn.ts), which sets up the env's full PATH (cmake/ninja/dtc) AND runs
|
|
164
|
-
* the activation hook (ZEPHYR_BASE / ZEPHYR_SDK_INSTALL_DIR) — so cuttlefish
|
|
165
|
-
* builds work with NO manual `micromamba activate`. This is what makes a fresh
|
|
166
|
-
* `cuttlefish build` succeed in any project without the user activating.
|
|
167
|
-
*
|
|
168
|
-
* Env name defaults to "zephyr"; override via TYPECAD_ZEPHYR_ENV. File-check
|
|
169
|
-
* based (no spawn) so it's cheap to run on every cuttlefish invocation.
|
|
170
|
-
*/
|
|
171
186
|
/** Read a TYPECAD_ZEPHYR_* value from the installer-written env-vars file in
|
|
172
187
|
* a micromamba env. Handles .sh (export VAR="val"), .bat (set "VAR=val"),
|
|
173
188
|
* and .ps1 ($env:VAR = "val"). Returns undefined if absent/unreadable. */
|
|
@@ -325,6 +340,13 @@ export function discoverWest(): WestInstall | null {
|
|
|
325
340
|
install = null;
|
|
326
341
|
}
|
|
327
342
|
if (install) {
|
|
343
|
+
// A PATH/venv west install knows nothing about the installer's SDK.
|
|
344
|
+
// Enrich it: west-spawn pins the child's ZEPHYR_SDK_INSTALL_DIR to the
|
|
345
|
+
// installer dir, so Zephyr's CMake cannot pick up a stray SDK from
|
|
346
|
+
// $HOME (a version mismatch that only surfaces at configure time).
|
|
347
|
+
if (!install.sdkInstallDir) {
|
|
348
|
+
install.sdkInstallDir = installerSdkDir();
|
|
349
|
+
}
|
|
328
350
|
cachedDiscover = install;
|
|
329
351
|
return install;
|
|
330
352
|
}
|
|
@@ -1,168 +1,174 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// west spawn helper — build a spawnSync invocation for `west <args>`
|
|
3
|
-
//
|
|
4
|
-
// Mirrors framework-esp32's idfSpawn(): given the discovered WestInstall,
|
|
5
|
-
// produce {command, args, env} that the toolchain destructures into spawnSync.
|
|
6
|
-
//
|
|
7
|
-
// Two modes:
|
|
8
|
-
// - 'launcher': spawn the `west` launcher directly (mode 'launcher').
|
|
9
|
-
// - 'module' : spawn `<python> -m west ...` (mode 'module'). This is the
|
|
10
|
-
// robust cross-platform form — it activates the venv's
|
|
11
|
-
// interpreter for the one process without sourcing anything.
|
|
12
|
-
//
|
|
13
|
-
// ZEPHYR_BASE is injected into the spawn env when a SDK root was discovered
|
|
14
|
-
// (find_package(Zephyr) needs it). west's prj.conf/CMakeLists are found via
|
|
15
|
-
// the project dir regardless.
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
|
-
|
|
18
|
-
import type { SpawnSyncOptions } from 'node:child_process';
|
|
19
|
-
import { dirname, join } from 'node:path';
|
|
20
|
-
import { existsSync } from 'node:fs';
|
|
21
|
-
import { type WestInstall, discoverWest } from './west-discover.js';
|
|
22
|
-
|
|
23
|
-
export interface WestInvocation {
|
|
24
|
-
/** The command to spawnSync: a `west` launcher or a Python interpreter. */
|
|
25
|
-
command: string;
|
|
26
|
-
/** Args for the command (includes `-m west` when in module mode). */
|
|
27
|
-
args: string[];
|
|
28
|
-
/** Base spawn options with cwd/timeout/encoding/stdio, plus the env carrying
|
|
29
|
-
* ZEPHYR_BASE when discovered. */
|
|
30
|
-
options: SpawnSyncOptions;
|
|
31
|
-
/** The install the invocation was built from, for surfacing to the user. */
|
|
32
|
-
install: WestInstall;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* The Scripts/ (Windows) or bin/ (POSIX) directory of the venv the discovered
|
|
37
|
-
* west runs under. `pythonExecutable` lives in that directory, so it is its
|
|
38
|
-
* dirname. Returns undefined for launcher-mode installs where no venv is known.
|
|
39
|
-
*/
|
|
40
|
-
function venvBinDir(install: WestInstall): string | undefined {
|
|
41
|
-
return install.pythonExecutable ? dirname(install.pythonExecutable) : undefined;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* The env to pass to the west spawn: the process env, with ZEPHYR_BASE injected
|
|
46
|
-
* when a SDK root was discovered, AND the venv's bin/Scripts dir prepended to
|
|
47
|
-
* PATH when west was found via a venv Python.
|
|
48
|
-
*
|
|
49
|
-
* The PATH prepend matters: `west flash` shells out to bare runner tools
|
|
50
|
-
* (`esptool`, `openocd`, `nrfjprog`, …) via check_call, so they resolve from
|
|
51
|
-
* PATH. Without the prepend, the user's PATH may surface a *different* tool
|
|
52
|
-
* ahead of the venv's — e.g. an older esptool whose argument spelling is
|
|
53
|
-
* incompatible with the runner. Putting the venv's bin first makes west's
|
|
54
|
-
* delegated subprocesses resolve to the same versions west itself runs under.
|
|
55
|
-
*/
|
|
56
|
-
export function buildEnv(install: WestInstall): NodeJS.ProcessEnv {
|
|
57
|
-
const env = { ...process.env };
|
|
58
|
-
if (install.zephyrBase && !env.ZEPHYR_BASE) {
|
|
59
|
-
env.ZEPHYR_BASE = install.zephyrBase;
|
|
60
|
-
}
|
|
61
|
-
// SWD flashing (`zephyr.runner: 'openocd'`): west's openocd runner resolves
|
|
62
|
-
// a bare `openocd` from PATH. The Zephyr SDK ships it under
|
|
63
|
-
// hosttools/openocd/bin (the SDK's own setup.cmd puts that dir on PATH for
|
|
64
|
-
// activated terminals) — do the same for spawned west processes so ST-Link
|
|
65
|
-
// flashing works without activation. $ZEPHYR_SDK_INSTALL_DIR (set by an
|
|
66
|
-
// activated env) wins over the discovered install dir.
|
|
67
|
-
const sdkRoot = env.ZEPHYR_SDK_INSTALL_DIR || install.sdkInstallDir;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
// the
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
'
|
|
120
|
-
'
|
|
121
|
-
'
|
|
122
|
-
'
|
|
123
|
-
|
|
124
|
-
'
|
|
125
|
-
'',
|
|
126
|
-
'
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// west spawn helper — build a spawnSync invocation for `west <args>`
|
|
3
|
+
//
|
|
4
|
+
// Mirrors framework-esp32's idfSpawn(): given the discovered WestInstall,
|
|
5
|
+
// produce {command, args, env} that the toolchain destructures into spawnSync.
|
|
6
|
+
//
|
|
7
|
+
// Two modes:
|
|
8
|
+
// - 'launcher': spawn the `west` launcher directly (mode 'launcher').
|
|
9
|
+
// - 'module' : spawn `<python> -m west ...` (mode 'module'). This is the
|
|
10
|
+
// robust cross-platform form — it activates the venv's
|
|
11
|
+
// interpreter for the one process without sourcing anything.
|
|
12
|
+
//
|
|
13
|
+
// ZEPHYR_BASE is injected into the spawn env when a SDK root was discovered
|
|
14
|
+
// (find_package(Zephyr) needs it). west's prj.conf/CMakeLists are found via
|
|
15
|
+
// the project dir regardless.
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
import type { SpawnSyncOptions } from 'node:child_process';
|
|
19
|
+
import { dirname, join } from 'node:path';
|
|
20
|
+
import { existsSync } from 'node:fs';
|
|
21
|
+
import { type WestInstall, discoverWest } from './west-discover.js';
|
|
22
|
+
|
|
23
|
+
export interface WestInvocation {
|
|
24
|
+
/** The command to spawnSync: a `west` launcher or a Python interpreter. */
|
|
25
|
+
command: string;
|
|
26
|
+
/** Args for the command (includes `-m west` when in module mode). */
|
|
27
|
+
args: string[];
|
|
28
|
+
/** Base spawn options with cwd/timeout/encoding/stdio, plus the env carrying
|
|
29
|
+
* ZEPHYR_BASE when discovered. */
|
|
30
|
+
options: SpawnSyncOptions;
|
|
31
|
+
/** The install the invocation was built from, for surfacing to the user. */
|
|
32
|
+
install: WestInstall;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The Scripts/ (Windows) or bin/ (POSIX) directory of the venv the discovered
|
|
37
|
+
* west runs under. `pythonExecutable` lives in that directory, so it is its
|
|
38
|
+
* dirname. Returns undefined for launcher-mode installs where no venv is known.
|
|
39
|
+
*/
|
|
40
|
+
function venvBinDir(install: WestInstall): string | undefined {
|
|
41
|
+
return install.pythonExecutable ? dirname(install.pythonExecutable) : undefined;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The env to pass to the west spawn: the process env, with ZEPHYR_BASE injected
|
|
46
|
+
* when a SDK root was discovered, AND the venv's bin/Scripts dir prepended to
|
|
47
|
+
* PATH when west was found via a venv Python.
|
|
48
|
+
*
|
|
49
|
+
* The PATH prepend matters: `west flash` shells out to bare runner tools
|
|
50
|
+
* (`esptool`, `openocd`, `nrfjprog`, …) via check_call, so they resolve from
|
|
51
|
+
* PATH. Without the prepend, the user's PATH may surface a *different* tool
|
|
52
|
+
* ahead of the venv's — e.g. an older esptool whose argument spelling is
|
|
53
|
+
* incompatible with the runner. Putting the venv's bin first makes west's
|
|
54
|
+
* delegated subprocesses resolve to the same versions west itself runs under.
|
|
55
|
+
*/
|
|
56
|
+
export function buildEnv(install: WestInstall): NodeJS.ProcessEnv {
|
|
57
|
+
const env = { ...process.env };
|
|
58
|
+
if (install.zephyrBase && !env.ZEPHYR_BASE) {
|
|
59
|
+
env.ZEPHYR_BASE = install.zephyrBase;
|
|
60
|
+
}
|
|
61
|
+
// SWD flashing (`zephyr.runner: 'openocd'`): west's openocd runner resolves
|
|
62
|
+
// a bare `openocd` from PATH. The Zephyr SDK ships it under
|
|
63
|
+
// hosttools/openocd/bin (the SDK's own setup.cmd puts that dir on PATH for
|
|
64
|
+
// activated terminals) — do the same for spawned west processes so ST-Link
|
|
65
|
+
// flashing works without activation. $ZEPHYR_SDK_INSTALL_DIR (set by an
|
|
66
|
+
// activated env) wins over the discovered install dir.
|
|
67
|
+
const sdkRoot = env.ZEPHYR_SDK_INSTALL_DIR || install.sdkInstallDir;
|
|
68
|
+
// Pin the west/cmake child to the discovered SDK: without this, Zephyr's
|
|
69
|
+
// FindZephyr-sdk searches $HOME and can latch onto a stray, older SDK —
|
|
70
|
+
// a configure-time version failure that only surfaces in the build log.
|
|
71
|
+
if (!env.ZEPHYR_SDK_INSTALL_DIR && install.sdkInstallDir) {
|
|
72
|
+
env.ZEPHYR_SDK_INSTALL_DIR = install.sdkInstallDir;
|
|
73
|
+
}
|
|
74
|
+
const openocdBin = sdkRoot ? join(sdkRoot, 'hosttools', 'openocd', 'bin') : undefined;
|
|
75
|
+
const prepend = [
|
|
76
|
+
openocdBin !== undefined && existsSync(openocdBin) ? openocdBin : undefined,
|
|
77
|
+
venvBinDir(install),
|
|
78
|
+
].filter((d): d is string => d !== undefined);
|
|
79
|
+
if (prepend.length > 0) {
|
|
80
|
+
const sep = process.platform === 'win32' ? ';' : ':';
|
|
81
|
+
// On Windows the PATH environment variable may be cased as `Path` (the
|
|
82
|
+
// registry-native form, the only one populated when node is launched from
|
|
83
|
+
// PowerShell/cmd) or `PATH` (POSIX form, set by Git Bash). Writing only one
|
|
84
|
+
// casing can leave the other stale/empty, which under PowerShell would drop
|
|
85
|
+
// the user's real PATH (cmake, ninja, …) — breaking `west` configure. Read
|
|
86
|
+
// whichever casing is populated and write that same casing back, preserving
|
|
87
|
+
// the full existing value with the discovered dirs prepended.
|
|
88
|
+
const existing = env.Path ?? env.PATH ?? '';
|
|
89
|
+
const updated = prepend.join(sep) + sep + existing;
|
|
90
|
+
if (env.Path !== undefined || (env.PATH === undefined && process.platform === 'win32')) {
|
|
91
|
+
env.Path = updated;
|
|
92
|
+
} else {
|
|
93
|
+
env.PATH = updated;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return env;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Build a spawn invocation that runs `west <westArgs>`.
|
|
101
|
+
*
|
|
102
|
+
* `baseOptions` carries the cwd/timeout/stdio settings the caller wants;
|
|
103
|
+
* westSpawn preserves them and injects the discovery env. The returned object
|
|
104
|
+
* destructures directly into spawnSync:
|
|
105
|
+
*
|
|
106
|
+
* const inv = westSpawn(['build', '-b', 'xiao_ble', projectRoot], { cwd, timeout });
|
|
107
|
+
* spawnSync(inv.command, inv.args, inv.options);
|
|
108
|
+
*
|
|
109
|
+
* Throws a clear, actionable error when no usable west install is discovered.
|
|
110
|
+
*/
|
|
111
|
+
export function westSpawn(
|
|
112
|
+
westArgs: string[],
|
|
113
|
+
baseOptions: SpawnSyncOptions,
|
|
114
|
+
): WestInvocation {
|
|
115
|
+
const install = discoverWest();
|
|
116
|
+
if (!install) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
[
|
|
119
|
+
'west (the Zephyr build tool) was not found.',
|
|
120
|
+
'',
|
|
121
|
+
'typecad-hal looked for it on PATH, in $ZEPHYR_BASE/.venv, in common',
|
|
122
|
+
'Zephyr workspace dirs (~/zephyrproject/.venv), and as a system',
|
|
123
|
+
"Python module (`python -m west`). To fix:",
|
|
124
|
+
'',
|
|
125
|
+
' • Run the typeCAD Zephyr installer (one command, any OS — needs Node ≥18):',
|
|
126
|
+
' node packages/zephyr-installer/install.mjs',
|
|
127
|
+
' then `micromamba activate zephyr` and retry.',
|
|
128
|
+
' • Or activate an existing Zephyr venv in this shell, or',
|
|
129
|
+
' • Or set ZEPHYR_BASE to your Zephyr SDK root (the venv at $ZEPHYR_BASE/../.venv is then used), or',
|
|
130
|
+
' • Or install west into a discoverable Python: pip install west',
|
|
131
|
+
'',
|
|
132
|
+
'See https://docs.zephyrproject.org/latest/develop/getting_started/index.html',
|
|
133
|
+
].join('\n'),
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const env = buildEnv(install);
|
|
138
|
+
// Strip `shell` if present — we pass absolute paths / known commands, and
|
|
139
|
+
// an explicit shell changes arg-quoting semantics on Windows.
|
|
140
|
+
const { shell: _drop, ...optsWithoutShell } = baseOptions as any;
|
|
141
|
+
|
|
142
|
+
if (install.mode === 'micromamba' && install.micromambaExe) {
|
|
143
|
+
// `micromamba run -n <env> west …` sets up the env's full PATH
|
|
144
|
+
// (cmake/ninja/dtc) and runs the activation hook (ZEPHYR_BASE /
|
|
145
|
+
// ZEPHYR_SDK_INSTALL_DIR), so typecad-hal builds work WITHOUT the user
|
|
146
|
+
// activating the env. Inject MAMBA_ROOT_PREFIX so micromamba finds envs.
|
|
147
|
+
const mmEnv = { ...env };
|
|
148
|
+
if (install.mambaRootPrefix) mmEnv.MAMBA_ROOT_PREFIX = install.mambaRootPrefix;
|
|
149
|
+
return {
|
|
150
|
+
command: install.micromambaExe,
|
|
151
|
+
args: ['run', '-n', install.envName ?? 'zephyr', 'west', ...westArgs],
|
|
152
|
+
options: { ...optsWithoutShell, env: mmEnv },
|
|
153
|
+
install,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (install.mode === 'launcher' && install.westExecutable) {
|
|
158
|
+
return {
|
|
159
|
+
command: install.westExecutable,
|
|
160
|
+
args: westArgs,
|
|
161
|
+
options: { ...optsWithoutShell, env },
|
|
162
|
+
install,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// module mode: <python> -m west <args>
|
|
167
|
+
const py = install.pythonExecutable!;
|
|
168
|
+
return {
|
|
169
|
+
command: py,
|
|
170
|
+
args: ['-m', 'west', ...westArgs],
|
|
171
|
+
options: { ...optsWithoutShell, env },
|
|
172
|
+
install,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { RuntimePolyfillIR } from '@typecad/cuttlefish/api/shared';
|
|
2
|
-
export interface TimerPolyfillIR extends RuntimePolyfillIR {
|
|
3
|
-
/** The clamped pool size the C++ was generated with. */
|
|
4
|
-
maxTimers: number;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Build the timer_methods polyfill IR. `requestedTimers` is sized from
|
|
8
|
-
* ctx.analysis.timerCallCount; it is clamped to [1, 16].
|
|
9
|
-
*/
|
|
10
|
-
export declare function buildTimerPolyfill(requestedTimers: number): TimerPolyfillIR;
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// Timer methods polyfill — Zephyr k_timer + k_work (heap-free)
|
|
3
|
-
//
|
|
4
|
-
// setInterval / setTimeout / clearInterval / clearTimeout backed by a fixed
|
|
5
|
-
// pool of k_timer + k_work pairs. The timer's expiry function (ISR context)
|
|
6
|
-
// submits a k_work item to the system workqueue; the work handler runs the
|
|
7
|
-
// user callback in thread context. This split keeps the ISR cheap and lets the
|
|
8
|
-
// callback run on a real thread (so it can do real work — but must not block,
|
|
9
|
-
// since the system workqueue is shared).
|
|
10
|
-
//
|
|
11
|
-
// EMIT BOUNDARY: emitted bytes land in user firmware. Covered by the TypeCAD
|
|
12
|
-
// Runtime Exception (RUNTIME_EXCEPTION.md at the repo root).
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
const MIN_TIMERS = 1;
|
|
15
|
-
const MAX_TIMERS_CAP = 16;
|
|
16
|
-
/**
|
|
17
|
-
* Build the timer_methods polyfill IR. `requestedTimers` is sized from
|
|
18
|
-
* ctx.analysis.timerCallCount; it is clamped to [1, 16].
|
|
19
|
-
*/
|
|
20
|
-
export function buildTimerPolyfill(requestedTimers) {
|
|
21
|
-
const maxTimers = Math.min(MAX_TIMERS_CAP, Math.max(MIN_TIMERS, requestedTimers));
|
|
22
|
-
const helperStructs = [`
|
|
23
|
-
// cuttlefish timer runtime — k_timer + k_work pool (heap-free).
|
|
24
|
-
struct __tc_TimerSlot {
|
|
25
|
-
struct k_timer timer;
|
|
26
|
-
struct k_work work;
|
|
27
|
-
void (*callback)(void);
|
|
28
|
-
bool active;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
static struct __tc_TimerSlot __tc_timer_slots[${maxTimers}];
|
|
32
|
-
|
|
33
|
-
static void __tc_timer_work_handler(struct k_work* w) {
|
|
34
|
-
// Runs on the system workqueue thread (NOT ISR). Find the owning slot by
|
|
35
|
-
// address and invoke the callback. Must not block.
|
|
36
|
-
for (int32_t i = 0; i < ${maxTimers}; i++) {
|
|
37
|
-
if (&__tc_timer_slots[i].work == w) {
|
|
38
|
-
if (__tc_timer_slots[i].callback != nullptr) { __tc_timer_slots[i].callback(); }
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
static void __tc_timer_expiry_fn(struct k_timer* t) {
|
|
45
|
-
// ISR context: submit the work item, do NOT run the callback here.
|
|
46
|
-
for (int32_t i = 0; i < ${maxTimers}; i++) {
|
|
47
|
-
if (&__tc_timer_slots[i].timer == t) {
|
|
48
|
-
(void)k_work_submit(&__tc_timer_slots[i].work);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
static int32_t __tc_timer_add(void (*cb)(void), int32_t ms, bool repeat) {
|
|
55
|
-
for (int32_t i = 0; i < ${maxTimers}; i++) {
|
|
56
|
-
if (!__tc_timer_slots[i].active) {
|
|
57
|
-
__tc_timer_slots[i].callback = cb;
|
|
58
|
-
__tc_timer_slots[i].active = true;
|
|
59
|
-
k_timer_init(&__tc_timer_slots[i].timer, __tc_timer_expiry_fn, nullptr);
|
|
60
|
-
k_work_init(&__tc_timer_slots[i].work, __tc_timer_work_handler);
|
|
61
|
-
k_timer_start(&__tc_timer_slots[i].timer, K_MSEC(ms), repeat ? K_MSEC(ms) : K_FOREVER);
|
|
62
|
-
return i + 1; // 1-based id
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return 0; // pool full
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
static void __tc_timer_clear(int32_t id) {
|
|
69
|
-
if (id > 0 && id <= ${maxTimers}) {
|
|
70
|
-
int32_t i = id - 1;
|
|
71
|
-
k_timer_stop(&__tc_timer_slots[i].timer);
|
|
72
|
-
__tc_timer_slots[i].active = false;
|
|
73
|
-
__tc_timer_slots[i].callback = nullptr;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
`];
|
|
77
|
-
const helperFunctions = [`
|
|
78
|
-
int32_t __tc_setInterval(void (*cb)(), int32_t ms) { return __tc_timer_add(cb, ms, true); }
|
|
79
|
-
int32_t __tc_setTimeout(void (*cb)(), int32_t ms) { return __tc_timer_add(cb, ms, false); }
|
|
80
|
-
void __tc_clearInterval(int32_t id) { __tc_timer_clear(id); }
|
|
81
|
-
void __tc_clearTimeout(int32_t id) { __tc_timer_clear(id); }
|
|
82
|
-
`];
|
|
83
|
-
return {
|
|
84
|
-
kind: 'polyfill',
|
|
85
|
-
id: 'timer_methods',
|
|
86
|
-
domain: 'embedded',
|
|
87
|
-
requiredIncludes: [],
|
|
88
|
-
forwardDeclarations: [],
|
|
89
|
-
helperStructs,
|
|
90
|
-
helperFunctions,
|
|
91
|
-
shimMacros: [],
|
|
92
|
-
dependencies: [],
|
|
93
|
-
maxTimers,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export interface BoardOverride {
|
|
2
|
-
/** LED pin name for boards whose user LED is not a gpio-leds node (the
|
|
3
|
-
* ESP32-S3 DevKitC's addressable RGB on GPIO48 — driven as plain GPIO,
|
|
4
|
-
* same as the deleted board package did). */
|
|
5
|
-
readonly led?: string;
|
|
6
|
-
}
|
|
7
|
-
export declare const BOARD_OVERRIDES: Readonly<Record<string, BoardOverride>>;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// board-overrides.ts — curated board-level facts the devicetree cannot
|
|
3
|
-
// express. The honest residue of the board-package deletion: things a board
|
|
4
|
-
// vendor documents in a datasheet but never encodes in DTS.
|
|
5
|
-
//
|
|
6
|
-
// Keyed by the bare board id (the first segment of the qualified target, so
|
|
7
|
-
// every variant/qualifier of the board inherits the override).
|
|
8
|
-
// ----------------------------------------------------------------------------
|
|
9
|
-
export const BOARD_OVERRIDES = {
|
|
10
|
-
esp32s3_devkitc: { led: 'GPIO48' },
|
|
11
|
-
};
|
package/dist/chips/esp32.d.ts
DELETED
package/dist/chips/esp32.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// Espressif ESP32 (esp32_devkitc) — Zephyr board descriptor
|
|
3
|
-
//
|
|
4
|
-
// Board target: `esp32_devkitc` (mainline Zephyr,
|
|
5
|
-
// boards/espressif/esp32_devkitc). Programmed over USB via the esptool runner
|
|
6
|
-
// (see toolchain/index.ts), the same flash path as the ESP32-S3.
|
|
7
|
-
//
|
|
8
|
-
// GPIO is split across TWO devicetree controllers — `gpio0` (pins 0–31) and
|
|
9
|
-
// `gpio1` (pins 32–39) — so this descriptor lists both in `gpioControllers`.
|
|
10
|
-
// The lowering routes each HAL pin to its owning controller at runtime; see
|
|
11
|
-
// chips/controllers.ts. (Same shape as the S3, but the ESP32's highest GPIO is
|
|
12
|
-
// 39, not 48 — `gpio1` has ngpios=8, not 17.)
|
|
13
|
-
//
|
|
14
|
-
// Minimal-by-design: the only DT facts carried here are the ones a compile-time
|
|
15
|
-
// DT macro cannot reach — the runtime pin→controller split, plus the `sw0`
|
|
16
|
-
// alias for the BOOT button (used by the devicetree-spec GPIO path). Every other
|
|
17
|
-
// DT fact (UART/I2C/SPI/`wdt` nodelabels) is resolved by Zephyr's own
|
|
18
|
-
// devicetree via emitted DT_NODELABEL macros, not hand-copied here.
|
|
19
|
-
//
|
|
20
|
-
// Verified against the Zephyr board DTS:
|
|
21
|
-
// boards/espressif/esp32_devkitc/esp32_devkitc_procpu.dts
|
|
22
|
-
// aliases { sw0 = &button0; } → button_0: pin 0 on gpio0, active-low + pull-up
|
|
23
|
-
// &gpio0/&gpio1 { status = "okay" } (esp32_devkitc_procpu.dts:64-70)
|
|
24
|
-
// &wifi { status = "okay" } (esp32_devkitc_procpu.dts:143-145)
|
|
25
|
-
// GPIO controller coverage:
|
|
26
|
-
// dts/xtensa/espressif/esp32/esp32_common.dtsi:314-337
|
|
27
|
-
// gpio0: ngpios = <32> (pins 0–31)
|
|
28
|
-
// gpio1: ngpios = <8> (pins 32–39)
|
|
29
|
-
//
|
|
30
|
-
// Note: GPIO 34–39 are input-only pads on ESP32 silicon (not modeled here —
|
|
31
|
-
// the DT does not encode output restrictions per pin; an output config on those
|
|
32
|
-
// pins fails at runtime against the raw controller, which is the expected
|
|
33
|
-
// silicon-accurate behavior).
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
|
-
export const ESP32_DEVKITC = {
|
|
36
|
-
id: 'esp32_devkitc',
|
|
37
|
-
soc: 'esp32',
|
|
38
|
-
gpioController: 'gpio0',
|
|
39
|
-
gpioControllers: [
|
|
40
|
-
{ nodelabel: 'gpio0', minPin: 0, maxPin: 31 },
|
|
41
|
-
{ nodelabel: 'gpio1', minPin: 32, maxPin: 39 },
|
|
42
|
-
],
|
|
43
|
-
gpio: {
|
|
44
|
-
// The BOOT button (GPIO0) is the board's only DT-aliased GPIO. Listed so a
|
|
45
|
-
// program reading/interrupting pin 0 goes through the polarity-correct
|
|
46
|
-
// devicetree-spec path (GPIO_ACTIVE_LOW honored by the DT flags).
|
|
47
|
-
dtSpecs: [
|
|
48
|
-
{ pin: 0, dtSpec: 'sw0' }, // BOOT button (GPIO0)
|
|
49
|
-
],
|
|
50
|
-
interruptPins: [
|
|
51
|
-
{ pin: 0, dtSpec: 'sw0' }, // BOOT button (GPIO0)
|
|
52
|
-
],
|
|
53
|
-
},
|
|
54
|
-
// WiFi: the ESP32 has a 2.4GHz radio; conn_mgr + the esp32 wifi driver
|
|
55
|
-
// (CONFIG_WIFI_ESP32) provide connectivity. WIFI_ESP32 depends on !SMP, and
|
|
56
|
-
// the ESP32 is AMP (dual-image procpu/appcpu), not SMP, by default — so the
|
|
57
|
-
// dependency is satisfied. Omitted on radioless targets.
|
|
58
|
-
wifi: { supported: true },
|
|
59
|
-
// DAC: the ESP32 has two 8-bit DAC channels on GPIO25 (channel 1) and GPIO26
|
|
60
|
-
// (channel 2). The Zephyr esp32 DAC driver (drivers/dac/dac_esp32.c) exposes
|
|
61
|
-
// them via the `dac0` node; the lowering emits dac_channel_setup +
|
|
62
|
-
// dac_write_value against DEVICE_DT_GET(DT_NODELABEL(dac0)). The overlay
|
|
63
|
-
// enables the node when the program uses dac.*. ESP32-S3 has no DAC.
|
|
64
|
-
dac: {
|
|
65
|
-
device: 'dac0',
|
|
66
|
-
channels: [
|
|
67
|
-
{ pin: 25, channel: 1, resolution: 8 },
|
|
68
|
-
{ pin: 26, channel: 2, resolution: 8 },
|
|
69
|
-
],
|
|
70
|
-
},
|
|
71
|
-
};
|
package/dist/chips/esp32s3.d.ts
DELETED