@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/index.ts
CHANGED
|
@@ -1,93 +1,91 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// HAL lowering dispatcher
|
|
3
|
-
//
|
|
4
|
-
// Routes a HALOpIR to the per-category lowering module by category prefix
|
|
5
|
-
// (e.g. 'gpio.write' → lowerGpio). Returns undefined for categories the
|
|
6
|
-
// framework does not lower (display/mdns/ota/rmt/
|
|
7
|
-
// capacitive/temp/espnow/crypto/i2s/twai/usb/eth/pcnt/mcpwm — see
|
|
8
|
-
// the manifest), so the transpiler falls back and the manifest validator
|
|
9
|
-
// cross-checks the unsupported categories. (board.* is registered below but is
|
|
10
|
-
// a dead-letter — its values are constant-folded at IR-build time.)
|
|
11
|
-
//
|
|
12
|
-
// Prefix dispatch (matching framework-esp32's lowerHalOp) keeps this resilient:
|
|
13
|
-
// a new op added to a category's lowering fn is picked up here automatically,
|
|
14
|
-
// without also editing a 40-case switch. The per-fn default arm still throws a
|
|
15
|
-
// clear "unsupported op" error for ops that fall within a category prefix but
|
|
16
|
-
// aren't handled, so coverage stays honest.
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
|
|
19
|
-
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
20
|
-
import { getActiveChip } from '../chips/index.js';
|
|
21
|
-
import { lowerGpio } from './gpio.js';
|
|
22
|
-
import { lowerTiming } from './timing.js';
|
|
23
|
-
import { lowerAdc } from './adc.js';
|
|
24
|
-
import { lowerPwm } from './pwm.js';
|
|
25
|
-
import { lowerI2c } from './i2c.js';
|
|
26
|
-
import { lowerSpi } from './spi.js';
|
|
27
|
-
import { lowerUart } from './uart.js';
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
*
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (op.operation.startsWith('
|
|
62
|
-
if (op.operation.startsWith('
|
|
63
|
-
if (op.operation.startsWith('
|
|
64
|
-
if (op.operation.startsWith('
|
|
65
|
-
if (op.operation.startsWith('
|
|
66
|
-
if (op.operation.startsWith('
|
|
67
|
-
if (op.operation.startsWith('
|
|
68
|
-
if (op.operation.startsWith('
|
|
69
|
-
if (op.operation.startsWith('interrupt.')) return lowerInterrupt(op, chip);
|
|
70
|
-
if (op.operation.startsWith('wdt.')) return lowerWdt(op);
|
|
71
|
-
if (op.operation.startsWith('hwtimer.')) return lowerHwtimer(op, chip);
|
|
72
|
-
if (op.operation.startsWith('
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (op.operation.startsWith('
|
|
76
|
-
|
|
77
|
-
if (op.operation.startsWith('
|
|
78
|
-
if (op.operation.startsWith('
|
|
79
|
-
if (op.operation.startsWith('
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (op.operation.startsWith('
|
|
83
|
-
if (op.operation.startsWith('
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return undefined;
|
|
93
|
-
}
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// HAL lowering dispatcher
|
|
3
|
+
//
|
|
4
|
+
// Routes a HALOpIR to the per-category lowering module by category prefix
|
|
5
|
+
// (e.g. 'gpio.write' → lowerGpio). Returns undefined for categories the
|
|
6
|
+
// framework does not lower (display/mdns/ota/rmt/
|
|
7
|
+
// capacitive/temp/espnow/crypto/i2s/twai/usb/eth/pcnt/mcpwm — see
|
|
8
|
+
// the manifest), so the transpiler falls back and the manifest validator
|
|
9
|
+
// cross-checks the unsupported categories. (board.* is registered below but is
|
|
10
|
+
// a dead-letter — its values are constant-folded at IR-build time.)
|
|
11
|
+
//
|
|
12
|
+
// Prefix dispatch (matching framework-esp32's lowerHalOp) keeps this resilient:
|
|
13
|
+
// a new op added to a category's lowering fn is picked up here automatically,
|
|
14
|
+
// without also editing a 40-case switch. The per-fn default arm still throws a
|
|
15
|
+
// clear "unsupported op" error for ops that fall within a category prefix but
|
|
16
|
+
// aren't handled, so coverage stays honest.
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
20
|
+
import { getActiveChip } from '../chips/index.js';
|
|
21
|
+
import { lowerGpio } from './gpio.js';
|
|
22
|
+
import { lowerTiming } from './timing.js';
|
|
23
|
+
import { lowerAdc } from './adc.js';
|
|
24
|
+
import { lowerPwm } from './pwm.js';
|
|
25
|
+
import { lowerI2c } from './i2c.js';
|
|
26
|
+
import { lowerSpi } from './spi.js';
|
|
27
|
+
import { lowerUart } from './uart.js';
|
|
28
|
+
import { lowerUsb } from './usb.js';
|
|
29
|
+
import { lowerInterrupt } from './interrupts.js';
|
|
30
|
+
import { lowerWdt } from './wdt.js';
|
|
31
|
+
import { lowerBle } from './ble.js';
|
|
32
|
+
import { lowerWifi } from './wifi.js';
|
|
33
|
+
import { lowerHttp } from './http.js';
|
|
34
|
+
import { lowerMqtt } from './mqtt.js';
|
|
35
|
+
import { lowerPreferences } from './preferences.js';
|
|
36
|
+
import { lowerBoard } from './board.js';
|
|
37
|
+
import { lowerRandom } from './random.js';
|
|
38
|
+
import { lowerDac } from './dac.js';
|
|
39
|
+
import { lowerFs } from './fs.js';
|
|
40
|
+
import { lowerSensor } from './sensor.js';
|
|
41
|
+
import { lowerHwtimer, lowerCounter } from './hwtimer.js';
|
|
42
|
+
import { lowerThread } from './thread.js';
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
lowerGpio, lowerTiming, lowerAdc, lowerPwm, lowerI2c, lowerSpi, lowerUart,
|
|
46
|
+
lowerUsb, lowerInterrupt, lowerWdt, lowerBle,
|
|
47
|
+
lowerWifi, lowerHttp, lowerMqtt, lowerPreferences, lowerBoard, lowerRandom,
|
|
48
|
+
lowerDac, lowerFs, lowerHwtimer, lowerCounter, lowerSensor, lowerThread,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Lower a HAL op to Zephyr C++. Returns undefined for unsupported categories
|
|
53
|
+
* (mirrors lowerHalOp in framework-esp32/src/lowering/index.ts).
|
|
54
|
+
*/
|
|
55
|
+
export function lowerHalOp(
|
|
56
|
+
op: HALOpIR,
|
|
57
|
+
): { code?: string; expression?: string } | undefined {
|
|
58
|
+
const chip = getActiveChip();
|
|
59
|
+
|
|
60
|
+
if (op.operation.startsWith('gpio.')) return lowerGpio(op, chip);
|
|
61
|
+
if (op.operation.startsWith('timing.')) return lowerTiming(op);
|
|
62
|
+
if (op.operation.startsWith('adc.')) return lowerAdc(op, chip);
|
|
63
|
+
if (op.operation.startsWith('pwm.')) return lowerPwm(op, chip);
|
|
64
|
+
if (op.operation.startsWith('dac.')) return lowerDac(op, chip);
|
|
65
|
+
if (op.operation.startsWith('i2c.')) return lowerI2c(op, chip);
|
|
66
|
+
if (op.operation.startsWith('spi.')) return lowerSpi(op, chip);
|
|
67
|
+
if (op.operation.startsWith('uart.')) return lowerUart(op);
|
|
68
|
+
if (op.operation.startsWith('usb.')) return lowerUsb(op, chip);
|
|
69
|
+
if (op.operation.startsWith('interrupt.')) return lowerInterrupt(op, chip);
|
|
70
|
+
if (op.operation.startsWith('wdt.')) return lowerWdt(op, chip);
|
|
71
|
+
if (op.operation.startsWith('hwtimer.')) return lowerHwtimer(op, chip);
|
|
72
|
+
if (op.operation.startsWith('counter.')) return lowerCounter(op, chip);
|
|
73
|
+
// (legacy pulse/shift bit-bang module removed)
|
|
74
|
+
if (op.operation.startsWith('ble.')) return lowerBle(op);
|
|
75
|
+
if (op.operation.startsWith('wifi.')) return lowerWifi(op);
|
|
76
|
+
if (op.operation.startsWith('http.')) return lowerHttp(op);
|
|
77
|
+
if (op.operation.startsWith('mqtt.')) return lowerMqtt(op);
|
|
78
|
+
if (op.operation.startsWith('preferences.')) return lowerPreferences(op);
|
|
79
|
+
if (op.operation.startsWith('fs.')) return lowerFs(op);
|
|
80
|
+
// board.resolve is constant-folded at IR-build time; lowerBoard is the
|
|
81
|
+
// dead-letter reached only on an unresolvable path.
|
|
82
|
+
if (op.operation.startsWith('board.')) return lowerBoard(op);
|
|
83
|
+
if (op.operation.startsWith('random.')) return lowerRandom(op);
|
|
84
|
+
if (op.operation.startsWith('sensor.')) return lowerSensor(op);
|
|
85
|
+
if (op.operation.startsWith('thread.')) return lowerThread(op);
|
|
86
|
+
|
|
87
|
+
// raw / snprintf.emit / display.* / ... — not lowered by this
|
|
88
|
+
// framework. Return undefined so the transpiler falls back and the manifest
|
|
89
|
+
// validator confirms the unsupported declaration.
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// `struct gpio_callback` per pin, registered with gpio_add_callback, with a
|
|
6
6
|
// trampoline that calls the user's C handler. The descriptor's gpio.interruptPins
|
|
7
7
|
// lists the pins with DT specs (buttons). The user's handler is a free C
|
|
8
|
-
// function; the trampoline calls it with no args
|
|
8
|
+
// function; the trampoline calls it with no args.
|
|
9
9
|
//
|
|
10
10
|
// Each interrupt pin gets a static callback struct + a trampoline in shimLines.
|
|
11
11
|
// attach enables + adds the callback; detach disables + removes it.
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
15
15
|
import type { ZephyrChipDescriptor, ZephyrInterruptPin } from '../chips/types.js';
|
|
16
|
+
import { controllerNodelabelForPin, controllerRawPinForPin, controllerRangeForPin } from '../chips/controllers.js';
|
|
17
|
+
import { ZEPHYR_GPIO_INTS } from '@typecad/hal';
|
|
16
18
|
|
|
17
19
|
/** Look up an interrupt pin spec by HAL pin number. */
|
|
18
20
|
function findIntPin(chip: ZephyrChipDescriptor, pin: number): ZephyrInterruptPin | undefined {
|
|
@@ -24,26 +26,42 @@ function dtSpecVar(dtSpec: string): string {
|
|
|
24
26
|
return `__tc_int_${dtSpec.replace(/-/g, '_')}`;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
// ── Thin GPIO interrupts (hal/gpio-pin.ts onInterrupt) — INT_* tokens ─────
|
|
30
|
+
//
|
|
31
|
+
// The name set comes from the GENERATED Zephyr token table (parsed from the
|
|
32
|
+
// pinned tree's drivers/gpio.h).
|
|
33
|
+
|
|
34
|
+
const GPIO_INT_TOKENS: Record<string, string> = Object.fromEntries(
|
|
35
|
+
ZEPHYR_GPIO_INTS.map((f) => [`GPIO.${f}`, `GPIO_${f}`]),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
/** Map thin-GPIO INT token text to the GPIO_INT_* macro. */
|
|
39
|
+
export function gpioIntTokenToMacro(intFlags: string): string {
|
|
40
|
+
const token = String(intFlags ?? '').trim();
|
|
41
|
+
const m = GPIO_INT_TOKENS[token];
|
|
42
|
+
if (!m) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`GPIO interrupt flag '${token}' is not a known GPIO.INT_* token — valid: ${Object.keys(GPIO_INT_TOKENS).join(', ')}.`,
|
|
45
|
+
);
|
|
36
46
|
}
|
|
47
|
+
return m;
|
|
37
48
|
}
|
|
38
49
|
|
|
39
50
|
/**
|
|
40
51
|
* Emit the per-pin interrupt callback state + trampolines. Called from shimLines
|
|
41
52
|
* when the program uses interrupts. The trampoline calls a user function via a
|
|
42
53
|
* function-pointer static, set at attach time.
|
|
54
|
+
*
|
|
55
|
+
* Two paths:
|
|
56
|
+
* - descriptor `gpio.interruptPins` (buttons with DT specs): callback state
|
|
57
|
+
* against the DT spec, polarity-correct via gpio_*_dt.
|
|
58
|
+
* - `usedPins` (any other pin the program attaches to): raw-controller state —
|
|
59
|
+
* GPIO.onInterrupt() works on EVERY GPIO, not just DT-aliased buttons. Each
|
|
60
|
+
* such pin gets its own callback struct + trampoline addressed by the owning
|
|
61
|
+
* controller (STM32 splits gpioa/gpiob/gpioc) and port-relative bit.
|
|
43
62
|
*/
|
|
44
|
-
export function interruptInitLines(chip: ZephyrChipDescriptor): string[] {
|
|
63
|
+
export function interruptInitLines(chip: ZephyrChipDescriptor, usedPins?: ReadonlySet<number>): string[] {
|
|
45
64
|
const pins = chip.gpio.interruptPins ?? [];
|
|
46
|
-
if (pins.length === 0) return [];
|
|
47
65
|
const lines: string[] = ['// CUTTLEFISH_INT_BEGIN'];
|
|
48
66
|
for (const pin of pins) {
|
|
49
67
|
const v = dtSpecVar(pin.dtSpec);
|
|
@@ -57,18 +75,60 @@ export function interruptInitLines(chip: ZephyrChipDescriptor): string[] {
|
|
|
57
75
|
`}`,
|
|
58
76
|
);
|
|
59
77
|
}
|
|
78
|
+
if (usedPins) {
|
|
79
|
+
for (const pin of usedPins) {
|
|
80
|
+
if (pins.some((p) => p.pin === pin)) continue;
|
|
81
|
+
const v = `__tc_int_raw${pin}`;
|
|
82
|
+
lines.push(
|
|
83
|
+
`static const struct device* ${v}_dev = DEVICE_DT_GET(DT_NODELABEL(${controllerNodelabelForPin(chip, pin)}));`,
|
|
84
|
+
`static struct gpio_callback ${v}_cb;`,
|
|
85
|
+
`static void (*${v}_handler)(void) = NULL;`,
|
|
86
|
+
`static void ${v}_tramp(const struct device* port, struct gpio_callback* cb, gpio_port_pins_t pins_v) {`,
|
|
87
|
+
` (void)port; (void)cb; (void)pins_v;`,
|
|
88
|
+
` if (${v}_handler) { ${v}_handler(); }`,
|
|
89
|
+
`}`,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
60
93
|
lines.push('// CUTTLEFISH_INT_END');
|
|
61
94
|
return lines;
|
|
62
95
|
}
|
|
63
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Collect the pin numbers the program attaches interrupts to (any GPIO — not
|
|
99
|
+
* just descriptor-listed buttons). Feeds interruptInitLines' raw-path state.
|
|
100
|
+
*/
|
|
101
|
+
export function collectInterruptPins(program: unknown): Set<number> {
|
|
102
|
+
const pins = new Set<number>();
|
|
103
|
+
const visit = (node: unknown): void => {
|
|
104
|
+
if (!node || typeof node !== 'object') return;
|
|
105
|
+
const n = node as Record<string, unknown>;
|
|
106
|
+
const op = n.operation;
|
|
107
|
+
if (op && typeof op === 'object') {
|
|
108
|
+
const o = op as Record<string, unknown>;
|
|
109
|
+
if (o.operation === 'interrupt.attach_flags' && typeof o.pin === 'number') {
|
|
110
|
+
pins.add(o.pin as number);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
for (const v of Object.values(n)) {
|
|
114
|
+
if (Array.isArray(v)) { for (const item of v) visit(item); }
|
|
115
|
+
else if (v && typeof v === 'object') visit(v);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
visit(program);
|
|
119
|
+
return pins;
|
|
120
|
+
}
|
|
121
|
+
|
|
64
122
|
/**
|
|
65
123
|
* Resolve a HAL interrupt.* op to Zephyr C++.
|
|
66
124
|
* Returns `{ code }` for statement ops, `{ expression }` for value-returning ops.
|
|
67
125
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* the
|
|
126
|
+
* Two paths: pins listed in the descriptor's gpio.interruptPins (DT-aliased
|
|
127
|
+
* buttons) go through the polarity-correct gpio_*_dt chain; every other GPIO
|
|
128
|
+
* attaches through the raw-controller chain (any GPIO is interrupt-capable on
|
|
129
|
+
* the supported SoCs — the descriptor list exists for DT specs, not as a
|
|
130
|
+
* capability gate). The manifest probe's synthetic op keeps the comment
|
|
131
|
+
* fallback (no program ⇒ no shim state was emitted for the raw path).
|
|
72
132
|
*/
|
|
73
133
|
export function lowerInterrupt(
|
|
74
134
|
op: HALOpIR,
|
|
@@ -78,10 +138,42 @@ export function lowerInterrupt(
|
|
|
78
138
|
const pin = findIntPin(chip, o.pin);
|
|
79
139
|
|
|
80
140
|
if (!pin) {
|
|
141
|
+
// Raw-controller path — state comes from interruptInitLines' usedPins.
|
|
142
|
+
// Only for pins a declared controller range covers: an out-of-range number
|
|
143
|
+
// (e.g. pin 99 on a 34-pin SoC) keeps the diagnostic comment. Single-
|
|
144
|
+
// controller chips declare no ranges, so every number is taken as real and
|
|
145
|
+
// the driver rejects invalid bits at runtime (Arduino-like behavior).
|
|
146
|
+
const knownPin = typeof o.pin === 'number' && Number.isInteger(o.pin)
|
|
147
|
+
&& (!chip.gpioControllers || chip.gpioControllers.length === 0
|
|
148
|
+
|| controllerRangeForPin(chip, o.pin) !== undefined);
|
|
149
|
+
if (knownPin) {
|
|
150
|
+
const v = `__tc_int_raw${o.pin}`;
|
|
151
|
+
const raw = controllerRawPinForPin(chip, o.pin);
|
|
152
|
+
if (op.operation === 'interrupt.attach_flags') {
|
|
153
|
+
// Thin GPIO: INT_* tokens instead of mode strings. The pin's
|
|
154
|
+
// input/pull configuration already came from the construction flags
|
|
155
|
+
// (the class emits gpio.configure ahead of this op) — no INPUT
|
|
156
|
+
// override here, unlike the legacy raw path above.
|
|
157
|
+
const flags = gpioIntTokenToMacro(o.intFlags);
|
|
158
|
+
return {
|
|
159
|
+
code: [
|
|
160
|
+
`${v}_handler = (${o.handler});`,
|
|
161
|
+
`gpio_init_callback(&${v}_cb, ${v}_tramp, BIT(${raw}));`,
|
|
162
|
+
`gpio_pin_interrupt_configure(${v}_dev, ${raw}, ${flags});`,
|
|
163
|
+
`gpio_add_callback(${v}_dev, &${v}_cb);`,
|
|
164
|
+
].join(' '),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (op.operation === 'interrupt.detach') {
|
|
168
|
+
return {
|
|
169
|
+
code: `gpio_pin_interrupt_configure(${v}_dev, ${raw}, GPIO_INT_DISABLE); gpio_remove_callback(${v}_dev, &${v}_cb); ${v}_handler = NULL;`,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
81
173
|
// Fallback (also covers the manifest probe): a diagnostic comment so the
|
|
82
174
|
// resolver returns non-undefined. Real attach needs a descriptor entry.
|
|
83
|
-
if (op.operation === 'interrupt.
|
|
84
|
-
return { code: `/* interrupt.
|
|
175
|
+
if (op.operation === 'interrupt.attach_flags') {
|
|
176
|
+
return { code: `/* interrupt.attach_flags(pin ${o.pin}): no DT spec — add to chip descriptor gpio.interruptPins */` };
|
|
85
177
|
}
|
|
86
178
|
return { code: `/* interrupt.detach(pin ${o.pin}): no DT spec */` };
|
|
87
179
|
}
|
|
@@ -89,12 +181,12 @@ export function lowerInterrupt(
|
|
|
89
181
|
const v = dtSpecVar(pin.dtSpec);
|
|
90
182
|
|
|
91
183
|
switch (op.operation) {
|
|
92
|
-
case 'interrupt.
|
|
93
|
-
|
|
184
|
+
case 'interrupt.attach_flags': {
|
|
185
|
+
// Thin GPIO: INT_* tokens; construction flags already configured the pin.
|
|
186
|
+
const flags = gpioIntTokenToMacro(o.intFlags);
|
|
94
187
|
return {
|
|
95
188
|
code: [
|
|
96
189
|
`${v}_handler = (${o.handler});`,
|
|
97
|
-
`gpio_pin_configure_dt(&${v}, GPIO_INPUT);`,
|
|
98
190
|
`gpio_init_callback(&${v}_cb, ${v}_tramp, BIT(${v}.pin));`,
|
|
99
191
|
`gpio_pin_interrupt_configure_dt(&${v}, ${flags});`,
|
|
100
192
|
`gpio_add_callback(${v}.port, &${v}_cb);`,
|
package/src/lowering/mqtt.ts
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
//
|
|
4
4
|
// Zephyr's MQTT library is event-driven but has no internal task: the app
|
|
5
5
|
// must call mqtt_input() when the socket is readable and mqtt_live()
|
|
6
|
-
// periodically for keepalive. The generated firmware is
|
|
7
|
-
//
|
|
6
|
+
// periodically for keepalive. The generated firmware is main()-based and
|
|
7
|
+
// the user's main() is not ours to edit — so the connect shim spawns a
|
|
8
8
|
// dedicated k_thread that runs the poll loop (poll() → mqtt_input/mqtt_live)
|
|
9
9
|
// until disconnect. This mirrors a "managed client" model (like ESP-IDF's
|
|
10
|
-
// esp_mqtt internal task) and keeps the user's
|
|
10
|
+
// esp_mqtt internal task) and keeps the user's main() untouched.
|
|
11
11
|
//
|
|
12
12
|
// mqtt_connect() does no DNS — the broker is a resolved sockaddr — so the
|
|
13
13
|
// shim getaddrinfo-resolves the broker host itself (like the HTTP shim).
|
|
@@ -270,8 +270,6 @@ export function mqttInitLines(): string[] {
|
|
|
270
270
|
` (void)mqtt_abort(&__tc_mqtt.client);`,
|
|
271
271
|
` return;`,
|
|
272
272
|
` }`,
|
|
273
|
-
` printk("tc-mqtt: connecting to %s:%u\\n", __tc_mqtt.host,`,
|
|
274
|
-
` static_cast<unsigned int>(__tc_mqtt.port));`,
|
|
275
273
|
` // Drive input locally until CONNACK arrives (poll thread hasn't started).`,
|
|
276
274
|
` // mqtt_connect opened the socket; poll it for the connect-ack. Cap the wait`,
|
|
277
275
|
` // so a silent broker doesn't hang setup forever.`,
|
|
@@ -294,7 +292,15 @@ export function mqttInitLines(): string[] {
|
|
|
294
292
|
` (void)k_thread_create(&__tc_mqtt.poll_thread, __tc_mqtt_stack,`,
|
|
295
293
|
` K_THREAD_STACK_SIZEOF(__tc_mqtt_stack),`,
|
|
296
294
|
` __tc_mqtt_poll_thread, nullptr, nullptr, nullptr,`,
|
|
297
|
-
` 5, 0,
|
|
295
|
+
` 5, 0, K_FOREVER);`,
|
|
296
|
+
`#ifdef CONFIG_SMP`,
|
|
297
|
+
` // On SMP targets park the poll thread on the app core so the network`,
|
|
298
|
+
` // stack never competes with the main/UI thread for core 0. k_thread_cpu_pin`,
|
|
299
|
+
` // is SMP-only; the pin happens before k_thread_start (which is why the`,
|
|
300
|
+
` // thread is created K_FOREVER). Compiles away on !SMP builds.`,
|
|
301
|
+
` (void)k_thread_cpu_pin(&__tc_mqtt.poll_thread, 1);`,
|
|
302
|
+
`#endif`,
|
|
303
|
+
` k_thread_start(&__tc_mqtt.poll_thread);`,
|
|
298
304
|
`}`,
|
|
299
305
|
``,
|
|
300
306
|
`static inline void __tc_mqtt_set_on_message(__tc_mqtt_msg_cb_t fn) {`,
|