@typecad/framework-zephyr 1.0.0-alpha.13 → 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 -35
- 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/controllers.d.ts +28 -8
- package/dist/chips/controllers.js +49 -12
- 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 +298 -15
- 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 +382 -12
- package/dist/chips/xiao-ble.js +33 -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 +83 -1
- package/dist/dt-config/kconfig.js +116 -27
- package/dist/dt-config/overlay.js +623 -18
- package/dist/framework.manifest.d.ts +20 -30
- package/dist/framework.manifest.js +124 -178
- package/dist/index.d.ts +4 -1
- package/dist/index.js +8 -2
- package/dist/lowering/adc.d.ts +26 -5
- package/dist/lowering/adc.js +137 -31
- 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 +90 -10
- 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 +12 -6
- package/dist/lowering/power.js +0 -4
- package/dist/lowering/preferences.js +49 -77
- package/dist/lowering/pulse.js +5 -36
- package/dist/lowering/pwm.d.ts +32 -3
- package/dist/lowering/pwm.js +105 -17
- 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 +18 -5
- 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 +120 -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 +881 -212
- 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 +212 -72
- 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 +713 -58
- package/dist/toolchain/scaffold.d.ts +9 -0
- package/dist/toolchain/scaffold.js +84 -7
- package/dist/toolchain/west-discover.d.ts +8 -1
- package/dist/toolchain/west-discover.js +19 -6
- package/dist/toolchain/west-spawn.js +17 -5
- 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 +16 -16
- package/src/as-built.ts +206 -0
- package/src/boardgen.ts +1428 -0
- package/src/chips/controllers.ts +61 -12
- package/src/chips/index.ts +35 -54
- package/src/chips/resolve.ts +316 -14
- package/src/chips/types.ts +388 -13
- 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 +177 -19
- package/src/dt-config/overlay.ts +1058 -450
- package/src/framework.manifest.ts +125 -178
- package/src/index.ts +57 -41
- package/src/lowering/adc.ts +222 -102
- 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 -152
- 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 +12 -6
- package/src/lowering/preferences.ts +327 -354
- package/src/lowering/pwm.ts +167 -74
- 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 +120 -111
- package/src/sdk/board-catalog-sync.ts +62 -0
- package/src/strategy.ts +888 -229
- 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 +765 -44
- package/src/toolchain/scaffold.ts +81 -7
- package/src/toolchain/west-discover.ts +334 -316
- package/src/toolchain/west-spawn.ts +17 -5
- 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 -70
- 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/lowering/spi.ts
CHANGED
|
@@ -1,124 +1,164 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// SPI lowering — spi_transceive_dt against a spi_dt_spec; CS as GPIO
|
|
3
|
-
//
|
|
4
|
-
// Zephyr's `spi_transceive_dt(&spec, tx, rx)` is stateless per-call, so there
|
|
5
|
-
// is no pending-tx-buffer (unlike I2C). The CS pin is driven as a plain GPIO
|
|
6
|
-
// (like ESP32), since the DT spec's CS handling is configured at compile time
|
|
7
|
-
// but the HAL's explicit cs_low/cs_high ops want manual control.
|
|
8
|
-
//
|
|
9
|
-
// The board's SPI node (spi2 on the XIAO) has no pre-declared client device
|
|
10
|
-
// node, so the lowering cannot use SPI_DT_SPEC_GET (which needs a client node).
|
|
11
|
-
// Instead we build a `struct spi_config` at runtime against
|
|
12
|
-
// DEVICE_DT_GET(DT_NODELABEL(spi2)) and call spi_transceive directly.
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
|
|
15
|
-
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
16
|
-
import type { ZephyrChipDescriptor } from '../chips/types.js';
|
|
17
|
-
import { parseControllerIndex } from './util.js';
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
`}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
*
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// SPI lowering — spi_transceive_dt against a spi_dt_spec; CS as GPIO
|
|
3
|
+
//
|
|
4
|
+
// Zephyr's `spi_transceive_dt(&spec, tx, rx)` is stateless per-call, so there
|
|
5
|
+
// is no pending-tx-buffer (unlike I2C). The CS pin is driven as a plain GPIO
|
|
6
|
+
// (like ESP32), since the DT spec's CS handling is configured at compile time
|
|
7
|
+
// but the HAL's explicit cs_low/cs_high ops want manual control.
|
|
8
|
+
//
|
|
9
|
+
// The board's SPI node (spi2 on the XIAO) has no pre-declared client device
|
|
10
|
+
// node, so the lowering cannot use SPI_DT_SPEC_GET (which needs a client node).
|
|
11
|
+
// Instead we build a `struct spi_config` at runtime against
|
|
12
|
+
// DEVICE_DT_GET(DT_NODELABEL(spi2)) and call spi_transceive directly.
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
16
|
+
import type { ZephyrChipDescriptor } from '../chips/types.js';
|
|
17
|
+
import { parseControllerIndex } from './util.js';
|
|
18
|
+
|
|
19
|
+
/** The C variable prefix for a controller's state. */
|
|
20
|
+
function prefix(idx: number): string {
|
|
21
|
+
return `__tc_spi${idx}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ── Thin SPI device names — the shared-facts discipline ────────────────────
|
|
25
|
+
//
|
|
26
|
+
// The DT nodelabel (tc_spit_spi<N>_cs<cs>), the shim's spi_dt_spec var, and
|
|
27
|
+
// the overlay scanner's regex all derive from bus index + cs pin here.
|
|
28
|
+
|
|
29
|
+
export interface SpiTargetNames {
|
|
30
|
+
dtLabel: string;
|
|
31
|
+
varName: string;
|
|
32
|
+
busIndex: number;
|
|
33
|
+
cs: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Derive a thin SPI target's names from the op facts. */
|
|
37
|
+
export function spiTargetNames(bus: string, cs: number | string): SpiTargetNames {
|
|
38
|
+
const busIndex = parseControllerIndex(typeof bus === 'string' ? bus : String(bus));
|
|
39
|
+
const csNum = typeof cs === 'number' ? cs : parseInt(String(cs), 10);
|
|
40
|
+
const stem = `spit_spi${busIndex}_cs${csNum}`;
|
|
41
|
+
return { dtLabel: `tc_${stem}`, varName: `__tc_${stem}_spec`, busIndex, cs: csNum };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** The per-target state block: one spi_dt_spec against the DT child node the
|
|
45
|
+
* overlay emits, plus the tc-spit-cfg comment the overlay scanner reads (the
|
|
46
|
+
* tc-sensor-cfg channel). Called from shimLines for each distinct target. */
|
|
47
|
+
export function spiTargetStateLines(bus: string, cs: number | string, hz: number | string = 0, mode: number | string = 0): string[] {
|
|
48
|
+
const n = spiTargetNames(bus, cs);
|
|
49
|
+
return [
|
|
50
|
+
'// CUTTLEFISH_SPIT_BEGIN',
|
|
51
|
+
// Zephyr 4.4's SPI_DT_SPEC_GET takes the base operation explicitly (mode
|
|
52
|
+
// bits come from the DT node's spi-cpol/spi-cpha via SPI_CONFIG_DT).
|
|
53
|
+
`static const struct spi_dt_spec ${n.varName} = SPI_DT_SPEC_GET(DT_NODELABEL(${n.dtLabel}), SPI_OP_MODE_MASTER | SPI_WORD_SET(8), 0);`,
|
|
54
|
+
`// tc-spit-cfg: ${n.dtLabel} hz=${Number(hz)} mode=${Number(mode)}`,
|
|
55
|
+
'// CUTTLEFISH_SPIT_END',
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Build the tx buffer declaration + set for a thin SPI op. A literal byte
|
|
60
|
+
* array becomes a local array; a single identifier is the user's own buffer
|
|
61
|
+
* (its storage + sizeof drive length). spi_buf.buf is void*, and the user's
|
|
62
|
+
* buffer may be const-qualified — cast through const void* to stay legal
|
|
63
|
+
* under -Werror without mutating anyone's qualifications. */
|
|
64
|
+
function spiTxBuffers(tx: unknown, tag: string): { decl: string; set: string } {
|
|
65
|
+
const bytes = (Array.isArray(tx) ? tx : []) as unknown[];
|
|
66
|
+
// Only an identifier-shaped string is a real caller buffer — the resolver
|
|
67
|
+
// collapses a single-byte literal array to buffer-kind with NUMERIC text
|
|
68
|
+
// (e.g. "159"), which must take the literal path below.
|
|
69
|
+
const isIdentifier = bytes.length === 1 && typeof bytes[0] === 'string' && /^[A-Za-z_][A-Za-z0-9_]*$/.test(bytes[0] as string);
|
|
70
|
+
if (isIdentifier) {
|
|
71
|
+
const name = bytes[0] as string;
|
|
72
|
+
return {
|
|
73
|
+
decl: `const struct spi_buf __tb${tag} = { .buf = const_cast<void*>(static_cast<const void*>(${name})), .len = sizeof(${name}) }; const struct spi_buf_set __txs${tag} = { .buffers = &__tb${tag}, .count = 1 };`,
|
|
74
|
+
set: `__txs${tag}`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
decl: `uint8_t __tx${tag}[] = { ${bytes.join(', ')} }; const struct spi_buf __tb${tag} = { .buf = __tx${tag}, .len = sizeof(__tx${tag}) }; const struct spi_buf_set __txs${tag} = { .buffers = &__tb${tag}, .count = 1 };`,
|
|
79
|
+
set: `__txs${tag}`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Emit the per-controller SPI state. The bus device resolves at compile time;
|
|
85
|
+
* a static spi_config holds the base operation flags, and mutable runtime fields
|
|
86
|
+
* hold the mode (CPOL/CPHA bits) + bit order (lsb) so set_mode/set_bit_order can
|
|
87
|
+
* rebuild operation at init time (Zephyr's spi_config.operation is the only knob).
|
|
88
|
+
*/
|
|
89
|
+
export function spiInitLines(chip: ZephyrChipDescriptor, controllerIndex: number): string[] {
|
|
90
|
+
const ctrl = chip.spi?.controllers[controllerIndex];
|
|
91
|
+
if (!ctrl) return [];
|
|
92
|
+
const p = prefix(controllerIndex);
|
|
93
|
+
return [
|
|
94
|
+
'// CUTTLEFISH_SPI_BEGIN',
|
|
95
|
+
`static const struct device* ${p}_dev = DEVICE_DT_GET(DT_NODELABEL(${ctrl.nodeLabel}));`,
|
|
96
|
+
`static bool ${p}_ready = false;`,
|
|
97
|
+
`static uint8_t ${p}_mode = 0; // bit0=CPOL, bit1=CPHA`,
|
|
98
|
+
`static bool ${p}_lsb = false; // false=MSB (default), true=LSB`,
|
|
99
|
+
`static struct spi_config ${p}_cfg = {`,
|
|
100
|
+
` .frequency = 1000000,`,
|
|
101
|
+
`};`,
|
|
102
|
+
`static void ${p}_init(void) {`,
|
|
103
|
+
` if (!${p}_ready) {`,
|
|
104
|
+
// NOTE: no .bus assignment — struct spi_config lost its `bus` member in
|
|
105
|
+
// Zephyr 4.x (deprecated 3.5, removed 4.0); spi_transceive takes the
|
|
106
|
+
// device alongside the config, which the ops below already do.
|
|
107
|
+
` ${p}_cfg.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8)`,
|
|
108
|
+
` | (${p}_lsb ? SPI_TRANSFER_LSB : SPI_TRANSFER_MSB)`,
|
|
109
|
+
` | ((${p}_mode & 0x1) ? SPI_MODE_CPOL : 0)`,
|
|
110
|
+
` | ((${p}_mode & 0x2) ? SPI_MODE_CPHA : 0);`,
|
|
111
|
+
` ${p}_ready = true;`,
|
|
112
|
+
` }`,
|
|
113
|
+
`}`,
|
|
114
|
+
'// CUTTLEFISH_SPI_END',
|
|
115
|
+
];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Resolve a HAL spi.* op to Zephyr C++.
|
|
120
|
+
* Returns `{ code }` for statement ops, `{ expression }` for value-returning ops.
|
|
121
|
+
*/
|
|
122
|
+
export function lowerSpi(
|
|
123
|
+
op: HALOpIR,
|
|
124
|
+
chip: ZephyrChipDescriptor,
|
|
125
|
+
): { code?: string; expression?: string } {
|
|
126
|
+
const o = op as any;
|
|
127
|
+
const idx = parseControllerIndex(o.bus);
|
|
128
|
+
const p = prefix(idx);
|
|
129
|
+
|
|
130
|
+
switch (op.operation) {
|
|
131
|
+
case 'spi.transceive': {
|
|
132
|
+
const v = spiTargetNames(o.bus, o.cs).varName;
|
|
133
|
+
const tx = spiTxBuffers(o.tx, 't');
|
|
134
|
+
const rxName = String(o.rx ?? '');
|
|
135
|
+
const rx = rxName
|
|
136
|
+
? `struct spi_buf __rb = { .buf = const_cast<void*>(static_cast<const void*>(${rxName})), .len = sizeof(${rxName}) }; const struct spi_buf_set __rbs = { .buffers = &__rb, .count = 1 };`
|
|
137
|
+
: `const struct spi_buf_set __rbs = { .buffers = NULL, .count = 0 };`;
|
|
138
|
+
return {
|
|
139
|
+
code: `{ ${tx.decl} ${rx} (void)spi_transceive_dt(&${v}, &${tx.set}, &__rbs); }`,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
case 'spi.dev_write': {
|
|
143
|
+
const v = spiTargetNames(o.bus, o.cs).varName;
|
|
144
|
+
const tx = spiTxBuffers(o.tx, 'w');
|
|
145
|
+
return {
|
|
146
|
+
code: `{ ${tx.decl} (void)spi_write_dt(&${v}, &${tx.set}); }`,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
case 'spi.reg_read': {
|
|
150
|
+
// One-byte register read against an INTERNAL buffer — no caller array
|
|
151
|
+
// (sidesteps the file-scope Uint8Array promotion issue; also just the
|
|
152
|
+
// right shape for ID/status registers).
|
|
153
|
+
const v = spiTargetNames(o.bus, o.cs).varName;
|
|
154
|
+
return {
|
|
155
|
+
expression: `({ uint8_t __txr = static_cast<uint8_t>(${o.reg}); uint8_t __rxr = 0; struct spi_buf __tbr = { .buf = &__txr, .len = 1 }; const struct spi_buf_set __txsr = { .buffers = &__tbr, .count = 1 }; struct spi_buf __rbr = { .buf = &__rxr, .len = 1 }; const struct spi_buf_set __rxsr = { .buffers = &__rbr, .count = 1 }; (void)spi_transceive_dt(&${v}, &__txsr, &__rxsr); __rxr; })`,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
default:
|
|
159
|
+
throw new Error(
|
|
160
|
+
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
161
|
+
`Open an issue or use rawCpp() to emit it manually.`,
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Thread lowering — Zephyr kernel threads (k_thread_create / k_thread_join)
|
|
3
|
+
//
|
|
4
|
+
// One state block per thread identity slot the program STARTS: a static
|
|
5
|
+
// K_THREAD_STACK_DEFINE (sized by the construction stackKb), the k_thread
|
|
6
|
+
// struct, and an entry trampoline bridging Zephyr's (void*, void*, void*)
|
|
7
|
+
// entry signature to the no-argument registered callback. start() creates
|
|
8
|
+
// and schedules (K_NO_WAIT); join() blocks (K_FOREVER).
|
|
9
|
+
//
|
|
10
|
+
// No devicetree, no Kconfig — kernel.h (always included) is the whole
|
|
11
|
+
// dependency. State emission is keyed on thread.start ops only, so a
|
|
12
|
+
// join-only program emits nothing (and its join guards on the same slot).
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
16
|
+
|
|
17
|
+
/** Per-instance symbol stem. */
|
|
18
|
+
function stem(instance: number): string {
|
|
19
|
+
return `__tc_thrd${instance}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Emit the per-thread state. Called from shimLines for each distinct thread
|
|
24
|
+
* the program starts.
|
|
25
|
+
*/
|
|
26
|
+
export function threadStateLines(instance: number, stackBytes: number): string[] {
|
|
27
|
+
const p = stem(instance);
|
|
28
|
+
return [
|
|
29
|
+
'// CUTTLEFISH_THREAD_BEGIN',
|
|
30
|
+
`K_THREAD_STACK_DEFINE(${p}_stack, ${stackBytes});`,
|
|
31
|
+
`static struct k_thread ${p}_thread;`,
|
|
32
|
+
`static void (*${p}_fn)(void) = NULL;`,
|
|
33
|
+
`static void ${p}_tramp(void* a, void* b, void* c) { (void)a; (void)b; (void)c; if (${p}_fn) { ${p}_fn(); } }`,
|
|
34
|
+
'// CUTTLEFISH_THREAD_END',
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Resolve a HAL thread.* op to Zephyr C++.
|
|
40
|
+
* Returns `{ code }` for statement ops.
|
|
41
|
+
*/
|
|
42
|
+
export function lowerThread(op: HALOpIR): { code?: string; expression?: string } {
|
|
43
|
+
const o = op as any;
|
|
44
|
+
const instance = typeof o.instance === 'number' ? o.instance : 0;
|
|
45
|
+
const p = stem(instance);
|
|
46
|
+
|
|
47
|
+
switch (op.operation) {
|
|
48
|
+
case 'thread.start': {
|
|
49
|
+
// Store the entry, create + schedule immediately. The stack size comes
|
|
50
|
+
// from the state block (the construction fact), via K_THREAD_STACK_SIZEOF.
|
|
51
|
+
return {
|
|
52
|
+
code: `${p}_fn = (${o.handler}); (void)k_thread_create(&${p}_thread, ${p}_stack, K_THREAD_STACK_SIZEOF(${p}_stack), ${p}_tramp, NULL, NULL, NULL, ${o.priority ?? 5}, 0, K_NO_WAIT);`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
case 'thread.join':
|
|
56
|
+
return { code: `(void)k_thread_join(&${p}_thread, K_FOREVER);` };
|
|
57
|
+
default:
|
|
58
|
+
throw new Error(
|
|
59
|
+
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
60
|
+
`Open an issue or use rawCpp() to emit it manually.`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
package/src/lowering/timing.ts
CHANGED
|
@@ -1,72 +1,46 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// Timing lowering — Zephyr kernel timing
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
op
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
case 'timing.
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
case 'timing.free_heap':
|
|
48
|
-
// No portable free-heap query without CONFIG_SYS_HEAP_RUNTIME_STATS.
|
|
49
|
-
// Return 0 with a comment so callers don't get a link error.
|
|
50
|
-
return { expression: '(0 /* free_heap: enable CONFIG_SYS_HEAP_RUNTIME_STATS for real value */)' };
|
|
51
|
-
case 'timing.set_interval':
|
|
52
|
-
// Backed by the timer_methods polyfill (k_timer + k_work). The handler is
|
|
53
|
-
// the resolved C++ callback name; timeout is the repeat period (ms).
|
|
54
|
-
// NOTE: these ops are declared 'polyfill' in the manifest, so setInterval
|
|
55
|
-
// is rewritten to __tc_setInterval before reaching the lowering — these
|
|
56
|
-
// cases are a fallback/defense and use the real op fields (handler/timeout).
|
|
57
|
-
return { expression: `__tc_setInterval(${o.handler}, ${o.timeout})` };
|
|
58
|
-
case 'timing.set_timeout':
|
|
59
|
-
// One-shot: k_timer with K_FOREVER period.
|
|
60
|
-
return { expression: `__tc_setTimeout(${o.handler}, ${o.timeout})` };
|
|
61
|
-
case 'timing.clear_interval':
|
|
62
|
-
return { code: `__tc_clearInterval(${o.id});` };
|
|
63
|
-
case 'timing.clear_timeout':
|
|
64
|
-
return { code: `__tc_clearTimeout(${o.id});` };
|
|
65
|
-
default:
|
|
66
|
-
throw new Error(
|
|
67
|
-
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
68
|
-
`Open an issue or use rawCpp() to emit it manually.`,
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Timing lowering — Zephyr kernel timing
|
|
3
|
+
//
|
|
4
|
+
// sleep/now/now_us/busy_wait_us lower directly to kernel calls. Periodic or
|
|
5
|
+
// deferred work is NOT a timing op: it is a Thread (k_thread) or a Counter
|
|
6
|
+
// (hardware timer), each with its own lowering.
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Resolve a HAL timing.* op to Zephyr C++.
|
|
13
|
+
* Returns `{ code }` for statement ops, `{ expression }` for value-returning ops.
|
|
14
|
+
*/
|
|
15
|
+
export function lowerTiming(
|
|
16
|
+
op: HALOpIR,
|
|
17
|
+
): { code?: string; expression?: string } {
|
|
18
|
+
const o = op as any;
|
|
19
|
+
|
|
20
|
+
switch (op.operation) {
|
|
21
|
+
case 'timing.sleep':
|
|
22
|
+
// Time.sleep — yielding ms sleep (k_msleep), delay()'s replacement.
|
|
23
|
+
return { code: `k_msleep(${o.ms});` };
|
|
24
|
+
case 'timing.now':
|
|
25
|
+
// Time.now — ms since boot as a double (k_uptime_get is int64_t ms).
|
|
26
|
+
return { expression: 'static_cast<double>(k_uptime_get())' };
|
|
27
|
+
case 'timing.now_us':
|
|
28
|
+
// Time.nowUs — µs since boot, uptime-derived for EVERY board: the
|
|
29
|
+
// cycle-counter form (k_cyc_to_us_floor64(k_cycle_get_64())) reads a
|
|
30
|
+
// constant on SoCs without a free-running 64-bit counter, so the one
|
|
31
|
+
// uniform expression that is monotonic and advancing everywhere is
|
|
32
|
+
// the kernel uptime scaled to µs. Resolution is therefore the uptime
|
|
33
|
+
// tick (millisecond), uniformly. A double holds µs exactly for ~285
|
|
34
|
+
// years.
|
|
35
|
+
return { expression: 'static_cast<double>(k_uptime_get() * 1000)' };
|
|
36
|
+
case 'timing.busy_wait_us':
|
|
37
|
+
// Time.busyWaitUs — spin, no yield; delayMicroseconds's honest name.
|
|
38
|
+
return { code: `k_busy_wait(${o.us});` };
|
|
39
|
+
default:
|
|
40
|
+
throw new Error(
|
|
41
|
+
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
42
|
+
`Open an issue or use rawCpp() to emit it manually.`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|