@typecad/framework-zephyr 1.0.0-alpha.14 → 1.0.0-alpha.15
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/README.md +22 -47
- package/dist/as-built.d.ts +33 -0
- package/dist/as-built.js +188 -0
- package/dist/async/timer-polyfill.js +1 -1
- package/dist/boardgen.d.ts +128 -0
- package/dist/boardgen.js +1366 -0
- package/dist/chips/board-overrides.d.ts +7 -0
- package/dist/chips/board-overrides.js +11 -0
- package/dist/chips/esp32s3.js +49 -0
- package/dist/chips/index.d.ts +6 -12
- package/dist/chips/index.js +18 -34
- package/dist/chips/resolve.d.ts +16 -2
- package/dist/chips/resolve.js +267 -10
- package/dist/chips/soc/.d.ts +2 -0
- package/dist/chips/soc/.js +129 -0
- package/dist/chips/soc/esp32.d.ts +2 -0
- package/dist/chips/soc/esp32.js +120 -0
- package/dist/chips/soc/esp32c3.d.ts +2 -0
- package/dist/chips/soc/esp32c3.js +90 -0
- package/dist/chips/soc/esp32c6.d.ts +2 -0
- package/dist/chips/soc/esp32c6.js +109 -0
- package/dist/chips/soc/esp32s3.d.ts +2 -0
- package/dist/chips/soc/esp32s3.js +189 -0
- package/dist/chips/soc/index.d.ts +2 -0
- package/dist/chips/soc/index.js +23 -0
- package/dist/chips/soc/nrf52840.d.ts +2 -0
- package/dist/chips/soc/nrf52840.js +130 -0
- package/dist/chips/soc/rp2040.d.ts +2 -0
- package/dist/chips/soc/rp2040.js +141 -0
- package/dist/chips/soc/rp2350a.d.ts +2 -0
- package/dist/chips/soc/rp2350a.js +145 -0
- package/dist/chips/soc/samd21g18a.d.ts +2 -0
- package/dist/chips/soc/samd21g18a.js +143 -0
- package/dist/chips/soc/stm32f411xe.d.ts +2 -0
- package/dist/chips/soc/stm32f411xe.js +251 -0
- package/dist/chips/types.d.ts +319 -0
- package/dist/chips/xiao-ble.js +21 -0
- package/dist/display/profiles.js +1 -1
- package/dist/doctor.js +38 -4
- package/dist/dt-config/custom-board.d.ts +23 -0
- package/dist/dt-config/custom-board.js +227 -0
- package/dist/dt-config/kconfig.d.ts +72 -1
- package/dist/dt-config/kconfig.js +115 -26
- package/dist/dt-config/overlay.js +548 -28
- package/dist/framework.manifest.d.ts +3 -3
- package/dist/framework.manifest.js +122 -185
- package/dist/index.d.ts +4 -1
- package/dist/index.js +8 -2
- package/dist/lowering/adc.d.ts +20 -2
- package/dist/lowering/adc.js +121 -29
- package/dist/lowering/ble.js +31 -28
- package/dist/lowering/dac.js +9 -9
- package/dist/lowering/fs.js +18 -10
- package/dist/lowering/gpio.d.ts +2 -0
- package/dist/lowering/gpio.js +82 -5
- package/dist/lowering/http.js +39 -14
- package/dist/lowering/hwtimer.d.ts +4 -0
- package/dist/lowering/hwtimer.js +35 -10
- package/dist/lowering/i2c.js +46 -54
- package/dist/lowering/index.d.ts +5 -5
- package/dist/lowering/index.js +15 -16
- package/dist/lowering/interrupts.d.ts +22 -5
- package/dist/lowering/interrupts.js +104 -22
- package/dist/lowering/mqtt.js +3 -5
- package/dist/lowering/power.js +0 -4
- package/dist/lowering/preferences.js +49 -77
- package/dist/lowering/pulse.js +0 -31
- package/dist/lowering/pwm.d.ts +12 -1
- package/dist/lowering/pwm.js +78 -14
- package/dist/lowering/random.js +3 -3
- package/dist/lowering/sensor.d.ts +37 -0
- package/dist/lowering/sensor.js +119 -0
- package/dist/lowering/spi.d.ts +12 -0
- package/dist/lowering/spi.js +65 -40
- package/dist/lowering/thread.d.ts +14 -0
- package/dist/lowering/thread.js +55 -0
- package/dist/lowering/timing.js +20 -46
- package/dist/lowering/tone.js +16 -4
- package/dist/lowering/uart.d.ts +13 -0
- package/dist/lowering/uart.js +72 -51
- package/dist/lowering/usb.d.ts +34 -0
- package/dist/lowering/usb.js +206 -0
- package/dist/lowering/wdt.d.ts +1 -1
- package/dist/lowering/wdt.js +17 -7
- package/dist/lowering/wifi.d.ts +3 -2
- package/dist/lowering/wifi.js +97 -111
- package/dist/sdk/board-catalog-sync.d.ts +16 -0
- package/dist/sdk/board-catalog-sync.js +41 -0
- package/dist/sdk/board-data.generated.d.ts +2 -0
- package/dist/sdk/board-data.generated.js +4 -0
- package/dist/sdk/catalog-walker.d.ts +90 -0
- package/dist/sdk/catalog-walker.js +682 -0
- package/dist/sdk/dts-reader.d.ts +83 -0
- package/dist/sdk/dts-reader.js +596 -0
- package/dist/strategy.d.ts +136 -17
- package/dist/strategy.js +839 -222
- package/dist/toolchain/bossac-touch.d.ts +18 -0
- package/dist/toolchain/bossac-touch.js +88 -0
- package/dist/toolchain/compat.d.ts +2 -2
- package/dist/toolchain/compat.js +8 -3
- package/dist/toolchain/debug-config.d.ts +21 -26
- package/dist/toolchain/debug-config.js +211 -71
- package/dist/toolchain/env-check.d.ts +4 -4
- package/dist/toolchain/env-check.js +5 -5
- package/dist/toolchain/index.d.ts +66 -1
- package/dist/toolchain/index.js +650 -70
- package/dist/toolchain/scaffold.js +39 -7
- package/dist/toolchain/west-discover.d.ts +4 -0
- package/dist/toolchain/west-discover.js +17 -6
- package/installer/CHANGELOG.md +473 -0
- package/installer/README.md +328 -0
- package/installer/environment.yml +46 -0
- package/installer/etc/conda/activate.d/zephyr.bat +7 -0
- package/installer/etc/conda/activate.d/zephyr.ps1 +12 -0
- package/installer/etc/conda/activate.d/zephyr.sh +20 -0
- package/installer/etc/conda/deactivate.d/zephyr.bat +6 -0
- package/installer/etc/conda/deactivate.d/zephyr.ps1 +6 -0
- package/installer/etc/conda/deactivate.d/zephyr.sh +4 -0
- package/installer/install.mjs +580 -0
- package/installer/install.ps1 +619 -0
- package/installer/install.sh +310 -0
- package/installer/lib/detect-platform.sh +62 -0
- package/installer/lib/fetch-sdk.sh +304 -0
- package/installer/lib/init-workspace.sh +153 -0
- package/installer/lib/write-activation.sh +76 -0
- package/installer/patches/tfm-c-include-separators.patch +19 -0
- package/installer/patches/zephyr-tfm-nordic-zephyr-include.patch +24 -0
- package/installer/templates/project/.typecad/activate-zephyr.ps1 +31 -0
- package/installer/templates/project/.typecad/activate-zephyr.sh +31 -0
- package/installer/templates/project/.vscode/settings.json +30 -0
- package/installer/templates/project/README.md +58 -0
- package/installer/versions.env +110 -0
- package/package.json +15 -15
- package/src/as-built.ts +206 -0
- package/src/boardgen.ts +1428 -0
- package/src/chips/index.ts +35 -54
- package/src/chips/resolve.ts +285 -10
- package/src/chips/types.ts +325 -1
- package/src/display/profiles.ts +1 -1
- package/src/doctor.ts +110 -77
- package/src/dt-config/custom-board.ts +325 -0
- package/src/dt-config/kconfig.ts +165 -18
- package/src/dt-config/overlay.ts +537 -25
- package/src/framework.manifest.ts +123 -185
- package/src/index.ts +57 -41
- package/src/lowering/adc.ts +222 -118
- package/src/lowering/ble.ts +32 -28
- package/src/lowering/dac.ts +82 -82
- package/src/lowering/fs.ts +18 -10
- package/src/lowering/gpio.ts +242 -155
- package/src/lowering/http.ts +512 -488
- package/src/lowering/hwtimer.ts +139 -101
- package/src/lowering/i2c.ts +116 -126
- package/src/lowering/index.ts +91 -93
- package/src/lowering/interrupts.ts +113 -21
- package/src/lowering/mqtt.ts +3 -5
- package/src/lowering/preferences.ts +327 -354
- package/src/lowering/pwm.ts +167 -99
- package/src/lowering/random.ts +3 -3
- package/src/lowering/sensor.ts +155 -0
- package/src/lowering/spi.ts +164 -124
- package/src/lowering/thread.ts +63 -0
- package/src/lowering/timing.ts +46 -72
- package/src/lowering/uart.ts +73 -51
- package/src/lowering/usb.ts +221 -0
- package/src/lowering/wdt.ts +95 -84
- package/src/lowering/wifi.ts +97 -112
- package/src/sdk/board-catalog-sync.ts +62 -0
- package/src/strategy.ts +848 -237
- package/src/toolchain/bossac-touch.ts +112 -0
- package/src/toolchain/compat.ts +8 -3
- package/src/toolchain/debug-config.ts +666 -522
- package/src/toolchain/env-check.ts +9 -9
- package/src/toolchain/index.ts +1286 -645
- package/src/toolchain/scaffold.ts +38 -7
- package/src/toolchain/west-discover.ts +19 -6
- package/src/async/timer-polyfill.ts +0 -107
- package/src/chips/esp32.ts +0 -74
- package/src/chips/esp32s3.ts +0 -57
- package/src/chips/xiao-ble.ts +0 -82
- package/src/lowering/power.ts +0 -70
- package/src/lowering/pulse.ts +0 -93
- package/src/lowering/tone.ts +0 -60
- package/src/lowering/worker-backing.ts +0 -94
- package/src/lowering/worker.ts +0 -17
package/src/chips/index.ts
CHANGED
|
@@ -1,54 +1,35 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// Chip descriptor
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
* (frameworkData.buildTarget / frameworkData.target). Accepts the bare board
|
|
37
|
-
* id ('xiao_ble', 'esp32s3_devkitc', 'esp32_devkitc') or a board/qualifier
|
|
38
|
-
* path ('esp32s3_devkitc/esp32s3/procpu', 'esp32_devkitc/esp32/procpu').
|
|
39
|
-
*/
|
|
40
|
-
export function chipForTarget(target?: string): ZephyrChipDescriptor {
|
|
41
|
-
const t = (target ?? '').trim().toLowerCase();
|
|
42
|
-
const boardId = t.split('/')[0];
|
|
43
|
-
switch (boardId) {
|
|
44
|
-
case 'xiao_ble':
|
|
45
|
-
return XIAO_BLE;
|
|
46
|
-
case 'esp32s3_devkitc':
|
|
47
|
-
return ESP32S3_DEVKITC;
|
|
48
|
-
case 'esp32_devkitc':
|
|
49
|
-
return ESP32_DEVKITC;
|
|
50
|
-
case '':
|
|
51
|
-
default:
|
|
52
|
-
return DEFAULT_CHIP;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Chip descriptor cache — the mechanism the strategy's lowering reads.
|
|
3
|
+
//
|
|
4
|
+
// There is no curated descriptor registry: every board's chip view is
|
|
5
|
+
// reconstructed from its generated board manifest via resolveChipFromBoard
|
|
6
|
+
// (src/chips/resolve.ts). This module only caches that resolved descriptor
|
|
7
|
+
// for the process lifetime (setActiveChip during profile resolution, the
|
|
8
|
+
// lowering reads getActiveChip) and provides the empty fallback for
|
|
9
|
+
// contexts with no board at all.
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
import type { ZephyrChipDescriptor } from './types.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The no-board fallback: no controllers, no buses, no silicon facts. The
|
|
16
|
+
* lowering treats it as "unsupported operation" per subsystem, which is the
|
|
17
|
+
* honest answer when no board resolved.
|
|
18
|
+
*/
|
|
19
|
+
export const NO_BOARD_CHIP: ZephyrChipDescriptor = {
|
|
20
|
+
id: 'no-board',
|
|
21
|
+
soc: '',
|
|
22
|
+
gpioController: 'gpio0',
|
|
23
|
+
gpio: { dtSpecs: [] },
|
|
24
|
+
probeMethods: [],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
let activeChip: ZephyrChipDescriptor = NO_BOARD_CHIP;
|
|
28
|
+
|
|
29
|
+
export function setActiveChip(d: ZephyrChipDescriptor): void {
|
|
30
|
+
activeChip = d;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function getActiveChip(): ZephyrChipDescriptor {
|
|
34
|
+
return activeChip;
|
|
35
|
+
}
|
package/src/chips/resolve.ts
CHANGED
|
@@ -7,20 +7,22 @@
|
|
|
7
7
|
// (from the MCU package's zephyr field) with board-level overrides (from the
|
|
8
8
|
// board package's zephyr field).
|
|
9
9
|
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
10
|
+
// This is the ONE resolution path: every board's chip view reconstructs
|
|
11
|
+
// from its generated manifest — there is no curated registry to fall back
|
|
12
|
+
// to.
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
14
|
|
|
15
15
|
import type { BoardConstants } from '@typecad/cuttlefish/api/shared';
|
|
16
16
|
import type {
|
|
17
17
|
ZephyrChipDescriptor,
|
|
18
|
+
ZephyrProbeMethod,
|
|
18
19
|
ZephyrGpioDtSpec,
|
|
19
20
|
ZephyrGpioController,
|
|
20
21
|
ZephyrBusController,
|
|
21
22
|
ZephyrPwmSpec,
|
|
22
23
|
ZephyrInterruptPin,
|
|
23
24
|
ZephyrAdcChannel,
|
|
25
|
+
ZephyrDacChannel,
|
|
24
26
|
} from './types.js';
|
|
25
27
|
|
|
26
28
|
/** Collect an indexed array of objects reconstructed from flat dot-path keys. */
|
|
@@ -49,7 +51,34 @@ function collectBusControllers(
|
|
|
49
51
|
): ZephyrBusController[] {
|
|
50
52
|
return collectIndexed<ZephyrBusController>(bc, prefix, (m, i) => {
|
|
51
53
|
const nodeLabel = m.get(`${prefix}.${i}.nodeLabel`) as string;
|
|
52
|
-
|
|
54
|
+
if (!nodeLabel) return null;
|
|
55
|
+
// Optional pinctrl synthesis data (nested object; string arrays arrive
|
|
56
|
+
// comma-joined from the board-constants flattener).
|
|
57
|
+
const splitCsv = (v: unknown): string[] | undefined =>
|
|
58
|
+
typeof v === 'string' && v.length > 0
|
|
59
|
+
? v.split(',').map((s) => s.trim()).filter(Boolean)
|
|
60
|
+
: undefined;
|
|
61
|
+
const include = m.get(`${prefix}.${i}.pinctrl.include`) as string | undefined;
|
|
62
|
+
const pinmux = splitCsv(m.get(`${prefix}.${i}.pinctrl.pinmux`));
|
|
63
|
+
const inputPinmux = splitCsv(m.get(`${prefix}.${i}.pinctrl.inputPinmux`));
|
|
64
|
+
const defines = splitCsv(m.get(`${prefix}.${i}.pinctrl.defines`));
|
|
65
|
+
const pinctrlRef = m.get(`${prefix}.${i}.pinctrlRef`) as string | undefined;
|
|
66
|
+
const props = splitCsv(m.get(`${prefix}.${i}.props`));
|
|
67
|
+
return {
|
|
68
|
+
nodeLabel,
|
|
69
|
+
...(include && pinmux
|
|
70
|
+
? {
|
|
71
|
+
pinctrl: {
|
|
72
|
+
include,
|
|
73
|
+
pinmux,
|
|
74
|
+
...(inputPinmux ? { inputPinmux } : {}),
|
|
75
|
+
...(defines ? { defines } : {}),
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
: {}),
|
|
79
|
+
...(pinctrlRef ? { pinctrlRef } : {}),
|
|
80
|
+
...(props ? { props } : {}),
|
|
81
|
+
};
|
|
53
82
|
});
|
|
54
83
|
}
|
|
55
84
|
|
|
@@ -57,7 +86,7 @@ function collectBusControllers(
|
|
|
57
86
|
* Try to derive a ZephyrChipDescriptor from board/MCU package constants.
|
|
58
87
|
*
|
|
59
88
|
* Returns null when no zephyr info is available in the board constants
|
|
60
|
-
* (the caller should
|
|
89
|
+
* (the caller should treat the board as unresolved — NO_BOARD_CHIP).
|
|
61
90
|
*/
|
|
62
91
|
export function resolveChipFromBoard(
|
|
63
92
|
bc: BoardConstants | undefined,
|
|
@@ -65,10 +94,25 @@ export function resolveChipFromBoard(
|
|
|
65
94
|
if (!bc) return null;
|
|
66
95
|
|
|
67
96
|
const boardTarget = bc.get('build.frameworks.zephyr') as string | undefined;
|
|
68
|
-
|
|
97
|
+
// MCU-silicon entry: an MCU-only config (no board package) carries the
|
|
98
|
+
// chip facts under zephyr.* without any build.frameworks target (the
|
|
99
|
+
// build target comes from frameworkData instead — a custom board name).
|
|
100
|
+
const socsRaw = bc.get('zephyr.socs') as string | undefined;
|
|
101
|
+
if (!boardTarget && !socsRaw) return null;
|
|
102
|
+
|
|
103
|
+
const socs = typeof socsRaw === 'string' && socsRaw.length > 0
|
|
104
|
+
? socsRaw.split(',').map((s) => s.trim()).filter(Boolean)
|
|
105
|
+
: [];
|
|
106
|
+
// Chip identity: the board target when a board resolved it, else the SoC
|
|
107
|
+
// (an MCU-only chip — its "board" is the generated custom board).
|
|
108
|
+
const id = boardTarget ?? socs[0] ?? 'custom';
|
|
69
109
|
|
|
70
110
|
const zGpioController = bc.get('zephyr.gpioController') as string | undefined;
|
|
71
|
-
|
|
111
|
+
// The soc name: MCU packages key it under mcu.id; generated board
|
|
112
|
+
// manifests carry it as the second segment of the qualified target.
|
|
113
|
+
const soc = (bc.get('mcu.id') as string)
|
|
114
|
+
?? (socs.length > 0 ? socs[0] : undefined)
|
|
115
|
+
?? (boardTarget && boardTarget.includes('/') ? boardTarget.split('/')[1] : '');
|
|
72
116
|
|
|
73
117
|
// ── Build mutable sub-objects, then construct the final descriptor ──────
|
|
74
118
|
|
|
@@ -107,6 +151,7 @@ export function resolveChipFromBoard(
|
|
|
107
151
|
const channel = m.get(`zephyr.pwm.specs.${i}.channel`) as number | undefined;
|
|
108
152
|
const periodNs = m.get(`zephyr.pwm.specs.${i}.periodNs`) as number | undefined;
|
|
109
153
|
const polarity = m.get(`zephyr.pwm.specs.${i}.polarity`) as string | undefined;
|
|
154
|
+
const pinctrl = m.get(`zephyr.pwm.specs.${i}.pinctrl`) as string | undefined;
|
|
110
155
|
// Board-shipped alias form (dtSpec) or synthesized form (controller +
|
|
111
156
|
// channel → overlay-generated alias) — at least one, else drop the entry.
|
|
112
157
|
if (pin == null || !(dtSpec || (controller && channel != null))) return null;
|
|
@@ -117,10 +162,26 @@ export function resolveChipFromBoard(
|
|
|
117
162
|
...(channel != null ? { channel } : {}),
|
|
118
163
|
...(periodNs != null ? { periodNs } : {}),
|
|
119
164
|
...(polarity ? { polarity } : {}),
|
|
165
|
+
...(pinctrl ? { pinctrl } : {}),
|
|
120
166
|
};
|
|
121
167
|
});
|
|
122
168
|
|
|
123
169
|
const adcNodeLabel = bc.get('zephyr.adc.nodeLabel') as string | undefined;
|
|
170
|
+
// PWM timer input clock — feeds the overlay's 16-bit prescaler derivation.
|
|
171
|
+
const pwmClockHz = bc.get('zephyr.pwm.clockHz') as number | undefined;
|
|
172
|
+
|
|
173
|
+
// PWM matrix (ESP32 LEDC): any listed pin can carry any channel; channels
|
|
174
|
+
// are assigned to the driven pins at build time (dt-config/overlay.ts).
|
|
175
|
+
const matrixController = bc.get('zephyr.pwm.matrix.controller') as string | undefined;
|
|
176
|
+
const matrixChannelCount = bc.get('zephyr.pwm.matrix.channelCount') as number | undefined;
|
|
177
|
+
const matrixPins = collectIndexed<number>(
|
|
178
|
+
bc, 'zephyr.pwm.matrix.pins',
|
|
179
|
+
(m, i) => (m.get(`zephyr.pwm.matrix.pins.${i}`) as number | undefined) ?? null,
|
|
180
|
+
);
|
|
181
|
+
const pwmMatrix = matrixController && matrixChannelCount
|
|
182
|
+
? { controller: matrixController, channelCount: matrixChannelCount, pins: matrixPins }
|
|
183
|
+
: undefined;
|
|
184
|
+
|
|
124
185
|
const adcResolution = bc.get('zephyr.adc.resolution') as number | undefined;
|
|
125
186
|
const adcVref = bc.get('zephyr.adc.vrefMv') as number | undefined;
|
|
126
187
|
const adcGain = bc.get('zephyr.adc.gain') as string | undefined;
|
|
@@ -129,15 +190,140 @@ export function resolveChipFromBoard(
|
|
|
129
190
|
const pin = m.get(`zephyr.adc.channels.${i}.pin`) as number;
|
|
130
191
|
const channel = m.get(`zephyr.adc.channels.${i}.channel`) as number;
|
|
131
192
|
const pinctrl = m.get(`zephyr.adc.channels.${i}.pinctrl`) as string | undefined;
|
|
193
|
+
const controller = m.get(`zephyr.adc.channels.${i}.controller`) as string | undefined;
|
|
132
194
|
if (pin != null && channel != null) {
|
|
133
|
-
return { pin, channel, ...(pinctrl ? { pinctrl } : {}) };
|
|
195
|
+
return { pin, channel, ...(pinctrl ? { pinctrl } : {}), ...(controller ? { controller } : {}) };
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
const dacDevice = bc.get('zephyr.dac.device') as string | undefined;
|
|
201
|
+
const dacChannels = collectIndexed<ZephyrDacChannel>(bc, 'zephyr.dac.channels', (m, i) => {
|
|
202
|
+
const pin = m.get(`zephyr.dac.channels.${i}.pin`) as number;
|
|
203
|
+
const channel = m.get(`zephyr.dac.channels.${i}.channel`) as number;
|
|
204
|
+
const resolution = m.get(`zephyr.dac.channels.${i}.resolution`) as number | undefined;
|
|
205
|
+
if (pin != null && channel != null) {
|
|
206
|
+
return { pin, channel, resolution: resolution ?? 12 };
|
|
134
207
|
}
|
|
135
208
|
return null;
|
|
136
209
|
});
|
|
137
210
|
|
|
138
211
|
const wdtNodeLabel = bc.get('zephyr.wdt.nodeLabel') as string | undefined;
|
|
212
|
+
|
|
213
|
+
// Hardware counters (Zephyr counter devices): nodeLabel always; the child
|
|
214
|
+
// form carries the timer parent the overlay attaches the (label-less)
|
|
215
|
+
// counter child to.
|
|
216
|
+
const hwtimerControllers = collectIndexed<ZephyrBusController>(bc, 'zephyr.hwtimer.controllers', (m, i) => {
|
|
217
|
+
const nodeLabel = m.get(`zephyr.hwtimer.controllers.${i}.nodeLabel`) as string;
|
|
218
|
+
const counterParent = m.get(`zephyr.hwtimer.controllers.${i}.counterParent`) as string | undefined;
|
|
219
|
+
if (!nodeLabel) return null;
|
|
220
|
+
return { nodeLabel, ...(counterParent ? { counterParent } : {}) };
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// Storage partition synthesis (boards whose DTS ships no storage_partition
|
|
224
|
+
// — see ZephyrChipDescriptor.storage).
|
|
225
|
+
const storageOffset = bc.get('zephyr.storage.offset') as number | undefined;
|
|
226
|
+
const storageSize = bc.get('zephyr.storage.size') as number | undefined;
|
|
227
|
+
const storagePreexisting = bc.get('zephyr.storage.preexisting') as boolean | undefined;
|
|
228
|
+
|
|
229
|
+
// USB device (CDC-ACM): zephyr.usb.controller + zephyr.usb.cdcInstances
|
|
230
|
+
// (+ optional vid/pid for the device descriptor).
|
|
231
|
+
const usbController = bc.get('zephyr.usb.controller') as string | undefined;
|
|
232
|
+
const usbCdcInstances = bc.get('zephyr.usb.cdcInstances') as number | undefined;
|
|
233
|
+
const usbVid = bc.get('zephyr.usb.vid') as string | undefined;
|
|
234
|
+
const usbPid = bc.get('zephyr.usb.pid') as string | undefined;
|
|
235
|
+
// Optional 1200-baud touch-to-reset data (BOSSA-bootloader boards).
|
|
236
|
+
const trFlag = bc.get('zephyr.usb.touchReset.flagAddress') as number | undefined;
|
|
237
|
+
const trMagic = bc.get('zephyr.usb.touchReset.magic') as number | undefined;
|
|
238
|
+
const trVid = bc.get('zephyr.usb.touchReset.bootloaderVid') as string | undefined;
|
|
239
|
+
const trPid = bc.get('zephyr.usb.touchReset.bootloaderPid') as string | undefined;
|
|
240
|
+
|
|
241
|
+
const probeMethods = collectIndexed<ZephyrProbeMethod>(bc, 'zephyr.probeMethods', (m, i) => { const id = m.get(`zephyr.probeMethods.${i}.id`) as string;
|
|
242
|
+
const runner = m.get(`zephyr.probeMethods.${i}.runner`) as string;
|
|
243
|
+
if (!id || !runner) return null;
|
|
244
|
+
const argsRaw = m.get(`zephyr.probeMethods.${i}.args`) as string | undefined;
|
|
245
|
+
const description = m.get(`zephyr.probeMethods.${i}.description`) as string | undefined;
|
|
246
|
+
const debugRaw = m.get(`zephyr.probeMethods.${i}.debug`) as boolean | undefined;
|
|
247
|
+
const debugInterface = m.get(`zephyr.probeMethods.${i}.debugInterface`) as string | undefined;
|
|
248
|
+
const debugDevice = m.get(`zephyr.probeMethods.${i}.debugDevice`) as string | undefined;
|
|
249
|
+
const debugCfgRaw = m.get(`zephyr.probeMethods.${i}.debugCfg`) as string | undefined;
|
|
250
|
+
const debugCfgSourceRaw = m.get(`zephyr.probeMethods.${i}.debugCfgSource`) as string | undefined;
|
|
251
|
+
// Args are comma-joined (west flags never carry commas); cfg lines are
|
|
252
|
+
// newline-joined (tcl legally contains commas).
|
|
253
|
+
const split = (v: string | undefined): string[] | undefined =>
|
|
254
|
+
typeof v === 'string' && v.length > 0 ? v.split(',') : undefined;
|
|
255
|
+
const splitLines = (v: string | undefined): string[] | undefined =>
|
|
256
|
+
typeof v === 'string' && v.length > 0 ? v.split('\n') : undefined;
|
|
257
|
+
const args = split(argsRaw);
|
|
258
|
+
return {
|
|
259
|
+
id,
|
|
260
|
+
runner,
|
|
261
|
+
...(args ? { args } : {}),
|
|
262
|
+
...(description ? { description } : {}),
|
|
263
|
+
...(debugRaw !== undefined ? { debug: debugRaw } : {}),
|
|
264
|
+
...(debugInterface ? { debugInterface: debugInterface as 'swd' | 'jtag' } : {}),
|
|
265
|
+
...(debugDevice ? { debugDevice } : {}),
|
|
266
|
+
...(split(debugCfgRaw) ? { debugCfg: splitLines(debugCfgRaw) } : {}),
|
|
267
|
+
...(split(debugCfgSourceRaw) ? { debugCfgSource: splitLines(debugCfgSourceRaw) } : {}),
|
|
268
|
+
};
|
|
269
|
+
});
|
|
139
270
|
const wifiSupported = bc.get('zephyr.wifi.supported') as boolean | undefined;
|
|
140
271
|
|
|
272
|
+
// ── Custom-board generator inputs (MCU silicon) ─────────────────────────
|
|
273
|
+
// Only complete when the MCU package carried a default console + clock
|
|
274
|
+
// plan — without those there is nothing to generate a board from.
|
|
275
|
+
const consoleNodeLabel = bc.get('zephyr.console.nodeLabel') as string | undefined;
|
|
276
|
+
const consoleTx = bc.get('zephyr.console.tx') as string | undefined;
|
|
277
|
+
const consoleRx = bc.get('zephyr.console.rx') as string | undefined;
|
|
278
|
+
const consoleSpeed = bc.get('zephyr.console.speed') as number | undefined;
|
|
279
|
+
const hseMHz = bc.get('zephyr.clocks.hseMHz') as number | undefined;
|
|
280
|
+
const pllDivM = bc.get('zephyr.clocks.pll.divM') as number | undefined;
|
|
281
|
+
const pllMulN = bc.get('zephyr.clocks.pll.mulN') as number | undefined;
|
|
282
|
+
const pllDivP = bc.get('zephyr.clocks.pll.divP') as number | undefined;
|
|
283
|
+
const pllDivQ = bc.get('zephyr.clocks.pll.divQ') as number | undefined;
|
|
284
|
+
const sysMHz = bc.get('zephyr.clocks.sysMHz') as number | undefined;
|
|
285
|
+
const dtsIncludesRaw = bc.get('zephyr.dtsIncludes') as string | undefined;
|
|
286
|
+
const usbNode = bc.get('zephyr.usb.usbNode') as string | undefined;
|
|
287
|
+
const usbPinctrlRaw = bc.get('zephyr.usb.pinctrl') as string | undefined;
|
|
288
|
+
const usbPinctrl = typeof usbPinctrlRaw === 'string' && usbPinctrlRaw.length > 0
|
|
289
|
+
? usbPinctrlRaw.split(',').map((s) => s.trim()).filter(Boolean)
|
|
290
|
+
: undefined;
|
|
291
|
+
const cbAdcNodeLabel = bc.get('zephyr.adcNode.nodeLabel') as string | undefined;
|
|
292
|
+
const cbAdcClockSource = bc.get('zephyr.adcNode.clockSource') as string | undefined;
|
|
293
|
+
const cbAdcPrescaler = bc.get('zephyr.adcNode.prescaler') as number | undefined;
|
|
294
|
+
const cbAdcPinctrl = bc.get('zephyr.adcNode.pinctrl') as string | undefined;
|
|
295
|
+
const customBoard =
|
|
296
|
+
socs.length > 0 &&
|
|
297
|
+
consoleNodeLabel && consoleTx && consoleRx &&
|
|
298
|
+
hseMHz != null && pllDivM != null && pllMulN != null && pllDivP != null &&
|
|
299
|
+
pllDivQ != null && sysMHz != null
|
|
300
|
+
? {
|
|
301
|
+
socs,
|
|
302
|
+
dtsIncludes: typeof dtsIncludesRaw === 'string' && dtsIncludesRaw.length > 0
|
|
303
|
+
? dtsIncludesRaw.split(',').map((s) => s.trim()).filter(Boolean)
|
|
304
|
+
: [],
|
|
305
|
+
console: {
|
|
306
|
+
nodeLabel: consoleNodeLabel,
|
|
307
|
+
tx: consoleTx,
|
|
308
|
+
rx: consoleRx,
|
|
309
|
+
speed: consoleSpeed ?? 115200,
|
|
310
|
+
},
|
|
311
|
+
clocks: {
|
|
312
|
+
hseMHz,
|
|
313
|
+
pll: { divM: pllDivM, mulN: pllMulN, divP: pllDivP, divQ: pllDivQ },
|
|
314
|
+
sysMHz,
|
|
315
|
+
ahbPrescaler: (bc.get('zephyr.clocks.ahbPrescaler') as number) ?? 1,
|
|
316
|
+
apb1Prescaler: (bc.get('zephyr.clocks.apb1Prescaler') as number) ?? 1,
|
|
317
|
+
apb2Prescaler: (bc.get('zephyr.clocks.apb2Prescaler') as number) ?? 1,
|
|
318
|
+
},
|
|
319
|
+
...(usbNode ? { usbNode } : {}),
|
|
320
|
+
...(usbPinctrl ? { usbPinctrl } : {}),
|
|
321
|
+
...(cbAdcNodeLabel && cbAdcClockSource && cbAdcPrescaler != null && cbAdcPinctrl
|
|
322
|
+
? { adcNode: { nodeLabel: cbAdcNodeLabel, clockSource: cbAdcClockSource, prescaler: cbAdcPrescaler, pinctrl: cbAdcPinctrl } }
|
|
323
|
+
: {}),
|
|
324
|
+
}
|
|
325
|
+
: undefined;
|
|
326
|
+
|
|
141
327
|
// ── Construct the final readonly descriptor ─────────────────────────────
|
|
142
328
|
|
|
143
329
|
const gpio: ZephyrChipDescriptor['gpio'] = {
|
|
@@ -146,7 +332,7 @@ export function resolveChipFromBoard(
|
|
|
146
332
|
};
|
|
147
333
|
|
|
148
334
|
return {
|
|
149
|
-
id
|
|
335
|
+
id,
|
|
150
336
|
soc,
|
|
151
337
|
gpioController: zGpioController ?? 'gpio0',
|
|
152
338
|
...(gc.length > 0 ? { gpioControllers: gc } : {}),
|
|
@@ -154,7 +340,15 @@ export function resolveChipFromBoard(
|
|
|
154
340
|
...(i2cControllers.length > 0 ? { i2c: { controllers: i2cControllers } } : {}),
|
|
155
341
|
...(spiControllers.length > 0 ? { spi: { controllers: spiControllers } } : {}),
|
|
156
342
|
...(uartControllers.length > 0 ? { uart: { controllers: uartControllers } } : {}),
|
|
157
|
-
...(pwmSpecs.length > 0
|
|
343
|
+
...(pwmSpecs.length > 0 || pwmMatrix
|
|
344
|
+
? {
|
|
345
|
+
pwm: {
|
|
346
|
+
specs: pwmSpecs,
|
|
347
|
+
...(pwmMatrix ? { matrix: pwmMatrix } : {}),
|
|
348
|
+
...(pwmClockHz ? { clockHz: pwmClockHz } : {}),
|
|
349
|
+
},
|
|
350
|
+
}
|
|
351
|
+
: {}),
|
|
158
352
|
...(adcNodeLabel || adcResolution != null || adcVref != null || adcChannels.length > 0
|
|
159
353
|
? {
|
|
160
354
|
adc: {
|
|
@@ -167,7 +361,88 @@ export function resolveChipFromBoard(
|
|
|
167
361
|
},
|
|
168
362
|
}
|
|
169
363
|
: {}),
|
|
364
|
+
...(dacDevice && dacChannels.length > 0 ? { dac: { device: dacDevice, channels: dacChannels } } : {}),
|
|
170
365
|
...(wdtNodeLabel ? { wdt: { nodeLabel: wdtNodeLabel } } : {}),
|
|
366
|
+
...(hwtimerControllers.length > 0 ? { hwtimer: { controllers: hwtimerControllers } } : {}),
|
|
367
|
+
...(storageOffset != null && storageSize != null
|
|
368
|
+
? { storage: { offset: storageOffset, size: storageSize, ...(storagePreexisting ? { preexisting: true } : {}) } }
|
|
369
|
+
: {}),
|
|
370
|
+
...(usbController && usbCdcInstances && usbCdcInstances > 0
|
|
371
|
+
? {
|
|
372
|
+
usb: {
|
|
373
|
+
controller: usbController,
|
|
374
|
+
cdcInstances: usbCdcInstances,
|
|
375
|
+
...(usbVid ? { vid: usbVid } : {}),
|
|
376
|
+
...(usbPid ? { pid: usbPid } : {}),
|
|
377
|
+
...(trFlag != null && trMagic != null
|
|
378
|
+
? {
|
|
379
|
+
touchReset: {
|
|
380
|
+
flagAddress: trFlag,
|
|
381
|
+
magic: trMagic,
|
|
382
|
+
...(trVid ? { bootloaderVid: trVid } : {}),
|
|
383
|
+
...(trPid ? { bootloaderPid: trPid } : {}),
|
|
384
|
+
},
|
|
385
|
+
}
|
|
386
|
+
: {}),
|
|
387
|
+
},
|
|
388
|
+
}
|
|
389
|
+
: {}),
|
|
171
390
|
...(wifiSupported ? { wifi: { supported: true as const } } : {}),
|
|
391
|
+
...(probeMethods.length > 0 ? { probeMethods } : {}),
|
|
392
|
+
...(customBoard ? { customBoard } : {}),
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Board-level PWM specs from the generated board manifest (zephyr.pwm.specs.*
|
|
398
|
+
* — the pwm-leds facts boardgen emits on virtual pins 8192+). The active
|
|
399
|
+
* chip's spec table is silicon-curated; these JOIN it (see mergeBoardPwmSpecs)
|
|
400
|
+
* so a board's own devicetree-aliased PWM LED is addressable without curation.
|
|
401
|
+
*/
|
|
402
|
+
export function boardPwmSpecsFromConstants(
|
|
403
|
+
bc: BoardConstants | undefined,
|
|
404
|
+
): ZephyrPwmSpec[] {
|
|
405
|
+
if (!bc) return [];
|
|
406
|
+
const specs: ZephyrPwmSpec[] = [];
|
|
407
|
+
for (let i = 0; i < 256; i++) {
|
|
408
|
+
const pin = bc.get(`zephyr.pwm.specs.${i}.pin`) as number | undefined;
|
|
409
|
+
if (pin == null) break;
|
|
410
|
+
const dtSpec = bc.get(`zephyr.pwm.specs.${i}.dtSpec`) as string | undefined;
|
|
411
|
+
const controller = bc.get(`zephyr.pwm.specs.${i}.controller`) as string | undefined;
|
|
412
|
+
const channel = bc.get(`zephyr.pwm.specs.${i}.channel`) as number | undefined;
|
|
413
|
+
if (!(dtSpec || (controller && channel != null))) continue;
|
|
414
|
+
specs.push({
|
|
415
|
+
pin,
|
|
416
|
+
...(dtSpec ? { dtSpec } : {}),
|
|
417
|
+
...(controller ? { controller } : {}),
|
|
418
|
+
...(channel != null ? { channel } : {}),
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
return specs;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Merge board-level PWM specs into a chip descriptor. Collision rule: a
|
|
426
|
+
* board spec whose pin OR dtSpec already exists in the chip's table is
|
|
427
|
+
* dropped (the curated entry wins — e.g. the XIAO's hand-tuned pwm-led0
|
|
428
|
+
* spec). Returns the chip unchanged when nothing joins.
|
|
429
|
+
*/
|
|
430
|
+
export function mergeBoardPwmSpecs(
|
|
431
|
+
chip: ZephyrChipDescriptor,
|
|
432
|
+
boardSpecs: readonly ZephyrPwmSpec[],
|
|
433
|
+
): ZephyrChipDescriptor {
|
|
434
|
+
if (boardSpecs.length === 0) return chip;
|
|
435
|
+
const existing = chip.pwm?.specs ?? [];
|
|
436
|
+
const joining = boardSpecs.filter(
|
|
437
|
+
(s) => !existing.some((e) => e.pin === s.pin || (s.dtSpec != null && e.dtSpec === s.dtSpec)),
|
|
438
|
+
);
|
|
439
|
+
if (joining.length === 0) return chip;
|
|
440
|
+
return {
|
|
441
|
+
...chip,
|
|
442
|
+
pwm: {
|
|
443
|
+
specs: [...existing, ...joining],
|
|
444
|
+
...(chip.pwm?.matrix ? { matrix: chip.pwm.matrix } : {}),
|
|
445
|
+
...(chip.pwm?.clockHz ? { clockHz: chip.pwm.clockHz } : {}),
|
|
446
|
+
},
|
|
172
447
|
};
|
|
173
448
|
}
|