@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/hwtimer.ts
CHANGED
|
@@ -1,101 +1,139 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// Hardware-timer lowering — Zephyr counter API
|
|
3
|
-
//
|
|
4
|
-
// HAL `hwtimer.*` (instance → frequency/overflow/start/stop) maps onto Zephyr's
|
|
5
|
-
// counter driver (<zephyr/drivers/counter.h>). A chip declares the counter
|
|
6
|
-
// devices it exposes (e.g. nRF RTC1 — RTC0 is kernel-owned) via
|
|
7
|
-
// `hwtimer.controllers[instance].nodeLabel`.
|
|
8
|
-
//
|
|
9
|
-
// Frequency model: a Zephyr counter has a fixed clock; the HAL
|
|
10
|
-
// set_frequency(hz) is realized as a top value of counter_freq/hz with an alarm
|
|
11
|
-
// callback (the on_overflow handler). start() arms both the top value and the
|
|
12
|
-
// callback so the call order (setFrequency → onOverflow → start, or any
|
|
13
|
-
// permutation) is handled uniformly.
|
|
14
|
-
//
|
|
15
|
-
// Targets without a free counter omit `hwtimer`; usage lowers to a comment and
|
|
16
|
-
// profileDiagnostics flags it. The JS setInterval/setTimeout polyfill
|
|
17
|
-
// (k_timer) is a separate surface and is unaffected.
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
|
|
20
|
-
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
21
|
-
import type { ZephyrChipDescriptor } from '../chips/types.js';
|
|
22
|
-
|
|
23
|
-
/** Per-instance emitted symbol stems. */
|
|
24
|
-
function devVar(instance: number): string {
|
|
25
|
-
return `__tc_hw_dev_${instance}`;
|
|
26
|
-
}
|
|
27
|
-
function hzVar(instance: number): string {
|
|
28
|
-
return `__tc_hw_hz_${instance}`;
|
|
29
|
-
}
|
|
30
|
-
function cbVar(instance: number): string {
|
|
31
|
-
return `__tc_hw_cb_${instance}`;
|
|
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
|
-
const
|
|
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
|
-
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Hardware-timer lowering — Zephyr counter API
|
|
3
|
+
//
|
|
4
|
+
// HAL `hwtimer.*` (instance → frequency/overflow/start/stop) maps onto Zephyr's
|
|
5
|
+
// counter driver (<zephyr/drivers/counter.h>). A chip declares the counter
|
|
6
|
+
// devices it exposes (e.g. nRF RTC1 — RTC0 is kernel-owned) via
|
|
7
|
+
// `hwtimer.controllers[instance].nodeLabel`.
|
|
8
|
+
//
|
|
9
|
+
// Frequency model: a Zephyr counter has a fixed clock; the HAL
|
|
10
|
+
// set_frequency(hz) is realized as a top value of counter_freq/hz with an alarm
|
|
11
|
+
// callback (the on_overflow handler). start() arms both the top value and the
|
|
12
|
+
// callback so the call order (setFrequency → onOverflow → start, or any
|
|
13
|
+
// permutation) is handled uniformly.
|
|
14
|
+
//
|
|
15
|
+
// Targets without a free counter omit `hwtimer`; usage lowers to a comment and
|
|
16
|
+
// profileDiagnostics flags it. The JS setInterval/setTimeout polyfill
|
|
17
|
+
// (k_timer) is a separate surface and is unaffected.
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
21
|
+
import type { ZephyrChipDescriptor } from '../chips/types.js';
|
|
22
|
+
|
|
23
|
+
/** Per-instance emitted symbol stems. */
|
|
24
|
+
function devVar(instance: number): string {
|
|
25
|
+
return `__tc_hw_dev_${instance}`;
|
|
26
|
+
}
|
|
27
|
+
function hzVar(instance: number): string {
|
|
28
|
+
return `__tc_hw_hz_${instance}`;
|
|
29
|
+
}
|
|
30
|
+
function cbVar(instance: number): string {
|
|
31
|
+
return `__tc_hw_cb_${instance}`;
|
|
32
|
+
}
|
|
33
|
+
/** The trampoline matching counter_top_callback_t: (dev, user_data). */
|
|
34
|
+
function trampVar(instance: number): string {
|
|
35
|
+
return `__tc_hw_tramp_${instance}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Emit the per-instance counter device handles + frequency/callback state.
|
|
40
|
+
* Called from shimLines when the program uses hardware timers.
|
|
41
|
+
*/
|
|
42
|
+
export function hwtimerInitLines(chip: ZephyrChipDescriptor): string[] {
|
|
43
|
+
const controllers = chip.hwtimer?.controllers ?? [];
|
|
44
|
+
if (controllers.length === 0) return [];
|
|
45
|
+
const lines: string[] = ['// CUTTLEFISH_HWTIMER_BEGIN'];
|
|
46
|
+
controllers.forEach((c, i) => {
|
|
47
|
+
lines.push(
|
|
48
|
+
`static const struct device* ${devVar(i)} = DEVICE_DT_GET(DT_NODELABEL(${c.nodeLabel}));`,
|
|
49
|
+
`static uint32_t ${hzVar(i)} = 1;`,
|
|
50
|
+
`static void (*${cbVar(i)})(void) = NULL;`,
|
|
51
|
+
`static void ${trampVar(i)}(const struct device* dev, void* user_data) {`,
|
|
52
|
+
` (void)dev; (void)user_data;`,
|
|
53
|
+
` if (${cbVar(i)}) { ${cbVar(i)}(); }`,
|
|
54
|
+
`}`,
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
lines.push('// CUTTLEFISH_HWTIMER_END');
|
|
58
|
+
return lines;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Resolve a HAL hwtimer.* op to Zephyr C++.
|
|
63
|
+
* Returns `{ code }` for statement ops.
|
|
64
|
+
*/
|
|
65
|
+
export function lowerHwtimer(
|
|
66
|
+
op: HALOpIR,
|
|
67
|
+
chip: ZephyrChipDescriptor,
|
|
68
|
+
): { code?: string; expression?: string } {
|
|
69
|
+
const o = op as any;
|
|
70
|
+
const controllers = chip.hwtimer?.controllers ?? [];
|
|
71
|
+
|
|
72
|
+
// No counter on this target. Comment + (in profileDiagnostics) a clear error.
|
|
73
|
+
if (controllers.length === 0) {
|
|
74
|
+
return { code: `/* hwtimer instance ${o.instance}: no counter device on ${chip.id} */` };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const instance = typeof o.instance === 'number' ? o.instance : parseInt(String(o.instance), 10);
|
|
78
|
+
if (isNaN(instance) || instance < 0 || instance >= controllers.length) {
|
|
79
|
+
return { code: `/* hwtimer instance ${o.instance}: out of range on ${chip.id} */` };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
switch (op.operation) {
|
|
83
|
+
default:
|
|
84
|
+
throw new Error(
|
|
85
|
+
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
86
|
+
`Open an issue or use rawCpp() to emit it manually.`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function lowerCounter(
|
|
92
|
+
op: HALOpIR,
|
|
93
|
+
chip: ZephyrChipDescriptor,
|
|
94
|
+
): { code?: string; expression?: string } {
|
|
95
|
+
const o = op as any;
|
|
96
|
+
const controllers = chip.hwtimer?.controllers ?? [];
|
|
97
|
+
|
|
98
|
+
if (controllers.length === 0) {
|
|
99
|
+
return { code: `/* ${op.operation}: no counter device on ${chip.id} */` };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const instance = typeof o.instance === 'number' ? o.instance : parseInt(String(o.instance), 10);
|
|
103
|
+
if (isNaN(instance) || instance < 0 || instance >= controllers.length) {
|
|
104
|
+
return { code: `/* counter instance ${o.instance}: out of range on ${chip.id} (${controllers.length} declared) */` };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
switch (op.operation) {
|
|
108
|
+
case 'counter.on_alarm':
|
|
109
|
+
return { code: `${cbVar(instance)} = (${o.handler});` };
|
|
110
|
+
case 'counter.start': {
|
|
111
|
+
// Apply the construction hz as the top value, arm the alarm callback,
|
|
112
|
+
// start. hz rides the op, so no ordering constraint exists. The API
|
|
113
|
+
// is counter_set_top_value(dev, const counter_top_cfg*) with a
|
|
114
|
+
// (dev, user_data) callback — the trampoline in hwtimerInitLines
|
|
115
|
+
// adapts the user's void() handler.
|
|
116
|
+
return {
|
|
117
|
+
code: [
|
|
118
|
+
`{`,
|
|
119
|
+
` ${hzVar(instance)} = ${o.hz};`,
|
|
120
|
+
` uint32_t __f = counter_get_frequency(${devVar(instance)});`,
|
|
121
|
+
` uint32_t __top = __f ? (__f / ${hzVar(instance)}) : 0U;`,
|
|
122
|
+
` if (__top > 0U) {`,
|
|
123
|
+
` struct counter_top_cfg __cfg = { .ticks = __top, .callback = ${trampVar(instance)}, .user_data = NULL, .flags = 0U };`,
|
|
124
|
+
` (void)counter_set_top_value(${devVar(instance)}, &__cfg);`,
|
|
125
|
+
` }`,
|
|
126
|
+
` (void)counter_start(${devVar(instance)});`,
|
|
127
|
+
`}`,
|
|
128
|
+
].join(' '),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
case 'counter.stop':
|
|
132
|
+
return { code: `(void)counter_stop(${devVar(instance)});` };
|
|
133
|
+
default:
|
|
134
|
+
throw new Error(
|
|
135
|
+
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
136
|
+
`Open an issue or use rawCpp() to emit it manually.`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
package/src/lowering/i2c.ts
CHANGED
|
@@ -1,126 +1,116 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// I2C lowering — transactional txbuf accumulator + per-call i2c_write
|
|
3
|
-
//
|
|
4
|
-
// Mirrors the ESP32 stateful model but simpler: Zephyr's `i2c_write(bus, buf,
|
|
5
|
-
// len, addr)` takes the address per-call, so there's no device-handle cache.
|
|
6
|
-
// The begin_transmission → write* → end_transmission sequence accumulates into
|
|
7
|
-
// `__tc_i2c<N>_txbuf` and flushes as one `i2c_write` at end_transmission.
|
|
8
|
-
// Reads go through request_from → i2c_read into `__tc_i2c<N>_rxbuf`, consumed
|
|
9
|
-
// by subsequent i2c.read / i2c.available calls.
|
|
10
|
-
//
|
|
11
|
-
// The device handle resolves at compile time via DEVICE_DT_GET(DT_NODELABEL(...)).
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
|
|
14
|
-
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
15
|
-
import type { ZephyrChipDescriptor } from '../chips/types.js';
|
|
16
|
-
import { parseControllerIndex } from './util.js';
|
|
17
|
-
|
|
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
|
-
return
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
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
|
-
return {
|
|
91
|
-
}
|
|
92
|
-
case 'i2c.
|
|
93
|
-
|
|
94
|
-
return {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
case 'i2c.recover':
|
|
119
|
-
return { code: `i2c_recover_bus(${p}_dev);` };
|
|
120
|
-
default:
|
|
121
|
-
throw new Error(
|
|
122
|
-
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
123
|
-
`Open an issue or use rawCpp() to emit it manually.`,
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// I2C lowering — transactional txbuf accumulator + per-call i2c_write
|
|
3
|
+
//
|
|
4
|
+
// Mirrors the ESP32 stateful model but simpler: Zephyr's `i2c_write(bus, buf,
|
|
5
|
+
// len, addr)` takes the address per-call, so there's no device-handle cache.
|
|
6
|
+
// The begin_transmission → write* → end_transmission sequence accumulates into
|
|
7
|
+
// `__tc_i2c<N>_txbuf` and flushes as one `i2c_write` at end_transmission.
|
|
8
|
+
// Reads go through request_from → i2c_read into `__tc_i2c<N>_rxbuf`, consumed
|
|
9
|
+
// by subsequent i2c.read / i2c.available calls.
|
|
10
|
+
//
|
|
11
|
+
// The device handle resolves at compile time via DEVICE_DT_GET(DT_NODELABEL(...)).
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
15
|
+
import type { ZephyrChipDescriptor } from '../chips/types.js';
|
|
16
|
+
import { parseControllerIndex } from './util.js';
|
|
17
|
+
|
|
18
|
+
/** The C variable prefix for a controller's state. */
|
|
19
|
+
function prefix(idx: number): string {
|
|
20
|
+
return `__tc_i2c${idx}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Emit the per-controller I2C state. Called from shimLines for each
|
|
25
|
+
* controller the program uses (gated on ctx.analysis.usesI2C).
|
|
26
|
+
*/
|
|
27
|
+
export function i2cInitLines(chip: ZephyrChipDescriptor, controllerIndex: number): string[] {
|
|
28
|
+
const ctrl = chip.i2c?.controllers[controllerIndex];
|
|
29
|
+
if (!ctrl) return [];
|
|
30
|
+
const p = prefix(controllerIndex);
|
|
31
|
+
return [
|
|
32
|
+
'// CUTTLEFISH_I2C_BEGIN',
|
|
33
|
+
`static const struct device* ${p}_dev = DEVICE_DT_GET(DT_NODELABEL(${ctrl.nodeLabel}));`,
|
|
34
|
+
'// CUTTLEFISH_I2C_END',
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Map a clock speed in Hz to an I2C_SPEED_* define. */
|
|
39
|
+
function speedForHz(hz: number): string {
|
|
40
|
+
if (hz <= 100_000) return 'I2C_SPEED_STANDARD';
|
|
41
|
+
if (hz <= 400_000) return 'I2C_SPEED_FAST';
|
|
42
|
+
if (hz <= 1_000_000) return 'I2C_SPEED_FAST_PLUS';
|
|
43
|
+
return 'I2C_SPEED_HIGH';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The (void) comma expression begin/end lower to — a no-op that references
|
|
48
|
+
* the controller's whole state block (device + transaction buffers) so a
|
|
49
|
+
* program calling only begin() stays -Werror clean (-Wunused-variable).
|
|
50
|
+
*/
|
|
51
|
+
function i2cKeepAlive(p: string): string {
|
|
52
|
+
return `(void)${p}_dev;`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** The thin-device bus-speed preamble: apply the construction hz once
|
|
56
|
+
* (i2c_configure with Zephyr's I2C_SPEED_SET tier mapping), or '' when the
|
|
57
|
+
* target constructed without hz. Guarded per controller, so the cost after
|
|
58
|
+
* the first op is one bool test. */
|
|
59
|
+
function i2cSpeedGuard(p: string, hz: unknown): string {
|
|
60
|
+
const n = typeof hz === 'number' ? hz : parseInt(String(hz ?? 0), 10);
|
|
61
|
+
if (!n || isNaN(n)) return '';
|
|
62
|
+
const speed = speedForHz(n);
|
|
63
|
+
const done = `${p}_spd_done`;
|
|
64
|
+
return `{ static bool ${done} = false; if (!${done}) { (void)i2c_configure(${p}_dev, I2C_SPEED_SET(${speed})); ${done} = true; } } `;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Resolve a HAL i2c.* op to Zephyr C++.
|
|
69
|
+
* Returns `{ code }` for statement ops, `{ expression }` for value-returning ops.
|
|
70
|
+
*/
|
|
71
|
+
export function lowerI2c(
|
|
72
|
+
op: HALOpIR,
|
|
73
|
+
chip: ZephyrChipDescriptor,
|
|
74
|
+
): { code?: string; expression?: string } {
|
|
75
|
+
const o = op as any;
|
|
76
|
+
const idx = parseControllerIndex(o.bus);
|
|
77
|
+
const p = prefix(idx);
|
|
78
|
+
|
|
79
|
+
switch (op.operation) {
|
|
80
|
+
// ── Thin I2C device (hal/i2c-target.ts) — Zephyr register verbs ──────
|
|
81
|
+
// One call per op against the controller device handle; the optional
|
|
82
|
+
// construction hz applies once via a guarded i2c_configure (the same
|
|
83
|
+
// call i2c.set_clock lowers to).
|
|
84
|
+
case 'i2c.reg_write': {
|
|
85
|
+
const pre = i2cSpeedGuard(p, o.hz);
|
|
86
|
+
return { code: `${pre} i2c_reg_write_byte(${p}_dev, static_cast<uint16_t>(${o.address}), static_cast<uint8_t>(${o.reg}), static_cast<uint8_t>(${o.value}));` };
|
|
87
|
+
}
|
|
88
|
+
case 'i2c.reg_read': {
|
|
89
|
+
const pre = i2cSpeedGuard(p, o.hz);
|
|
90
|
+
return { expression: `({ ${pre} uint8_t __v = 0; (void)i2c_reg_read_byte(${p}_dev, static_cast<uint16_t>(${o.address}), static_cast<uint8_t>(${o.reg}), &__v); __v; })` };
|
|
91
|
+
}
|
|
92
|
+
case 'i2c.reg_update': {
|
|
93
|
+
const pre = i2cSpeedGuard(p, o.hz);
|
|
94
|
+
return { code: `${pre} (void)i2c_reg_update_byte(${p}_dev, static_cast<uint16_t>(${o.address}), static_cast<uint8_t>(${o.reg}), static_cast<uint8_t>(${o.mask}), static_cast<uint8_t>(${o.value}));` };
|
|
95
|
+
}
|
|
96
|
+
case 'i2c.dev_write': {
|
|
97
|
+
const pre = i2cSpeedGuard(p, o.hz);
|
|
98
|
+
const bytes: unknown[] = o.bytes ?? [];
|
|
99
|
+
// Identifier-shaped only — a single-byte literal array arrives as
|
|
100
|
+
// numeric text ("159") and must take the literal path.
|
|
101
|
+
const isBuffer = bytes.length === 1 && typeof bytes[0] === 'string' && /^[A-Za-z_][A-Za-z0-9_]*$/.test(bytes[0] as string);
|
|
102
|
+
if (isBuffer) {
|
|
103
|
+
const name = bytes[0] as string;
|
|
104
|
+
// A named user buffer: i2c_write against its storage directly.
|
|
105
|
+
return { code: `${pre} (void)i2c_write(${p}_dev, reinterpret_cast<const uint8_t*>(${name}), sizeof(${name}), static_cast<uint16_t>(${o.address}));` };
|
|
106
|
+
}
|
|
107
|
+
const arr = `static const uint8_t __tc_i2cw[] = { ${bytes.join(', ')} };`;
|
|
108
|
+
return { code: `${pre} ${arr} (void)i2c_write(${p}_dev, __tc_i2cw, sizeof(__tc_i2cw), static_cast<uint16_t>(${o.address}));` };
|
|
109
|
+
}
|
|
110
|
+
default:
|
|
111
|
+
throw new Error(
|
|
112
|
+
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
113
|
+
`Open an issue or use rawCpp() to emit it manually.`,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|