@typecad/framework-zephyr 1.0.0-alpha.14 → 1.0.0-alpha.16
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 +226 -76
- package/dist/toolchain/env-check.d.ts +4 -4
- package/dist/toolchain/env-check.js +5 -5
- package/dist/toolchain/index.d.ts +115 -1
- package/dist/toolchain/index.js +680 -71
- 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 +676 -522
- package/src/toolchain/env-check.ts +9 -9
- package/src/toolchain/index.ts +1359 -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/README.md
CHANGED
|
@@ -24,86 +24,61 @@ fix (`pip install west`, set `ZEPHYR_BASE`, or activate the venv).
|
|
|
24
24
|
|
|
25
25
|
## How it works
|
|
26
26
|
|
|
27
|
-
- HAL ops (`gpio.write`, `i2c.
|
|
28
|
-
(`gpio_pin_set_dt`, `
|
|
27
|
+
- HAL ops (`gpio.write`, `i2c.reg_read`, etc.) lower to native Zephyr driver
|
|
28
|
+
calls (`gpio_pin_set_dt`, `i2c_reg_read_byte`, etc.) — no Arduino API.
|
|
29
29
|
- The generated `src/main.cpp` defines `int main(void)` — the standard Zephyr
|
|
30
|
-
C entry point.
|
|
31
|
-
`loop()`
|
|
32
|
-
|
|
30
|
+
C entry point. Top-level statements lower straight into `main()` (no
|
|
31
|
+
`setup()`/`loop()` pair); event-driven programs get their scheduler loop
|
|
32
|
+
appended inside `main()` by the driver machinery.
|
|
33
33
|
- The framework emits a complete Zephyr application: root `CMakeLists.txt`
|
|
34
34
|
(`find_package(Zephyr)` + `file(GLOB src/*.cpp)`) and `prj.conf` (the Kconfig
|
|
35
35
|
symbols for the lowered peripherals). Both are regenerated idempotently —
|
|
36
36
|
only rewritten when their content changes, so Ninja's incremental build is
|
|
37
37
|
preserved.
|
|
38
|
-
-
|
|
39
|
-
**
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
board
|
|
43
|
-
**Pico 2** (`rpi_pico2/rp2350a/m33`), and **WeAct Black Pill V2.0**
|
|
44
|
-
(`blackpill_f411ce/stm32f411xe` — the first STM32 target; flashed over USB
|
|
45
|
-
via the ROM DFU bootloader). The rpi_pico, esp32c3, esp32c6, and blackpill
|
|
46
|
-
boards resolve their chip data from the board packages' `zephyr` field (see
|
|
47
|
-
`resolveChipFromBoard`) rather than the hardcoded chip registry; the
|
|
48
|
-
qualified Pico 2 target selects the Cortex-M33 cpucluster (Zephyr 4.3+
|
|
49
|
-
rejects the bare `rpi_pico2` because the board also ships a Hazard3 variant
|
|
50
|
-
with no default).
|
|
38
|
+
- Board targets are not curated: **every board variant in the generated board
|
|
39
|
+
catalog** resolves the same way (`resolveChipFromBoard` over the catalog's
|
|
40
|
+
board data — there is no hardcoded chip registry or target list). The
|
|
41
|
+
catalog is machine-local, generated from your Zephyr tree by
|
|
42
|
+
`cuttlefish board sync` (and refreshed automatically by builds).
|
|
51
43
|
|
|
52
44
|
## Installation
|
|
53
45
|
|
|
54
46
|
```sh
|
|
55
|
-
cuttlefish
|
|
47
|
+
cuttlefish create # pick a board from the catalog; the Zephyr framework is the default
|
|
56
48
|
```
|
|
57
49
|
|
|
58
50
|
Or in `cuttlefish.config.ts`:
|
|
59
51
|
|
|
60
52
|
```ts
|
|
61
53
|
export default {
|
|
54
|
+
entry: './src/main.ts',
|
|
55
|
+
board: 'xiao_ble/nrf52840',
|
|
62
56
|
framework: '@typecad/framework-zephyr',
|
|
63
|
-
frameworkData: {
|
|
64
|
-
buildTarget: 'xiao_ble',
|
|
65
|
-
},
|
|
66
|
-
toolchain: { type: 'west' },
|
|
67
57
|
};
|
|
68
58
|
```
|
|
69
59
|
|
|
70
60
|
## HAL coverage
|
|
71
61
|
|
|
72
62
|
The manifest (`src/framework.manifest.ts`) is the honest, complete record of
|
|
73
|
-
what lowers. Fully
|
|
74
|
-
|
|
75
|
-
**random** (xorshift32 PRNG seeded from the Zephyr entropy tap)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
**
|
|
63
|
+
what lowers. Fully lowered: **gpio, pwm, adc, dac** (pin-fact-gated),
|
|
64
|
+
**i2c, spi, uart, interrupts, timing, wdt, counter, thread, shift, board
|
|
65
|
+
constants**, **random** (xorshift32 PRNG seeded from the Zephyr entropy tap),
|
|
66
|
+
**preferences (Store)**, **fs (File)**, **sensor**, **ble**, **snprintf**, and
|
|
67
|
+
**wifi/http/mqtt** (ESP32-class radio targets only — nRF52840 has no WiFi).
|
|
68
|
+
**Display** lowers via the generic `<zephyr/drivers/display.h>` GFX runtime.
|
|
69
|
+
Declared unsupported on this target: **i2s, twai/CAN, ethernet, espnow,
|
|
70
|
+
hardware crypto, pcnt, mcpwm**. USB CDC is board-gated: it lowers only on
|
|
71
|
+
boards whose DTS enables the USB device controller.
|
|
80
72
|
|
|
81
73
|
Run `npm test` (the manifest validator) to confirm the declared coverage matches
|
|
82
74
|
the actual lowering behavior.
|
|
83
75
|
|
|
84
|
-
## Hardware tests
|
|
85
|
-
|
|
86
|
-
On-device tests live in `tests/`. Run them against real hardware:
|
|
87
|
-
|
|
88
|
-
```sh
|
|
89
|
-
npm run test:hw # all groups
|
|
90
|
-
npm run test:hw:gpio # just GPIO
|
|
91
|
-
npm run test:hw:timers # just timing
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
Update `test.port` in `cuttlefish.config.ts` to your XIAO's serial device
|
|
95
|
-
before running. The tests transpile → `west build` → flash → read results over
|
|
96
|
-
the console.
|
|
97
|
-
|
|
98
76
|
## Notes / limitations
|
|
99
77
|
|
|
100
78
|
- **Minimal C++ libc.** Zephyr's default C++ support (`lib/cpp/minimal`) has no
|
|
101
79
|
`<vector>`, `<string>`, `<iostream>`, `<functional>`, exceptions, or RTTI.
|
|
102
80
|
`prj.conf` enables `CONFIG_NEWLIB_LIBC` for `std::string`/`std::vector`; array
|
|
103
81
|
literals still promote to the StaticArray wrapper, not `std::vector`.
|
|
104
|
-
- **Timer ops unsupported.** `timing.set_interval`/`set_timeout`/`clear_*` need
|
|
105
|
-
a polyfill-backed async runtime this framework does not emit yet. A Zephyr
|
|
106
|
-
workqueue / `k_thread` backing is a follow-on.
|
|
107
82
|
- **Debug mode.** `cuttlefish build --debug` routes through `printk` (always
|
|
108
83
|
available, no `CONFIG_CONSOLE` dependency) rather than `std::cout`, since the
|
|
109
84
|
minimal libc has no iostream. Breakpoints halt on console input (`ENTER`
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface AsBuiltRoute {
|
|
2
|
+
source: string;
|
|
3
|
+
channel: number;
|
|
4
|
+
port: string;
|
|
5
|
+
bit: number;
|
|
6
|
+
pinctrl: string;
|
|
7
|
+
}
|
|
8
|
+
export interface AsBuiltFacts {
|
|
9
|
+
adc: AsBuiltRoute[];
|
|
10
|
+
pwm: AsBuiltRoute[];
|
|
11
|
+
dac: AsBuiltRoute[];
|
|
12
|
+
}
|
|
13
|
+
/** The .cuttlefish/as-built.json shape (machine-authored facts file). */
|
|
14
|
+
export interface AsBuiltFile {
|
|
15
|
+
version: 1;
|
|
16
|
+
board: string;
|
|
17
|
+
generatedAt: string;
|
|
18
|
+
routes: {
|
|
19
|
+
adcPins: AsBuiltRoute[];
|
|
20
|
+
pwmPins: AsBuiltRoute[];
|
|
21
|
+
dacPins: AsBuiltRoute[];
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Parse a resolved zephyr.dts into raw pin routes. Labels are matched as
|
|
26
|
+
* whole tokens (`label:` or `label {`) — in dtc output every node carries
|
|
27
|
+
* its labels inline before the node name.
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseZephyrDts(text: string): AsBuiltFacts;
|
|
30
|
+
/** Parse + shape-validate .cuttlefish/as-built.json; errors name the file. */
|
|
31
|
+
export declare function parseAsBuiltJson(text: string, source?: string): AsBuiltFile;
|
|
32
|
+
/** Serialize the as-built snapshot (deterministic field order). */
|
|
33
|
+
export declare function asBuiltJson(board: string, facts: AsBuiltFacts): string;
|
package/dist/as-built.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// as-built.ts — harvest pin routes from a build's resolved zephyr.dts
|
|
3
|
+
//
|
|
4
|
+
// The third fact source: after any successful `west build`, the fully
|
|
5
|
+
// merged devicetree at <build>/zephyr/zephyr.dts contains the board's
|
|
6
|
+
// pinctrl nodes with LABELS verbatim — the stable name grammar
|
|
7
|
+
// (`adc1_in1_pa1`, `tim4_ch1_pb6`, `iomuxc_<pad>_adc1_in1`) — with the
|
|
8
|
+
// vendor macro values already expanded away. Parsing names only needs ONE
|
|
9
|
+
// grammar per shape, immune to vendor macro churn, and corrects a broken
|
|
10
|
+
// catalog harvest per-pin before the next build (the walker's macro-value
|
|
11
|
+
// grammars are the fragile half; this is the robust half).
|
|
12
|
+
//
|
|
13
|
+
// Scope is honest: only node-name families appear (STM32-style dtsi nodes
|
|
14
|
+
// and the i.MX RT label grammar with its in-band pad join). Header-matrix
|
|
15
|
+
// families (Kinetis/LPC/GD32 macro routing, ESP32/RP2 matrices) never
|
|
16
|
+
// exist as DT nodes — the walker + family tables remain their source.
|
|
17
|
+
// ----------------------------------------------------------------------------
|
|
18
|
+
// STM32-style pinctrl dtsi labels (all spellings the walker knows):
|
|
19
|
+
// adc1_in1_pa1 / adc_in0_pa0 / adc1_inp16_pa0, tim4_ch1_pb6,
|
|
20
|
+
// dac1_out1_pa4. Labels appear verbatim in zephyr.dts
|
|
21
|
+
// (`adc1_in0_pa0: adc1_in0_pa0 {`). The `inn` negative inputs stay out —
|
|
22
|
+
// the thin HAL is single-ended. The F1 (AFIO) family uses `tim1_ch1_pwm_out_pa8`
|
|
23
|
+
// and `dac_out1_pa4` — separate grammars.
|
|
24
|
+
const ST_ADC = /^([a-z]*adc\d*_(?:in|inp)\d+_p([a-z])(\d+))$/;
|
|
25
|
+
const ST_PWM = /^(tim(\d+)_ch(\d+)_p([a-z])(\d+))$/;
|
|
26
|
+
const ST_PWM_F1 = /^(tim(\d+)_ch(\d+)_pwm_out_p([a-z])(\d+))$/;
|
|
27
|
+
const ST_DAC = /^(dac(\d+)_out(\d+)_p([a-z])(\d+))$/;
|
|
28
|
+
const ST_DAC_F1 = /^(dac_out(\d+)_p([a-z])(\d+))$/;
|
|
29
|
+
// i.MX RT labels: iomuxc_<pad>_adc1_in1 / iomuxc_<pad>_flexpwm2_pwma3,
|
|
30
|
+
// with the pad→GPIO join as sibling iomuxc_<pad>_gpio1_io12 labels. The NEW
|
|
31
|
+
// RT parts (rt11xx/rt116x/rt118x) use `…_flexpwm1_pwm0_a` (pwm<K>_<a|b> →
|
|
32
|
+
// A=0/B=1). Their ADC is the LPADC (`lpadc<N>`) and stays out — see
|
|
33
|
+
// dts-reader.ts.
|
|
34
|
+
const IMX_GPIO = /^iomuxc_([a-z0-9_]+)_gpio(\d+)_io(\d+)$/;
|
|
35
|
+
const IMX_ADC = /^iomuxc_([a-z0-9_]+)_adc(\d+)_in(\d+)$/;
|
|
36
|
+
const IMX_PWM = /^iomuxc_([a-z0-9_]+)_flexpwm(\d+)_pwm([ab])(\d+)$/;
|
|
37
|
+
const IMX_PWM2 = /^iomuxc_([a-z0-9_]+)_flexpwm(\d+)_pwm(\d+)_([ab])$/;
|
|
38
|
+
/**
|
|
39
|
+
* Parse a resolved zephyr.dts into raw pin routes. Labels are matched as
|
|
40
|
+
* whole tokens (`label:` or `label {`) — in dtc output every node carries
|
|
41
|
+
* its labels inline before the node name.
|
|
42
|
+
*/
|
|
43
|
+
export function parseZephyrDts(text) {
|
|
44
|
+
const facts = { adc: [], pwm: [], dac: [] };
|
|
45
|
+
const imxPadToGpio = new Map();
|
|
46
|
+
const seen = new Set();
|
|
47
|
+
// Every label occurrence: `label:` (label before node) — zephyr.dts
|
|
48
|
+
// renders `label: nodename {`, INDENTED with tabs. Whole-token labels.
|
|
49
|
+
for (const m of text.matchAll(/^\s*([a-z][a-z0-9_]*):\s/gm)) {
|
|
50
|
+
const label = m[1];
|
|
51
|
+
if (seen.has(label))
|
|
52
|
+
continue;
|
|
53
|
+
let g;
|
|
54
|
+
if ((g = label.match(ST_ADC))) {
|
|
55
|
+
seen.add(label);
|
|
56
|
+
// Source: the unit prefix from the name — `adc1_in1…` → adc1, the
|
|
57
|
+
// single-unit spelling `adc_in0…` → adc.
|
|
58
|
+
const unit = label.match(/^([a-z]+?\d*)_in/);
|
|
59
|
+
facts.adc.push({
|
|
60
|
+
source: unit ? unit[1] : 'adc',
|
|
61
|
+
channel: Number(label.match(/_(?:in|inp)(\d+)_/)[1]),
|
|
62
|
+
port: g[2].toUpperCase(),
|
|
63
|
+
bit: Number(g[3]),
|
|
64
|
+
pinctrl: label,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
else if ((g = label.match(ST_PWM))) {
|
|
68
|
+
seen.add(label);
|
|
69
|
+
facts.pwm.push({
|
|
70
|
+
source: `tim${g[2]}`,
|
|
71
|
+
channel: Number(g[3]),
|
|
72
|
+
port: g[4].toUpperCase(),
|
|
73
|
+
bit: Number(g[5]),
|
|
74
|
+
pinctrl: label,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
else if ((g = label.match(ST_PWM_F1))) {
|
|
78
|
+
seen.add(label);
|
|
79
|
+
facts.pwm.push({
|
|
80
|
+
source: `tim${g[2]}`,
|
|
81
|
+
channel: Number(g[3]),
|
|
82
|
+
port: g[4].toUpperCase(),
|
|
83
|
+
bit: Number(g[5]),
|
|
84
|
+
pinctrl: label,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else if ((g = label.match(ST_DAC))) {
|
|
88
|
+
seen.add(label);
|
|
89
|
+
facts.dac.push({
|
|
90
|
+
source: `dac${g[2]}`,
|
|
91
|
+
channel: Number(g[3]),
|
|
92
|
+
port: g[4].toUpperCase(),
|
|
93
|
+
bit: Number(g[5]),
|
|
94
|
+
pinctrl: label,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else if ((g = label.match(ST_DAC_F1))) {
|
|
98
|
+
seen.add(label);
|
|
99
|
+
facts.dac.push({
|
|
100
|
+
source: 'dac1',
|
|
101
|
+
channel: Number(g[2]),
|
|
102
|
+
port: g[3].toUpperCase(),
|
|
103
|
+
bit: Number(g[4]),
|
|
104
|
+
pinctrl: label,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
else if ((g = label.match(IMX_GPIO))) {
|
|
108
|
+
seen.add(label);
|
|
109
|
+
if (!imxPadToGpio.has(g[1]))
|
|
110
|
+
imxPadToGpio.set(g[1], { port: g[2], bit: Number(g[3]) });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// i.MX routes resolve after the join map is complete.
|
|
114
|
+
for (const m of text.matchAll(/^\s*([a-z][a-z0-9_]*):\s/gm)) {
|
|
115
|
+
const label = m[1];
|
|
116
|
+
let g;
|
|
117
|
+
if ((g = label.match(IMX_ADC))) {
|
|
118
|
+
const gpio = imxPadToGpio.get(g[1]);
|
|
119
|
+
if (!gpio || seen.has(label))
|
|
120
|
+
continue;
|
|
121
|
+
seen.add(label);
|
|
122
|
+
facts.adc.push({
|
|
123
|
+
source: `adc${g[2]}`,
|
|
124
|
+
channel: Number(g[3]),
|
|
125
|
+
port: gpio.port,
|
|
126
|
+
bit: gpio.bit,
|
|
127
|
+
pinctrl: label,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
else if ((g = label.match(IMX_PWM))) {
|
|
131
|
+
const gpio = imxPadToGpio.get(g[1]);
|
|
132
|
+
if (!gpio || seen.has(label))
|
|
133
|
+
continue;
|
|
134
|
+
seen.add(label);
|
|
135
|
+
facts.pwm.push({
|
|
136
|
+
source: `flexpwm${g[2]}_pwm${g[4]}`,
|
|
137
|
+
channel: g[3] === 'b' ? 1 : 0,
|
|
138
|
+
port: gpio.port,
|
|
139
|
+
bit: gpio.bit,
|
|
140
|
+
pinctrl: label,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
else if ((g = label.match(IMX_PWM2))) {
|
|
144
|
+
const gpio = imxPadToGpio.get(g[1]);
|
|
145
|
+
if (!gpio || seen.has(label))
|
|
146
|
+
continue;
|
|
147
|
+
seen.add(label);
|
|
148
|
+
facts.pwm.push({
|
|
149
|
+
source: `flexpwm${g[2]}_pwm${g[3]}`,
|
|
150
|
+
channel: g[4] === 'b' ? 1 : 0,
|
|
151
|
+
port: gpio.port,
|
|
152
|
+
bit: gpio.bit,
|
|
153
|
+
pinctrl: label,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return facts;
|
|
158
|
+
}
|
|
159
|
+
/** Parse + shape-validate .cuttlefish/as-built.json; errors name the file. */
|
|
160
|
+
export function parseAsBuiltJson(text, source = '.cuttlefish/as-built.json') {
|
|
161
|
+
let parsed;
|
|
162
|
+
try {
|
|
163
|
+
parsed = JSON.parse(text);
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
throw new Error(`${source} is not valid JSON: ${err.message}`);
|
|
167
|
+
}
|
|
168
|
+
const file = parsed;
|
|
169
|
+
if (!file || typeof file !== 'object' || file.version !== 1 || typeof file.board !== 'string'
|
|
170
|
+
|| !file.routes || !Array.isArray(file.routes.adcPins) || !Array.isArray(file.routes.pwmPins)) {
|
|
171
|
+
throw new Error(`${source} must carry version 1, a board target, and routes.{adcPins,pwmPins}.`);
|
|
172
|
+
}
|
|
173
|
+
return file;
|
|
174
|
+
}
|
|
175
|
+
/** Serialize the as-built snapshot (deterministic field order). */
|
|
176
|
+
export function asBuiltJson(board, facts) {
|
|
177
|
+
const byPin = (a, b) => a.port.localeCompare(b.port) || a.bit - b.bit || a.channel - b.channel;
|
|
178
|
+
return JSON.stringify({
|
|
179
|
+
version: 1,
|
|
180
|
+
board,
|
|
181
|
+
generatedAt: new Date().toISOString(),
|
|
182
|
+
routes: {
|
|
183
|
+
adcPins: [...facts.adc].sort(byPin),
|
|
184
|
+
pwmPins: [...facts.pwm].sort(byPin),
|
|
185
|
+
dacPins: [...facts.dac].sort(byPin),
|
|
186
|
+
},
|
|
187
|
+
}, null, 1);
|
|
188
|
+
}
|
|
@@ -59,7 +59,7 @@ static int32_t __tc_timer_add(void (*cb)(void), int32_t ms, bool repeat) {
|
|
|
59
59
|
k_timer_init(&__tc_timer_slots[i].timer, __tc_timer_expiry_fn, nullptr);
|
|
60
60
|
k_work_init(&__tc_timer_slots[i].work, __tc_timer_work_handler);
|
|
61
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
|
|
62
|
+
return i + 1; // 1-based id
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
return 0; // pool full
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { BoardDataEntry } from '@typecad/cuttlefish/board-catalog';
|
|
2
|
+
export interface GeneratedBoard {
|
|
3
|
+
readonly boardTs: string;
|
|
4
|
+
readonly boardJson: string;
|
|
5
|
+
/** The resolved board record (identifier/name/vendor) — for build notes. */
|
|
6
|
+
readonly board: BoardDataEntry;
|
|
7
|
+
/** Non-fatal notes from generation — user facts shadowing harvested
|
|
8
|
+
* routes (the user won; the harvest said otherwise). */
|
|
9
|
+
readonly warnings?: readonly string[];
|
|
10
|
+
}
|
|
11
|
+
/** Look up a board variant by qualified target or bare board id. */
|
|
12
|
+
export declare function findBoardData(target: string): BoardDataEntry | undefined;
|
|
13
|
+
/** soc name from a qualified target ('board/soc/qual' → 'soc'). */
|
|
14
|
+
export declare function socOfTarget(target: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* nRF SAADC AIN→P0-pad map per SoC — [channel, pad] pairs (see the synthesis
|
|
17
|
+
* block in buildModule for the verification trail). Undefined for SoCs
|
|
18
|
+
* without a verified map (including every /cpunet variant: the nRF5340
|
|
19
|
+
* network core declares no SAADC).
|
|
20
|
+
*/
|
|
21
|
+
export declare function nrfSaadcAinPads(soc: string, identifier: string): readonly [number, number][] | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* ESP32 DAC channel→GPIO pad map per SoC — [channel, pad] pairs, silicon-
|
|
24
|
+
* fixed (no pinctrl group; the DAC outputs through the RTC IO mux on a fixed
|
|
25
|
+
* pad). Only the original ESP32 and the ESP32-S2 carry the 8-bit DAC; the
|
|
26
|
+
* S3/C3/C6/H2 dropped it. Sourced from the HAL's dac_periph.c
|
|
27
|
+
* (`dac_channel_io_num[]`), like the nRF SAADC table is from the PS.
|
|
28
|
+
*/
|
|
29
|
+
export declare function esp32DacPins(soc: string): readonly [number, number][] | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Parse a datasheet pin name into (controller nodelabel, controller-relative
|
|
32
|
+
* bit) per the soc's naming family — the inverse of the sweep naming:
|
|
33
|
+
* nRF P0.28 / P0_28 → gpio0.28
|
|
34
|
+
* RP2040 GP25 → gpio0.25
|
|
35
|
+
* ESP32 GPIO9 → gpio0.9 (GPIO32+ → gpio1.x)
|
|
36
|
+
* letters PA5 / PB6 → gpioa.5 / gpiob.6
|
|
37
|
+
* flat GPIO9 (non-esp32 socs, single flat controller) → gpio.9
|
|
38
|
+
*/
|
|
39
|
+
export declare function parsePinName(soc: string, name: string): {
|
|
40
|
+
controller: string;
|
|
41
|
+
pin: number;
|
|
42
|
+
} | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Build the board module contents from one board record. This is the one
|
|
45
|
+
* builder for every kind of board: catalog records (from the local overlay
|
|
46
|
+
* generated off the installed SDK's tree) and contract records (custom PCB
|
|
47
|
+
* specs) both route through here.
|
|
48
|
+
*/
|
|
49
|
+
/** One board's user-declared facts — the `boards['<target>']` section. */
|
|
50
|
+
export interface UserBoardFacts {
|
|
51
|
+
adc?: {
|
|
52
|
+
/** DT nodelabel of the ADC device (default: the board's primary, or 'adc'). */
|
|
53
|
+
device?: string;
|
|
54
|
+
channels: {
|
|
55
|
+
pin: number;
|
|
56
|
+
channel: number;
|
|
57
|
+
pinctrl?: string;
|
|
58
|
+
}[];
|
|
59
|
+
};
|
|
60
|
+
pwm?: {
|
|
61
|
+
/** Static specs — pin→controller/channel. Suppresses the auto nRF matrix. */
|
|
62
|
+
specs: {
|
|
63
|
+
pin: number;
|
|
64
|
+
controller: string;
|
|
65
|
+
channel: number;
|
|
66
|
+
pinctrl?: string;
|
|
67
|
+
}[];
|
|
68
|
+
};
|
|
69
|
+
dac?: {
|
|
70
|
+
device: string;
|
|
71
|
+
channels: {
|
|
72
|
+
pin: number;
|
|
73
|
+
channel: number;
|
|
74
|
+
resolution?: number;
|
|
75
|
+
}[];
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** The whole cuttlefish.facts.json shape. */
|
|
79
|
+
export interface UserFactsFile {
|
|
80
|
+
boards: Record<string, UserBoardFacts>;
|
|
81
|
+
}
|
|
82
|
+
/** Parse + shape-validate the facts file; a clear error names the file. */
|
|
83
|
+
export declare function parseUserFactsJson(text: string, source?: string): UserFactsFile;
|
|
84
|
+
/** The section matching a target — the same exact → lowercase → prefix
|
|
85
|
+
* leniency findBoardData applies to catalog keys. */
|
|
86
|
+
export declare function userFactsForTarget(file: UserFactsFile | undefined, target: string): UserBoardFacts | undefined;
|
|
87
|
+
export declare function buildModule(entry: BoardDataEntry, userFacts?: UserBoardFacts, factsSuffix?: string, seedWarnings?: readonly string[]): GeneratedBoard;
|
|
88
|
+
/**
|
|
89
|
+
* Generate the board module contents for a qualified Zephyr board target
|
|
90
|
+
* ('esp32s3_devkitc/esp32s3/procpu'). Bare SoC names are not targets —
|
|
91
|
+
* every board resolves through the catalog like any other.
|
|
92
|
+
*/
|
|
93
|
+
export declare function generateBoard(target: string, opts?: {
|
|
94
|
+
factsJson?: string;
|
|
95
|
+
asBuiltJson?: string;
|
|
96
|
+
}): GeneratedBoard;
|
|
97
|
+
/**
|
|
98
|
+
* Generate the board module for a CONTRACT board — a custom PCB with no
|
|
99
|
+
* Zephyr board record. The contract (exported from a TypeCAD project)
|
|
100
|
+
* supplies the wired pads by datasheet name and which bus families the PCB
|
|
101
|
+
* routes; the SoC's bus controller nodelabels come from the INSTALLED
|
|
102
|
+
* Zephyr tree's soc dtsi (the SDK is the source of truth — a contract build
|
|
103
|
+
* compiles against that tree).
|
|
104
|
+
*
|
|
105
|
+
* Returns a full board module (the transpiler's pin map + chip resolution
|
|
106
|
+
* read board.json). The caller layers the narrowed board.ts on top, so the
|
|
107
|
+
* firmware can only touch pads the PCB actually wired.
|
|
108
|
+
*/
|
|
109
|
+
export declare function generateBoardModuleFromContract(opts: {
|
|
110
|
+
soc: string;
|
|
111
|
+
zephyrBase: string;
|
|
112
|
+
/** Wired pad names in the soc's datasheet form (PA5, P0.28, GP25...). */
|
|
113
|
+
pinNames: readonly string[];
|
|
114
|
+
/** Functional names to export as aliases of a wired pad (TX → PA9). */
|
|
115
|
+
padAliases?: readonly {
|
|
116
|
+
exportName: string;
|
|
117
|
+
padName: string;
|
|
118
|
+
}[];
|
|
119
|
+
/** Which bus families the PCB routes. */
|
|
120
|
+
peripherals: {
|
|
121
|
+
i2c: boolean;
|
|
122
|
+
spi: boolean;
|
|
123
|
+
uart: boolean;
|
|
124
|
+
};
|
|
125
|
+
}): {
|
|
126
|
+
boardTs: string;
|
|
127
|
+
boardJson: string;
|
|
128
|
+
};
|