@typecad/framework-zephyr 1.0.0-alpha.16 → 1.0.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -21
- package/README.md +49 -87
- package/dist/as-built.d.ts +2 -2
- package/dist/as-built.js +2 -2
- package/dist/audit.d.ts +111 -0
- package/dist/audit.js +416 -0
- package/dist/boardgen.d.ts +1 -9
- package/dist/boardgen.js +288 -47
- package/dist/chips/resolve.js +20 -0
- package/dist/chips/types.d.ts +22 -1
- package/dist/debug-codegen.js +1 -1
- package/dist/display/bindings.d.ts +55 -0
- package/dist/display/bindings.js +316 -0
- package/dist/display/gfx.d.ts +2 -3
- package/dist/display/gfx.js +166 -154
- package/dist/display/index.js +20 -1
- package/dist/display/mipi-dbi-host.d.ts +9 -0
- package/dist/display/mipi-dbi-host.js +174 -0
- package/dist/display/profiles.d.ts +109 -4
- package/dist/display/profiles.js +270 -7
- package/dist/display/touch-adapter.js +119 -49
- package/dist/display/ui-adapter-eink.d.ts +2 -0
- package/dist/display/ui-adapter-eink.js +4 -0
- package/dist/display/ui-adapter-gray.d.ts +8 -0
- package/dist/display/ui-adapter-gray.js +170 -0
- package/dist/display/ui-adapter-mono.d.ts +13 -0
- package/dist/display/ui-adapter-mono.js +230 -0
- package/dist/display/ui-adapter-native.d.ts +10 -0
- package/dist/display/ui-adapter-native.js +295 -0
- package/dist/display/ui-adapter-shared.d.ts +11 -0
- package/dist/display/ui-adapter-shared.js +122 -0
- package/dist/display/ui-adapter.js +510 -558
- package/dist/doctor.js +4 -4
- package/dist/dt-config/custom-board.js +2 -2
- package/dist/dt-config/kconfig.d.ts +62 -1
- package/dist/dt-config/kconfig.js +141 -38
- package/dist/dt-config/overlay.d.ts +15 -2
- package/dist/dt-config/overlay.js +433 -18
- package/dist/framework.manifest.d.ts +10 -4
- package/dist/framework.manifest.js +133 -17
- package/dist/index.d.ts +2 -0
- package/dist/index.js +14 -6
- package/dist/licenses.d.ts +2 -2
- package/dist/licenses.js +13 -92
- package/dist/lowering/can.d.ts +25 -0
- package/dist/lowering/can.js +97 -0
- package/dist/lowering/clock.d.ts +17 -0
- package/dist/lowering/clock.js +58 -0
- package/dist/lowering/fs.js +1 -1
- package/dist/lowering/gpio.js +0 -32
- package/dist/lowering/hid.d.ts +27 -0
- package/dist/lowering/hid.js +244 -0
- package/dist/lowering/http.js +264 -32
- package/dist/lowering/i2c.d.ts +8 -0
- package/dist/lowering/i2c.js +137 -5
- package/dist/lowering/i2s.d.ts +27 -0
- package/dist/lowering/i2s.js +98 -0
- package/dist/lowering/index.d.ts +9 -1
- package/dist/lowering/index.js +25 -1
- package/dist/lowering/interrupts.js +6 -0
- package/dist/lowering/matrix.d.ts +15 -0
- package/dist/lowering/matrix.js +63 -0
- package/dist/lowering/mqtt.js +110 -8
- package/dist/lowering/power.d.ts +3 -2
- package/dist/lowering/power.js +20 -45
- package/dist/lowering/pwm.js +25 -0
- package/dist/lowering/sensor.d.ts +2 -2
- package/dist/lowering/sensor.js +8 -4
- package/dist/lowering/strip.d.ts +16 -0
- package/dist/lowering/strip.js +70 -0
- package/dist/lowering/thread.js +5 -1
- package/dist/lowering/trace.d.ts +44 -0
- package/dist/lowering/trace.js +239 -0
- package/dist/lowering/uart.js +6 -1
- package/dist/lowering/usb.d.ts +3 -1
- package/dist/lowering/usb.js +16 -13
- package/dist/lowering/wdt.js +2 -29
- package/dist/sbom.d.ts +181 -0
- package/dist/sbom.js +901 -0
- package/dist/sdk/board-catalog-sync.d.ts +1 -3
- package/dist/sdk/board-catalog-sync.js +4 -10
- package/dist/strategy.d.ts +82 -46
- package/dist/strategy.js +639 -182
- package/dist/tmp-probe.d.ts +2 -0
- package/dist/tmp-probe.js +9 -0
- package/dist/toolchain/debug-config.d.ts +50 -90
- package/dist/toolchain/debug-config.js +239 -510
- package/dist/toolchain/env-check.d.ts +1 -3
- package/dist/toolchain/env-check.js +2 -7
- package/dist/toolchain/index.d.ts +28 -3
- package/dist/toolchain/index.js +498 -62
- package/dist/toolchain/runners.d.ts +16 -0
- package/dist/toolchain/runners.js +75 -0
- package/dist/toolchain/scaffold.d.ts +5 -2
- package/dist/toolchain/scaffold.js +79 -15
- package/dist/toolchain/west-discover.d.ts +6 -0
- package/dist/toolchain/west-discover.js +36 -13
- package/dist/toolchain/west-spawn.js +8 -2
- package/dist/west-inventory.d.ts +25 -0
- package/dist/west-inventory.js +97 -0
- package/installer/README.md +328 -328
- package/installer/install.sh +2 -2
- package/installer/templates/project/.typecad/activate-zephyr.ps1 +1 -1
- package/installer/templates/project/.typecad/activate-zephyr.sh +1 -1
- package/installer/templates/project/.vscode/settings.json +1 -1
- package/installer/templates/project/README.md +2 -2
- package/package.json +5 -5
- package/src/as-built.ts +206 -206
- package/src/audit.ts +529 -0
- package/src/boardgen.ts +265 -50
- package/src/chips/resolve.ts +21 -0
- package/src/chips/types.ts +10 -1
- package/src/display/bindings.ts +347 -0
- package/src/display/gfx.ts +318 -306
- package/src/display/index.ts +87 -70
- package/src/display/mipi-dbi-host.ts +183 -0
- package/src/display/profiles.ts +458 -139
- package/src/display/touch-adapter.ts +119 -49
- package/src/display/ui-adapter-eink.ts +13 -0
- package/src/display/ui-adapter-gray.ts +178 -0
- package/src/display/ui-adapter-mono.ts +238 -0
- package/src/display/ui-adapter-native.ts +304 -0
- package/src/display/ui-adapter-shared.ts +125 -0
- package/src/display/ui-adapter.ts +732 -781
- package/src/doctor.ts +4 -4
- package/src/dt-config/custom-board.ts +2 -2
- package/src/dt-config/kconfig.ts +647 -505
- package/src/dt-config/overlay.ts +1475 -1058
- package/src/framework.manifest.ts +659 -535
- package/src/index.ts +16 -6
- package/src/licenses.ts +346 -425
- package/src/lowering/can.ts +140 -0
- package/src/lowering/clock.ts +91 -0
- package/src/lowering/fs.ts +135 -135
- package/src/lowering/gpio.ts +0 -33
- package/src/lowering/hid.ts +261 -0
- package/src/lowering/http.ts +264 -32
- package/src/lowering/i2c.ts +142 -5
- package/src/lowering/i2s.ts +143 -0
- package/src/lowering/index.ts +18 -1
- package/src/lowering/interrupts.ts +6 -0
- package/src/lowering/matrix.ts +70 -0
- package/src/lowering/mqtt.ts +109 -8
- package/src/lowering/power.ts +41 -0
- package/src/lowering/pwm.ts +192 -167
- package/src/lowering/sensor.ts +159 -155
- package/src/lowering/strip.ts +81 -0
- package/src/lowering/thread.ts +5 -1
- package/src/lowering/trace.ts +270 -0
- package/src/lowering/uart.ts +6 -1
- package/src/lowering/usb.ts +16 -13
- package/src/lowering/wdt.ts +2 -25
- package/src/sbom.ts +1117 -0
- package/src/sdk/board-catalog-sync.ts +4 -25
- package/src/strategy.ts +2680 -2309
- package/src/toolchain/debug-config.ts +262 -522
- package/src/toolchain/env-check.ts +279 -285
- package/src/toolchain/index.ts +1792 -1359
- package/src/toolchain/runners.ts +80 -0
- package/src/toolchain/scaffold.ts +355 -296
- package/src/toolchain/west-discover.ts +35 -13
- package/src/toolchain/west-spawn.ts +174 -168
- package/src/west-inventory.ts +102 -0
- package/dist/async/timer-polyfill.d.ts +0 -10
- package/dist/async/timer-polyfill.js +0 -95
- package/dist/chips/board-overrides.d.ts +0 -7
- package/dist/chips/board-overrides.js +0 -11
- package/dist/chips/esp32.d.ts +0 -2
- package/dist/chips/esp32.js +0 -71
- package/dist/chips/esp32s3.d.ts +0 -2
- package/dist/chips/esp32s3.js +0 -103
- package/dist/chips/soc/.d.ts +0 -2
- package/dist/chips/soc/.js +0 -129
- package/dist/chips/soc/esp32.d.ts +0 -2
- package/dist/chips/soc/esp32.js +0 -120
- package/dist/chips/soc/esp32c3.d.ts +0 -2
- package/dist/chips/soc/esp32c3.js +0 -90
- package/dist/chips/soc/esp32c6.d.ts +0 -2
- package/dist/chips/soc/esp32c6.js +0 -109
- package/dist/chips/soc/esp32s3.d.ts +0 -2
- package/dist/chips/soc/esp32s3.js +0 -189
- package/dist/chips/soc/index.d.ts +0 -2
- package/dist/chips/soc/index.js +0 -23
- package/dist/chips/soc/nrf52840.d.ts +0 -2
- package/dist/chips/soc/nrf52840.js +0 -130
- package/dist/chips/soc/rp2040.d.ts +0 -2
- package/dist/chips/soc/rp2040.js +0 -141
- package/dist/chips/soc/rp2350a.d.ts +0 -2
- package/dist/chips/soc/rp2350a.js +0 -145
- package/dist/chips/soc/samd21g18a.d.ts +0 -2
- package/dist/chips/soc/samd21g18a.js +0 -143
- package/dist/chips/soc/stm32f411xe.d.ts +0 -2
- package/dist/chips/soc/stm32f411xe.js +0 -251
- package/dist/chips/xiao-ble.d.ts +0 -2
- package/dist/chips/xiao-ble.js +0 -100
- package/dist/lowering/pulse.d.ts +0 -7
- package/dist/lowering/pulse.js +0 -51
- package/dist/lowering/tone.d.ts +0 -10
- package/dist/lowering/tone.js +0 -63
- package/dist/lowering/worker-backing.d.ts +0 -14
- package/dist/lowering/worker-backing.js +0 -79
- package/dist/lowering/worker.d.ts +0 -6
- package/dist/lowering/worker.js +0 -14
- package/dist/sdk/board-data.generated.d.ts +0 -2
- package/dist/sdk/board-data.generated.js +0 -4
- package/dist/sdk/catalog-walker.d.ts +0 -90
- package/dist/sdk/catalog-walker.js +0 -682
- package/dist/sdk/dts-reader.d.ts +0 -83
- package/dist/sdk/dts-reader.js +0 -596
- package/src/debug-codegen.ts +0 -207
|
@@ -96,6 +96,85 @@ export default defineFrameworkManifest({
|
|
|
96
96
|
'pwm.set_pulse': 'supported',
|
|
97
97
|
'pwm.set_duty': 'supported',
|
|
98
98
|
'pwm.set_period': 'supported',
|
|
99
|
+
// Servo (hal/servo.ts): calibrated 50 Hz sugar on the same channel —
|
|
100
|
+
// clamping and the angle→pulse mapping run in the lowered C++.
|
|
101
|
+
'pwm.servo_us': 'supported',
|
|
102
|
+
'pwm.servo_angle': 'supported',
|
|
103
|
+
'pwm.servo_idle': 'supported',
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
// ── Supported: LED strip (ws2812-spi over led_strip API) ───────────────
|
|
107
|
+
strip: {
|
|
108
|
+
// DAC discipline: lowers on every board with a wired SPI controller;
|
|
109
|
+
// a board with none lowers to a comment (profileDiagnostics flags it).
|
|
110
|
+
supported: true,
|
|
111
|
+
partialCoverage: true,
|
|
112
|
+
ops: {
|
|
113
|
+
// Strip (hal/strip.ts): buffer edits + one-wire-transaction show.
|
|
114
|
+
'strip.set_pixel': 'supported',
|
|
115
|
+
'strip.fill': 'supported',
|
|
116
|
+
'strip.show': 'supported',
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
// ── Board-gated: USB HID keyboard/mouse (zephyr,hid-device) ───────────
|
|
120
|
+
hid: {
|
|
121
|
+
// Same BOARD-GATED shape as usb below: the lowering only fires when
|
|
122
|
+
// the board's manifest carries zephyr.usb.* — the manifest probe runs
|
|
123
|
+
// with no board, so the honest declaration is unsupported here. The
|
|
124
|
+
// board module exports Keyboard/Mouse only on USB-capable boards
|
|
125
|
+
// (the module-resolution gate); one HID interface per program (the v1
|
|
126
|
+
// ceiling — mixing the two classes is a compile-time #error).
|
|
127
|
+
supported: false,
|
|
128
|
+
unsupportedReason: 'Board-gated: HID lowers only on boards whose DTS enables the USB device controller (boardgen emits zephyr.usb.* from the catalog).',
|
|
129
|
+
partialCoverage: false,
|
|
130
|
+
ops: unsupportedOps('hid.'),
|
|
131
|
+
},
|
|
132
|
+
// ── Supported: CAN bus (harvested can@ controllers) ────────────────────
|
|
133
|
+
can: {
|
|
134
|
+
supported: true,
|
|
135
|
+
partialCoverage: true,
|
|
136
|
+
ops: {
|
|
137
|
+
// Classic CAN (11/29-bit ids, ≤8-byte payloads). Partial: CAN-FD,
|
|
138
|
+
// bitrate data phase, and RTR frames are not surfaced in v1.
|
|
139
|
+
'can.begin': 'supported',
|
|
140
|
+
'can.send': 'supported',
|
|
141
|
+
'can.on_receive': 'supported',
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
// ── Supported: wall-clock time (rtc alias / counter shim) ─────────────
|
|
145
|
+
clock: {
|
|
146
|
+
supported: true,
|
|
147
|
+
partialCoverage: true,
|
|
148
|
+
ops: {
|
|
149
|
+
// set/now in Unix epoch seconds. Partial: v1 semantics are
|
|
150
|
+
// session-scoped on counter-backed boards — only hardware-calendar
|
|
151
|
+
// aliases persist across power loss.
|
|
152
|
+
'clock.set': 'supported',
|
|
153
|
+
'clock.now': 'supported',
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
// ── Supported: explicit power-state entry (sys_poweroff) ───────────────
|
|
157
|
+
power: {
|
|
158
|
+
supported: true,
|
|
159
|
+
partialCoverage: true,
|
|
160
|
+
ops: {
|
|
161
|
+
// Soft-off entry — never returns; wake by reset or a board wake
|
|
162
|
+
// source. Partial: the light states belong to the idle policy, not
|
|
163
|
+
// the app (no op surface for them in v1).
|
|
164
|
+
'power.off': 'supported',
|
|
165
|
+
// off_for arms the RTC wake timer before soft-off — ESP32 family
|
|
166
|
+
// (the harvested rtc_timer fact); boards without the fact lower
|
|
167
|
+
// to a comment naming the limitation (the DAC discipline).
|
|
168
|
+
'power.off_for': 'supported',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
// ── Supported: GPIO key matrix (gpio-kbd-matrix, input subsystem) ─────
|
|
172
|
+
matrix: {
|
|
173
|
+
supported: true,
|
|
174
|
+
partialCoverage: false,
|
|
175
|
+
ops: {
|
|
176
|
+
// Matrix (hal/matrix.ts): (row, col, pressed) trampoline.
|
|
177
|
+
'matrix.on_key': 'supported',
|
|
99
178
|
},
|
|
100
179
|
},
|
|
101
180
|
// ── Supported: ADC (SAADC via adc_read + channel setup) ────────────────
|
|
@@ -141,6 +220,12 @@ export default defineFrameworkManifest({
|
|
|
141
220
|
'i2c.reg_read': 'supported',
|
|
142
221
|
'i2c.reg_update': 'supported',
|
|
143
222
|
'i2c.dev_write': 'supported',
|
|
223
|
+
// I2C responder (hal/i2c-responder.ts): this board as an I2C target.
|
|
224
|
+
'i2c.resp_on_receive': 'supported',
|
|
225
|
+
'i2c.resp_on_request': 'supported',
|
|
226
|
+
'i2c.resp_available': 'supported',
|
|
227
|
+
'i2c.resp_read': 'supported',
|
|
228
|
+
'i2c.resp_write': 'supported',
|
|
144
229
|
},
|
|
145
230
|
},
|
|
146
231
|
spi: {
|
|
@@ -276,11 +361,25 @@ export default defineFrameworkManifest({
|
|
|
276
361
|
partialCoverage: true,
|
|
277
362
|
// Partial: mono profiles (ssd1306-zephyr) drive display.* ops via the
|
|
278
363
|
// direct GFX runtime only — no CuttlefishGFX UI rendering path. The
|
|
279
|
-
//
|
|
280
|
-
//
|
|
281
|
-
//
|
|
282
|
-
|
|
283
|
-
|
|
364
|
+
// direct-spi UI adapters (st7796-zephyr, ili9341-zephyr) drive the
|
|
365
|
+
// panel over spi_write with per-controller Adafruit init tables;
|
|
366
|
+
// st7796-zephyr is the full-fidelity path on the clone rig
|
|
367
|
+
// (18-bit mode, hardware-verified incl. colors + touch interaction;
|
|
368
|
+
// the demo needs psram:'opi' for full rendering and resetPin for the
|
|
369
|
+
// touch module's power enable). The zephyr-display transport rides
|
|
370
|
+
// in-tree panel drivers through Zephyr's display API: st7796s via an
|
|
371
|
+
// adapter-emitted CS-holding mipi-dbi host — colors hardware-confirmed
|
|
372
|
+
// correct on the rig with the byte-swap + CS-hold knobs (the stock
|
|
373
|
+
// bridge corrupts bursts on this clone; a ladder test observed slight
|
|
374
|
+
// uniform dimness vs the direct path's 18-bit mode, so direct remains
|
|
375
|
+
// the max-fidelity option there); ili9341 via the stock mipi-dbi-spi
|
|
376
|
+
// bridge is compile/link-verified only. Drop-in configs (display.driver
|
|
377
|
+
// = any bound compatible + geometry + quirk flags) ride the same path.
|
|
378
|
+
// Touch: FT6336U through the input subsystem (in-tree driver,
|
|
379
|
+
// polling mode, hardware-verified); XPT2046 stays on the raw adapter
|
|
380
|
+
// (the in-tree driver's DT scaling would double-apply calibration).
|
|
381
|
+
unsupportedReason: 'Mono panels (ssd1306) are direct-op only (no UI rendering); the direct-spi ili9341 UI path is not yet hardware-verified; the zephyr-display transport is hue-verified but 16-bit-brightness-limited on the clone st7796s (use direct-spi there) and compile-verified on ili9341; e-ink is out of scope at this time.',
|
|
382
|
+
drivers: ['ili9341-zephyr', 'ili9341-zephyr-display', 'st7796-zephyr', 'st7796-zephyr-display', 'ssd1306-zephyr'],
|
|
284
383
|
colorFormat: 'rgb565',
|
|
285
384
|
ops: {
|
|
286
385
|
'display.init': 'supported',
|
|
@@ -359,14 +458,17 @@ export default defineFrameworkManifest({
|
|
|
359
458
|
supported: true,
|
|
360
459
|
partialCoverage: false,
|
|
361
460
|
// MQTT 3.1.1 client over Zephyr <zephyr/net/mqtt.h> (mqtts:// TLS via
|
|
362
|
-
// MQTT_TRANSPORT_SECURE + the shared mbedTLS matrix
|
|
363
|
-
//
|
|
364
|
-
//
|
|
365
|
-
//
|
|
461
|
+
// MQTT_TRANSPORT_SECURE + the shared mbedTLS matrix). caCert pins the
|
|
462
|
+
// broker's CA (DER-decoded at emit, tls_credential_add sec tag,
|
|
463
|
+
// TLS_PEER_VERIFY_REQUIRED); mqtts:// without a CA stays
|
|
464
|
+
// encrypted-but-unverified (TLS_PEER_VERIFY_NONE). The __tc_mqtt
|
|
465
|
+
// shim resolves the broker, runs the mqtt_input/mqtt_live poll loop on
|
|
466
|
+
// a background k_thread, and dispatches incoming PUBLISHes to the user's
|
|
366
467
|
// onMessage callback. Requires a networked target (ESP32 WiFi);
|
|
367
468
|
// profileDiagnostics flags usage on a radioless chip.
|
|
368
469
|
ops: {
|
|
369
|
-
'mqtt.connect': 'supported', 'mqtt.
|
|
470
|
+
'mqtt.connect': 'supported', 'mqtt.set_ca_cert': 'supported',
|
|
471
|
+
'mqtt.on_message': 'supported',
|
|
370
472
|
'mqtt.subscribe': 'supported', 'mqtt.publish': 'supported',
|
|
371
473
|
'mqtt.connected': 'supported', 'mqtt.disconnect': 'supported',
|
|
372
474
|
},
|
|
@@ -385,10 +487,13 @@ export default defineFrameworkManifest({
|
|
|
385
487
|
},
|
|
386
488
|
},
|
|
387
489
|
i2s: {
|
|
388
|
-
supported:
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
490
|
+
supported: true,
|
|
491
|
+
partialCoverage: true,
|
|
492
|
+
ops: {
|
|
493
|
+
'i2s.write': 'supported',
|
|
494
|
+
'i2s.read': 'supported',
|
|
495
|
+
'i2s.read_at': 'supported',
|
|
496
|
+
},
|
|
392
497
|
},
|
|
393
498
|
twai: {
|
|
394
499
|
supported: false,
|
|
@@ -502,10 +607,21 @@ export default defineFrameworkManifest({
|
|
|
502
607
|
compat: {
|
|
503
608
|
zephyr: '>=4.3 <5.0',
|
|
504
609
|
},
|
|
505
|
-
// `
|
|
610
|
+
// `typecad-hal doctor` prints the detected Zephyr version + compat result and
|
|
506
611
|
// previews how the configured board target resolves for that version.
|
|
507
612
|
doctor: { available: true },
|
|
508
|
-
// `
|
|
509
|
-
// and resolves each one's SPDX license
|
|
613
|
+
// `typecad-hal licenses` enumerates the Zephyr kernel + west manifest projects
|
|
614
|
+
// and resolves each one's SPDX license.
|
|
510
615
|
licenses: { available: true },
|
|
616
|
+
// `typecad-hal sbom` emits a build-true SBOM (CycloneDX 1.6 / SPDX 2.3):
|
|
617
|
+
// linked west modules + kernel with commit SHAs and licenses, the hashed
|
|
618
|
+
// firmware artifact, the board, and the toolchain in `formulation`;
|
|
619
|
+
// --check/--diff gate the record against the build.
|
|
620
|
+
sbom: { available: true },
|
|
621
|
+
// `typecad-hal audit` evaluates the last build's merged Kconfig against a
|
|
622
|
+
// security baseline (shell/console exposure, entropy, watchdog, hard-coded
|
|
623
|
+
// credentials...), with committed waivers (.typecad-hal/audit-waivers.json)
|
|
624
|
+
// recorded as deviations and a machine-readable sidecar
|
|
625
|
+
// (<buildDir>/security-audit.json).
|
|
626
|
+
audit: { available: true },
|
|
511
627
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export { bossacTouchReset } from './toolchain/bossac-touch.js';
|
|
|
5
5
|
export { writeProjectDebugArtifacts } from './toolchain/debug-config.js';
|
|
6
6
|
export { runDoctor as doctor } from './doctor.js';
|
|
7
7
|
export { runLicensesPresenter as licenses } from './licenses.js';
|
|
8
|
+
export { runSbomPresenter as sbom } from './sbom.js';
|
|
9
|
+
export { runAuditPresenter as audit } from './audit.js';
|
|
8
10
|
export { setActiveChip, getActiveChip, NO_BOARD_CHIP, } from './chips/index.js';
|
|
9
11
|
export type { ZephyrChipDescriptor, ZephyrGpioDtSpec, } from './chips/types.js';
|
|
10
12
|
export { syncBoardCatalog, ensureFreshBoardCatalog, loadBoardCatalogOverlay, resetBoardCatalogOverlayCache, } from './sdk/board-catalog-sync.js';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// @typecad/framework-zephyr — public exports
|
|
3
3
|
//
|
|
4
|
-
// The
|
|
4
|
+
// The typecad-hal loader (framework-package.ts) requires a `FrameworkStrategy`
|
|
5
5
|
// export (the PlatformStrategy class it instantiates) and an optional
|
|
6
6
|
// `Toolchain`. This package aliases ZephyrStrategy → FrameworkStrategy.
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
@@ -9,25 +9,33 @@ export { ZephyrStrategy as FrameworkStrategy } from './strategy.js';
|
|
|
9
9
|
export { ZephyrStrategy } from './strategy.js';
|
|
10
10
|
export { Toolchain } from './toolchain/index.js';
|
|
11
11
|
export { bossacTouchReset } from './toolchain/bossac-touch.js';
|
|
12
|
-
// Create-time starter debug artifacts. The `
|
|
12
|
+
// Create-time starter debug artifacts. The `typecad-hal create` flow reads this
|
|
13
13
|
// optional named export off the loaded framework module (same loader pattern
|
|
14
14
|
// as doctor/licenses) and calls it for freshly scaffolded projects, so F5 in
|
|
15
15
|
// VS Code works before the first build. No-ops for non-GDB targets.
|
|
16
16
|
export { writeProjectDebugArtifacts } from './toolchain/debug-config.js';
|
|
17
|
-
// `
|
|
17
|
+
// `typecad-hal doctor` — verify the installed Zephyr is reachable + inside the
|
|
18
18
|
// declared compat range, and preview board-target normalization. Re-exported
|
|
19
19
|
// under the dispatcher-facing alias `doctor` so the loader picks it up as
|
|
20
20
|
// mod.doctor (see framework-package.ts).
|
|
21
21
|
export { runDoctor as doctor } from './doctor.js';
|
|
22
|
-
// `
|
|
22
|
+
// `typecad-hal licenses` — enumerate the Zephyr kernel + west manifest projects
|
|
23
23
|
// and resolve each one's SPDX license. Re-exported under the dispatcher-facing
|
|
24
24
|
// alias `licenses` so the loader picks it up as mod.licenses (see
|
|
25
|
-
// framework-package.ts).
|
|
25
|
+
// framework-package.ts).
|
|
26
26
|
export { runLicensesPresenter as licenses } from './licenses.js';
|
|
27
|
+
// `typecad-hal sbom` — emit/verify a build-true software bill of materials
|
|
28
|
+
// (CycloneDX 1.6 / SPDX 2.3). Re-exported under the dispatcher-facing alias
|
|
29
|
+
// `sbom` so the loader picks it up as mod.sbom (see framework-package.ts).
|
|
30
|
+
export { runSbomPresenter as sbom } from './sbom.js';
|
|
31
|
+
// `typecad-hal audit` — evaluate the last build's merged Kconfig against the
|
|
32
|
+
// security baseline, with committed waivers recorded as deviations.
|
|
33
|
+
// Re-exported under the dispatcher-facing alias `audit` (same loader pattern).
|
|
34
|
+
export { runAuditPresenter as audit } from './audit.js';
|
|
27
35
|
// Chip descriptor cache (the lowering's resolved-board view; no curated
|
|
28
36
|
// registry — every board reconstructs from its generated manifest).
|
|
29
37
|
export { setActiveChip, getActiveChip, NO_BOARD_CHIP, } from './chips/index.js';
|
|
30
38
|
// Board catalog sync — regenerate the local board overlay from the user's
|
|
31
|
-
// own Zephyr tree (`
|
|
39
|
+
// own Zephyr tree (`typecad-hal board sync`), so board add/change/remove
|
|
32
40
|
// tracks `west update` instead of cuttlefish releases.
|
|
33
41
|
export { syncBoardCatalog, ensureFreshBoardCatalog, loadBoardCatalogOverlay, resetBoardCatalogOverlayCache, } from './sdk/board-catalog-sync.js';
|
package/dist/licenses.d.ts
CHANGED
|
@@ -47,13 +47,13 @@ export declare function scanZephyrLicenses(runner: ZephyrLicensesRunner, all?: b
|
|
|
47
47
|
/** @internal Test-only override of the default runner. Pass null to simulate west-not-found. */
|
|
48
48
|
export declare function __setLicensesRunnerForTest(runner: ZephyrLicensesRunner | null | undefined): void;
|
|
49
49
|
/**
|
|
50
|
-
* `
|
|
50
|
+
* `typecad-hal licenses` (Zephyr) presenter. Enumerates the Zephyr kernel +
|
|
51
51
|
* west manifest projects, resolves each one's license, classifies copyleft
|
|
52
52
|
* risk, and renders a sorted table. Warns on unknown licenses; sets
|
|
53
53
|
* process.exitCode under --strict when any strong-copyleft dependency is
|
|
54
54
|
* present. Never calls process.exit().
|
|
55
55
|
*
|
|
56
56
|
* Default scope = only the modules the firmware actually links (from the last
|
|
57
|
-
* `
|
|
57
|
+
* `typecad-hal build`); `--all` lists every west manifest module.
|
|
58
58
|
*/
|
|
59
59
|
export declare function runLicensesPresenter(strict: boolean, all: boolean): void;
|
package/dist/licenses.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// @typecad/framework-zephyr — Zephyr license scanner
|
|
3
3
|
//
|
|
4
|
-
// Zephyr-specific enumeration + presenter for the `
|
|
4
|
+
// Zephyr-specific enumeration + presenter for the `typecad-hal licenses`
|
|
5
5
|
// subcommand. The framework-agnostic SPDX detection engine lives in the shared
|
|
6
6
|
// cuttlefish core (`@typecad/cuttlefish/api/shared`); this module owns only the
|
|
7
7
|
// Zephyr pieces: discovering the west workspace, enumerating the Zephyr kernel
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// links, derived from the build's `compile_commands.json` (a module is
|
|
13
13
|
// listed iff its sources were compiled). A west manifest carries every
|
|
14
14
|
// vendor HAL/library; almost none are linked by a single project, so the
|
|
15
|
-
// default filters them out. Requires a prior `
|
|
15
|
+
// default filters them out. Requires a prior `typecad-hal build` — without
|
|
16
16
|
// one, only the kernel is reported with a hint to build first.
|
|
17
17
|
// - `--all`: every west manifest project (the whole workspace).
|
|
18
18
|
//
|
|
@@ -23,40 +23,11 @@ import { spawnSync } from 'node:child_process';
|
|
|
23
23
|
import { readFileSync, readdirSync } from 'node:fs';
|
|
24
24
|
import * as path from 'node:path';
|
|
25
25
|
import * as ui from '@typecad/cuttlefish/utils/ui';
|
|
26
|
-
import {
|
|
26
|
+
import { loadTypecadConfig } from '@typecad/cuttlefish/config-loader';
|
|
27
27
|
import { resolveLibraryLicense, RISK_RANK, riskBracket, statusMark, countByRisk, } from '@typecad/cuttlefish/api/shared';
|
|
28
28
|
import { discoverWest } from './toolchain/west-discover.js';
|
|
29
29
|
import { westSpawn } from './toolchain/west-spawn.js';
|
|
30
|
-
|
|
31
|
-
// Linked-module filtering (project scope)
|
|
32
|
-
// ---------------------------------------------------------------------------
|
|
33
|
-
/** Normalize a path for case-insensitive, separator-agnostic comparison. */
|
|
34
|
-
function norm(p) {
|
|
35
|
-
return p.split('\\').join('/').toLowerCase();
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Filter the west manifest to the modules whose sources were compiled in the
|
|
39
|
-
* last build. A module is "linked" iff some compiled translation unit lives
|
|
40
|
-
* under its abspath. If the build data is unparseable, no filtering is applied
|
|
41
|
-
* (degrade to listing all modules rather than reporting nothing).
|
|
42
|
-
*/
|
|
43
|
-
function filterLinkedModules(ccText, modules) {
|
|
44
|
-
let arr;
|
|
45
|
-
try {
|
|
46
|
-
arr = JSON.parse(ccText);
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
return modules;
|
|
50
|
-
}
|
|
51
|
-
if (!Array.isArray(arr))
|
|
52
|
-
return modules;
|
|
53
|
-
// One normalized blob of every compiled source path; membership is then a
|
|
54
|
-
// substring check per module (O(modules) after an O(TUs) join).
|
|
55
|
-
const blob = arr
|
|
56
|
-
.map((e) => norm(typeof e?.file === 'string' ? e.file : ''))
|
|
57
|
-
.join('\n');
|
|
58
|
-
return modules.filter((m) => blob.includes(norm(m.abspath) + '/'));
|
|
59
|
-
}
|
|
30
|
+
import { filterLinkedModules, findCompileCommandsPath } from './west-inventory.js';
|
|
60
31
|
// ---------------------------------------------------------------------------
|
|
61
32
|
// scanZephyrLicenses — enumerate + resolve the workspace dependency set
|
|
62
33
|
// ---------------------------------------------------------------------------
|
|
@@ -139,59 +110,6 @@ export function scanZephyrLicenses(runner, all = false) {
|
|
|
139
110
|
// ---------------------------------------------------------------------------
|
|
140
111
|
// Default runner — wires seams to discoverWest + westSpawn + fs
|
|
141
112
|
// ---------------------------------------------------------------------------
|
|
142
|
-
/**
|
|
143
|
-
* Find the build's compile_commands.json under cwd. Cuttlefish's Zephyr project
|
|
144
|
-
* root is the transpile output dir (e.g. `<cwd>/src/out`), so the build dir is
|
|
145
|
-
* `<root>/build` — not necessarily `<cwd>/build`. Check the common layouts,
|
|
146
|
-
* then fall back to a bounded search (skipping node_modules/.git/dist).
|
|
147
|
-
*/
|
|
148
|
-
function findCompileCommandsText(readFile, readdir) {
|
|
149
|
-
const direct = [
|
|
150
|
-
path.join(process.cwd(), 'build', 'compile_commands.json'),
|
|
151
|
-
path.join(process.cwd(), 'out', 'build', 'compile_commands.json'),
|
|
152
|
-
path.join(process.cwd(), 'src', 'out', 'build', 'compile_commands.json'),
|
|
153
|
-
];
|
|
154
|
-
for (const c of direct) {
|
|
155
|
-
const text = readFile(c);
|
|
156
|
-
if (text)
|
|
157
|
-
return text;
|
|
158
|
-
}
|
|
159
|
-
// Bounded recursive search for a build/compile_commands.json.
|
|
160
|
-
const isCc = (p) => {
|
|
161
|
-
const n = norm(p);
|
|
162
|
-
return n.endsWith('/build/compile_commands.json') || n.endsWith('\\build\\compile_commands.json');
|
|
163
|
-
};
|
|
164
|
-
let found;
|
|
165
|
-
const seen = new Set();
|
|
166
|
-
const walk = (dir, depth) => {
|
|
167
|
-
if (found || depth > 4 || seen.has(dir))
|
|
168
|
-
return;
|
|
169
|
-
seen.add(dir);
|
|
170
|
-
let entries;
|
|
171
|
-
try {
|
|
172
|
-
entries = readdir(dir);
|
|
173
|
-
}
|
|
174
|
-
catch {
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
for (const e of entries) {
|
|
178
|
-
const full = path.join(dir, e);
|
|
179
|
-
if (e === 'compile_commands.json' && isCc(full)) {
|
|
180
|
-
found = full;
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
for (const e of entries) {
|
|
185
|
-
if (found)
|
|
186
|
-
return;
|
|
187
|
-
if (e === 'node_modules' || e === '.git' || e === 'dist' || e.startsWith('.'))
|
|
188
|
-
continue;
|
|
189
|
-
walk(path.join(dir, e), depth + 1);
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
walk(process.cwd(), 0);
|
|
193
|
-
return found ? (readFile(found) ?? null) : null;
|
|
194
|
-
}
|
|
195
113
|
function defaultRunner() {
|
|
196
114
|
const install = discoverWest();
|
|
197
115
|
if (!install)
|
|
@@ -257,7 +175,10 @@ function defaultRunner() {
|
|
|
257
175
|
topdir,
|
|
258
176
|
listModules,
|
|
259
177
|
zephyrBase,
|
|
260
|
-
compileCommands: () =>
|
|
178
|
+
compileCommands: () => {
|
|
179
|
+
const p = findCompileCommandsPath(readFile, readdir);
|
|
180
|
+
return p ? (readFile(p) ?? null) : null;
|
|
181
|
+
},
|
|
261
182
|
readFile,
|
|
262
183
|
readdir,
|
|
263
184
|
};
|
|
@@ -271,14 +192,14 @@ export function __setLicensesRunnerForTest(runner) {
|
|
|
271
192
|
testRunner = runner;
|
|
272
193
|
}
|
|
273
194
|
/**
|
|
274
|
-
* `
|
|
195
|
+
* `typecad-hal licenses` (Zephyr) presenter. Enumerates the Zephyr kernel +
|
|
275
196
|
* west manifest projects, resolves each one's license, classifies copyleft
|
|
276
197
|
* risk, and renders a sorted table. Warns on unknown licenses; sets
|
|
277
198
|
* process.exitCode under --strict when any strong-copyleft dependency is
|
|
278
199
|
* present. Never calls process.exit().
|
|
279
200
|
*
|
|
280
201
|
* Default scope = only the modules the firmware actually links (from the last
|
|
281
|
-
* `
|
|
202
|
+
* `typecad-hal build`); `--all` lists every west manifest module.
|
|
282
203
|
*/
|
|
283
204
|
export function runLicensesPresenter(strict, all) {
|
|
284
205
|
ui.printHeader();
|
|
@@ -289,7 +210,7 @@ export function runLicensesPresenter(strict, all) {
|
|
|
289
210
|
// never blocks the license scan.
|
|
290
211
|
let buildTarget;
|
|
291
212
|
try {
|
|
292
|
-
buildTarget =
|
|
213
|
+
buildTarget = loadTypecadConfig(process.cwd())?.buildTarget;
|
|
293
214
|
}
|
|
294
215
|
catch {
|
|
295
216
|
/* best-effort */
|
|
@@ -314,8 +235,8 @@ export function runLicensesPresenter(strict, all) {
|
|
|
314
235
|
// Project scope with no build: only the kernel is reported. Hint the user to
|
|
315
236
|
// build (which records which modules actually link) or use --all.
|
|
316
237
|
if (result.needsBuild) {
|
|
317
|
-
ui.printInfo('(no build found — only the Zephyr kernel is shown. Run `
|
|
318
|
-
'this report to the modules your firmware actually links, or use `
|
|
238
|
+
ui.printInfo('(no build found — only the Zephyr kernel is shown. Run `typecad-hal build` to scope ' +
|
|
239
|
+
'this report to the modules your firmware actually links, or use `typecad-hal licenses --all` ' +
|
|
319
240
|
'for every west module.)');
|
|
320
241
|
}
|
|
321
242
|
const counts = countByRisk(result.entries);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
2
|
+
import type { ZephyrChipDescriptor } from '../chips/types.js';
|
|
3
|
+
/** Which can.* verbs the program actually uses on a controller — the
|
|
4
|
+
* init block emits only the state those verbs reference (Zephyr's -Werror
|
|
5
|
+
* turns an unreferenced static function/variable into a build failure:
|
|
6
|
+
* a send-only program must not carry the rx trampoline). */
|
|
7
|
+
export interface CanUsage {
|
|
8
|
+
begin: boolean;
|
|
9
|
+
send: boolean;
|
|
10
|
+
onReceive: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Emit the per-controller CAN state: device handle, rx trampoline +
|
|
14
|
+
* handler slot, and the accept-all filters. Called from shimLines when the
|
|
15
|
+
* program uses can.* on this controller and the chip declares it.
|
|
16
|
+
*/
|
|
17
|
+
export declare function canInitLines(chip: ZephyrChipDescriptor, controllerIndex: number, usage: CanUsage): string[];
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a HAL can.* op to Zephyr C++.
|
|
20
|
+
* Returns `{ code }` for statement ops.
|
|
21
|
+
*/
|
|
22
|
+
export declare function lowerCan(op: HALOpIR, chip: ZephyrChipDescriptor): {
|
|
23
|
+
code?: string;
|
|
24
|
+
expression?: string;
|
|
25
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// CAN lowering — Zephyr's can API over the harvested controller node
|
|
3
|
+
//
|
|
4
|
+
// The controller is addressed by its DT nodelabel (chip.can, the harvested
|
|
5
|
+
// can@ node — ESP32 TWAI, STM32 bxCAN, NXP FlexCAN…). begin() applies
|
|
6
|
+
// mode + bitrate + start in the required order (mode and bitrate need a
|
|
7
|
+
// stopped controller); send() builds one can_frame and submits it with a
|
|
8
|
+
// bounded timeout and no tx callback (blocking-send form); onReceive()
|
|
9
|
+
// installs the accept-all filter whose trampoline carries the frame as
|
|
10
|
+
// ten scalars — the Matrix discipline (ISR context, set-a-variable work).
|
|
11
|
+
// ----------------------------------------------------------------------------
|
|
12
|
+
/** The C variable names for a CAN controller's state. */
|
|
13
|
+
function prefix(idx) {
|
|
14
|
+
return `__tc_can${idx}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Emit the per-controller CAN state: device handle, rx trampoline +
|
|
18
|
+
* handler slot, and the accept-all filters. Called from shimLines when the
|
|
19
|
+
* program uses can.* on this controller and the chip declares it.
|
|
20
|
+
*/
|
|
21
|
+
export function canInitLines(chip, controllerIndex, usage) {
|
|
22
|
+
const ctrl = chip.can?.controllers[controllerIndex];
|
|
23
|
+
if (!ctrl)
|
|
24
|
+
return [];
|
|
25
|
+
const p = prefix(controllerIndex);
|
|
26
|
+
const lines = [
|
|
27
|
+
'// CUTTLEFISH_CAN_BEGIN',
|
|
28
|
+
`static const struct device* ${p}_dev = DEVICE_DT_GET(DT_NODELABEL(${ctrl.nodeLabel}));`,
|
|
29
|
+
];
|
|
30
|
+
if (usage.begin) {
|
|
31
|
+
// Shim-scoped (not per call site): a second begin() anywhere in the
|
|
32
|
+
// program must not re-fire can_start on a started controller.
|
|
33
|
+
lines.push(`static bool ${p}_started = false;`);
|
|
34
|
+
}
|
|
35
|
+
if (usage.onReceive) {
|
|
36
|
+
lines.push(`static void (*${p}_rx)(double, double, double, double, double, double, double, double, double, double) = NULL;`,
|
|
37
|
+
// dlc-bounded: drivers fill only data[0..dlc-1] — copy into a zeroed
|
|
38
|
+
// local so the handler's b0..b7 tail is zero, as the class documents.
|
|
39
|
+
'static void __tc_can_rx_trampoline(const struct device* dev, struct can_frame* frame, void* user_data) {', ' (void)dev;', ' (void)user_data;', ` if (${p}_rx != NULL) {`, ' uint8_t __tc_d[8] = { 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U };', ' for (uint32_t __tc_i = 0U; (__tc_i < 8U) && (__tc_i < static_cast<uint32_t>(frame->dlc)); ++__tc_i) { __tc_d[__tc_i] = frame->data[__tc_i]; }', ` ${p}_rx(static_cast<double>(frame->id), static_cast<double>(frame->dlc),`, ` static_cast<double>(__tc_d[0]), static_cast<double>(__tc_d[1]),`, ` static_cast<double>(__tc_d[2]), static_cast<double>(__tc_d[3]),`, ` static_cast<double>(__tc_d[4]), static_cast<double>(__tc_d[5]),`, ` static_cast<double>(__tc_d[6]), static_cast<double>(__tc_d[7]));`, ' }', '}',
|
|
40
|
+
// Two accept-all filters: can_filter_matches_filter never delivers an
|
|
41
|
+
// IDE (29-bit) frame to a filter without CAN_FILTER_IDE — one filter
|
|
42
|
+
// per frame format, so extended sends are receivable too.
|
|
43
|
+
`static const struct can_filter ${p}_filter = { .id = 0U, .mask = 0U, .flags = 0U };`, `static const struct can_filter ${p}_filter_ext = { .id = 0U, .mask = 0U, .flags = CAN_FILTER_IDE };`, `static bool ${p}_filter_added = false;`);
|
|
44
|
+
}
|
|
45
|
+
if (usage.send) {
|
|
46
|
+
lines.push(`static void __tc_can_tx_done(const struct device* dev, int error, void* user_data) {`, ' (void)dev; (void)error; (void)user_data;', '}');
|
|
47
|
+
}
|
|
48
|
+
lines.push('// CUTTLEFISH_CAN_END');
|
|
49
|
+
return lines;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolve a HAL can.* op to Zephyr C++.
|
|
53
|
+
* Returns `{ code }` for statement ops.
|
|
54
|
+
*/
|
|
55
|
+
export function lowerCan(op, chip) {
|
|
56
|
+
const o = op;
|
|
57
|
+
// DAC discipline: a board with no harvested can@ node lowers to a comment
|
|
58
|
+
// naming the constraint (the board gate already refuses the CAN import;
|
|
59
|
+
// this keeps the manifest probe and direct-lowering paths honest).
|
|
60
|
+
if (!chip.can || chip.can.controllers.length === 0) {
|
|
61
|
+
return { code: `/* ${op.operation}: this board's chip data declares no CAN controller (no harvested can@ node) */` };
|
|
62
|
+
}
|
|
63
|
+
const idx = Math.min(Number(o.instance ?? 0), chip.can.controllers.length - 1);
|
|
64
|
+
const p = prefix(idx);
|
|
65
|
+
const started = `${p}_started`;
|
|
66
|
+
switch (op.operation) {
|
|
67
|
+
case 'can.begin': {
|
|
68
|
+
// Mode and bitrate require a STOPPED controller — apply them before
|
|
69
|
+
// the start, and start exactly once. Failures printk (the loud-
|
|
70
|
+
// diagnostics policy): a CAN bus that never comes up is otherwise a
|
|
71
|
+
// silent hang at the first send.
|
|
72
|
+
return {
|
|
73
|
+
code: `{ int __tc_err; if (${o.loopback}) { __tc_err = can_set_mode(${p}_dev, CAN_MODE_LOOPBACK); if (__tc_err != 0) { printk("typecad-hal can: set_mode failed: %d\\n", __tc_err); } } __tc_err = can_set_bitrate(${p}_dev, ${o.hz}); if (__tc_err != 0) { printk("typecad-hal can: bitrate failed: %d\\n", __tc_err); } if (!${started}) { ${started} = true; __tc_err = can_start(${p}_dev); if (__tc_err != 0) { printk("typecad-hal can: start failed: %d\\n", __tc_err); } } }`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
case 'can.send': {
|
|
77
|
+
const bytes = (o.data ?? []);
|
|
78
|
+
if (bytes.length > 8) {
|
|
79
|
+
throw new Error(`CAN send: classic frames carry at most 8 bytes — got ${bytes.length}.`);
|
|
80
|
+
}
|
|
81
|
+
const assigns = bytes
|
|
82
|
+
.map((b, i) => `__tc_frame.data[${i}] = static_cast<uint8_t>(${b});`)
|
|
83
|
+
.join(' ');
|
|
84
|
+
return {
|
|
85
|
+
code: `{ struct can_frame __tc_frame = { 0 }; __tc_frame.id = static_cast<uint32_t>(${o.id}); __tc_frame.dlc = ${bytes.length}U; __tc_frame.flags = ${o.extended ? 'CAN_FRAME_IDE' : '0U'}; ${assigns} int __tc_err = can_send(${p}_dev, &__tc_frame, K_MSEC(100), __tc_can_tx_done, NULL); if (__tc_err != 0) { printk("typecad-hal can: send failed: %d\\n", __tc_err); } }`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
case 'can.on_receive': {
|
|
89
|
+
return {
|
|
90
|
+
code: `{ ${p}_rx = ${o.handler}; if (!${p}_filter_added) { ${p}_filter_added = true; (void)can_add_rx_filter(${p}_dev, __tc_can_rx_trampoline, NULL, &${p}_filter); (void)can_add_rx_filter(${p}_dev, __tc_can_rx_trampoline, NULL, &${p}_filter_ext); } }`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
default:
|
|
94
|
+
throw new Error(`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
95
|
+
`Open an issue or use rawCpp() to emit it manually.`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
2
|
+
/** The conversion helpers + device handle. Called from shimLines when the
|
|
3
|
+
* program uses clock.* — each helper only when its consuming op appears
|
|
4
|
+
* (a now()-only program must not carry the unused set() helper: -Werror
|
|
5
|
+
* fails the build on unreferenced static functions). */
|
|
6
|
+
export declare function clockInitLines(usage: {
|
|
7
|
+
set: boolean;
|
|
8
|
+
now: boolean;
|
|
9
|
+
}): string[];
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a HAL clock.* op to Zephyr C++.
|
|
12
|
+
* Returns `{ code }` for set, `{ expression }` for now.
|
|
13
|
+
*/
|
|
14
|
+
export declare function lowerClock(op: HALOpIR): {
|
|
15
|
+
code?: string;
|
|
16
|
+
expression?: string;
|
|
17
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Clock lowering — rtc_set_time / rtc_get_time on the `rtc` DT alias
|
|
3
|
+
//
|
|
4
|
+
// The alias is Zephyr's own discovery convention. Boards with a hardware
|
|
5
|
+
// calendar RTC alias it themselves; the overlay generator synthesizes a
|
|
6
|
+
// zephyr,rtc-counter shim (a child of the board's first free counter — the
|
|
7
|
+
// counter driver keeps the parent, so Counter and Clock coexist) when they
|
|
8
|
+
// do not.
|
|
9
|
+
//
|
|
10
|
+
// Epoch ↔ civil conversion is Howard Hinnant's days_from_civil pair —
|
|
11
|
+
// pure int64 arithmetic, no libc timezone machinery, valid over the whole
|
|
12
|
+
// Unix range. The helpers live in the shim block so both ops share them.
|
|
13
|
+
// ----------------------------------------------------------------------------
|
|
14
|
+
const RTC_DEV = 'DEVICE_DT_GET(DT_ALIAS(rtc))';
|
|
15
|
+
/** The conversion helpers + device handle. Called from shimLines when the
|
|
16
|
+
* program uses clock.* — each helper only when its consuming op appears
|
|
17
|
+
* (a now()-only program must not carry the unused set() helper: -Werror
|
|
18
|
+
* fails the build on unreferenced static functions). */
|
|
19
|
+
export function clockInitLines(usage) {
|
|
20
|
+
const lines = [
|
|
21
|
+
'// CUTTLEFISH_CLOCK_BEGIN',
|
|
22
|
+
`static const struct device* __tc_rtc = ${RTC_DEV};`,
|
|
23
|
+
];
|
|
24
|
+
if (usage.now) {
|
|
25
|
+
lines.push('static int64_t __tc_days_from_civil(int32_t yy, int32_t mm, int32_t dd) {', ' yy -= (mm <= 2) ? 1 : 0;', ' const int32_t era = (yy >= 0 ? yy : yy - 399) / 400;', ' const int32_t yoe = yy - era * 400;', ' const int32_t doy = (153 * (mm + (mm > 2 ? -3 : 9)) + 2) / 5 + dd - 1;', ' const int32_t doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;', ' return (static_cast<int64_t>(era) * 146097) + static_cast<int64_t>(doe) - 719468;', '}');
|
|
26
|
+
}
|
|
27
|
+
if (usage.set) {
|
|
28
|
+
lines.push('static void __tc_civil_from_days(int64_t z, int32_t* yy, int32_t* mm, int32_t* dd) {', ' z += 719468;', ' const int64_t era = (z >= 0 ? z : z - 146096) / 146097;', ' const int64_t doe = z - (era * 146097);', ' const int64_t yoe = (doe - (doe / 1460) + (doe / 36524) - (doe / 146096)) / 365;', ' const int64_t y = yoe + (era * 400);', ' const int64_t doy = doe - ((365 * yoe) + (yoe / 4) - (yoe / 100));', ' const int64_t mp = ((5 * doy) + 2) / 153;', ' const int64_t d = doy - (((153 * mp) + 2) / 5) + 1;', ' const int64_t m = mp + (mp < 10 ? 3 : -9);', ' *yy = static_cast<int32_t>(y + (m <= 2 ? 1 : 0));', ' *mm = static_cast<int32_t>(m);', ' *dd = static_cast<int32_t>(d);', '}');
|
|
29
|
+
}
|
|
30
|
+
lines.push('// CUTTLEFISH_CLOCK_END');
|
|
31
|
+
return lines;
|
|
32
|
+
}
|
|
33
|
+
/** The all-zero/unknown rtc_time initializer (wday/yday unknown per the
|
|
34
|
+
* struct's contract). */
|
|
35
|
+
const TM_INIT = 'struct rtc_time __tc_tm = { 0, 0, 0, 0, 0, 0, -1, -1, -1, 0 }';
|
|
36
|
+
/**
|
|
37
|
+
* Resolve a HAL clock.* op to Zephyr C++.
|
|
38
|
+
* Returns `{ code }` for set, `{ expression }` for now.
|
|
39
|
+
*/
|
|
40
|
+
export function lowerClock(op) {
|
|
41
|
+
const o = op;
|
|
42
|
+
switch (op.operation) {
|
|
43
|
+
case 'clock.set': {
|
|
44
|
+
// epoch (runtime text) → civil date → rtc_set_time.
|
|
45
|
+
return {
|
|
46
|
+
code: `{ int64_t __tc_ep = static_cast<int64_t>(${o.epoch}); int32_t __tc_y = 0; int32_t __tc_mo = 0; int32_t __tc_d = 0; __tc_civil_from_days(__tc_ep / 86400, &__tc_y, &__tc_mo, &__tc_d); int64_t __tc_sod = __tc_ep % 86400; ${TM_INIT}; __tc_tm.tm_year = __tc_y - 1900; __tc_tm.tm_mon = __tc_mo - 1; __tc_tm.tm_mday = __tc_d; __tc_tm.tm_hour = static_cast<int32_t>(__tc_sod / 3600); __tc_tm.tm_min = static_cast<int32_t>((__tc_sod % 3600) / 60); __tc_tm.tm_sec = static_cast<int32_t>(__tc_sod % 60); (void)rtc_set_time(__tc_rtc, &__tc_tm); }`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
case 'clock.now': {
|
|
50
|
+
return {
|
|
51
|
+
expression: `({ ${TM_INIT}; double __tc_epoch = 0.0; if (rtc_get_time(__tc_rtc, &__tc_tm) == 0) { int64_t __tc_days = __tc_days_from_civil(__tc_tm.tm_year + 1900, __tc_tm.tm_mon + 1, __tc_tm.tm_mday); __tc_epoch = static_cast<double>((__tc_days * 86400) + (static_cast<int64_t>(__tc_tm.tm_hour) * 3600) + (static_cast<int64_t>(__tc_tm.tm_min) * 60) + static_cast<int64_t>(__tc_tm.tm_sec)); } __tc_epoch; })`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
default:
|
|
55
|
+
throw new Error(`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
56
|
+
`Open an issue or use rawCpp() to emit it manually.`);
|
|
57
|
+
}
|
|
58
|
+
}
|