@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
|
@@ -1,354 +1,327 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// Preferences lowering — Zephyr settings subsystem (ZMS backend)
|
|
3
|
-
//
|
|
4
|
-
// The HAL Preferences surface is the ESP32-NVS session model: begin(ns) →
|
|
5
|
-
// typed put_*/get_* → end(). Zephyr's settings subsystem has no session — it
|
|
6
|
-
// is a flat dotted key-space plus a one-time settings_load() at boot that
|
|
7
|
-
// fills an in-RAM cache via the h_set callback. We model the session on top:
|
|
8
|
-
//
|
|
9
|
-
// begin("app") → records the active subtree prefix "tc/app/"
|
|
10
|
-
// putInt("k",v) → writes the cache + settings_save_one("tc/app/k", bytes, 4)
|
|
11
|
-
// getInt("k",d) → cache lookup, returns d if absent
|
|
12
|
-
// remove("k") → settings_delete("tc/app/k") + drop cache slot
|
|
13
|
-
// clear() → settings_delete each known tc/<ns>/* key + clear cache
|
|
14
|
-
// end() → clears the prefix (NOT the cache — end() is not a wipe on
|
|
15
|
-
// ESP32 either; it only closes the NVS handle)
|
|
16
|
-
//
|
|
17
|
-
// begin/end are intentionally lightweight on Zephyr. They stay in the IR so a
|
|
18
|
-
// future backend that genuinely needs a session/namespace (NVS, a crypto-
|
|
19
|
-
// sealed store) has the hook without lowering every read through setup. On
|
|
20
|
-
// Zephyr they only carry the key prefix.
|
|
21
|
-
//
|
|
22
|
-
// The settings backend is ZMS (Zephyr Memory Storage), selected by
|
|
23
|
-
// CONFIG_SETTINGS + CONFIG_ZMS + CONFIG_SETTINGS_ZMS. The backend locates the
|
|
24
|
-
// storage partition automatically: the fixed-partition labeled
|
|
25
|
-
// `storage_partition`, or whatever /chosen `zephyr,settings-partition` points
|
|
26
|
-
// at (see dt-config/overlay.ts). No partition macro is referenced here.
|
|
27
|
-
//
|
|
28
|
-
// EMIT BOUNDARY: emitted bytes land in user firmware. Covered by the TypeCAD
|
|
29
|
-
// Runtime Exception (RUNTIME_EXCEPTION.md at the repo root).
|
|
30
|
-
// ---------------------------------------------------------------------------
|
|
31
|
-
|
|
32
|
-
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
33
|
-
|
|
34
|
-
/** Render a HAL field: pass through (already rendered by the resolver). */
|
|
35
|
-
function
|
|
36
|
-
return String(v);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
* The
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
`
|
|
78
|
-
`
|
|
79
|
-
`
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
`
|
|
84
|
-
|
|
85
|
-
`
|
|
86
|
-
`
|
|
87
|
-
`
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
`// settings_load()
|
|
91
|
-
`//
|
|
92
|
-
`//
|
|
93
|
-
`//
|
|
94
|
-
|
|
95
|
-
`
|
|
96
|
-
`
|
|
97
|
-
`
|
|
98
|
-
`
|
|
99
|
-
`
|
|
100
|
-
`
|
|
101
|
-
`
|
|
102
|
-
`
|
|
103
|
-
`
|
|
104
|
-
`
|
|
105
|
-
`
|
|
106
|
-
`
|
|
107
|
-
`
|
|
108
|
-
`
|
|
109
|
-
`
|
|
110
|
-
`
|
|
111
|
-
`
|
|
112
|
-
`
|
|
113
|
-
` return -
|
|
114
|
-
`}`,
|
|
115
|
-
`static int
|
|
116
|
-
`
|
|
117
|
-
`
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
`
|
|
127
|
-
`
|
|
128
|
-
`
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
`//
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
`
|
|
141
|
-
`
|
|
142
|
-
`
|
|
143
|
-
`
|
|
144
|
-
`
|
|
145
|
-
`
|
|
146
|
-
`
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
`//
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
`
|
|
154
|
-
`
|
|
155
|
-
`
|
|
156
|
-
`
|
|
157
|
-
`
|
|
158
|
-
`
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
`//
|
|
163
|
-
`//
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
`
|
|
167
|
-
`
|
|
168
|
-
`
|
|
169
|
-
`
|
|
170
|
-
`
|
|
171
|
-
`
|
|
172
|
-
` (
|
|
173
|
-
`
|
|
174
|
-
`
|
|
175
|
-
`
|
|
176
|
-
` (void)
|
|
177
|
-
` slot->
|
|
178
|
-
`
|
|
179
|
-
`
|
|
180
|
-
|
|
181
|
-
`
|
|
182
|
-
`
|
|
183
|
-
|
|
184
|
-
`
|
|
185
|
-
`
|
|
186
|
-
`
|
|
187
|
-
`
|
|
188
|
-
`
|
|
189
|
-
`
|
|
190
|
-
`
|
|
191
|
-
`
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
``,
|
|
197
|
-
`//
|
|
198
|
-
`//
|
|
199
|
-
`//
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
`
|
|
203
|
-
` (
|
|
204
|
-
`
|
|
205
|
-
`
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
`
|
|
215
|
-
`
|
|
216
|
-
`
|
|
217
|
-
`
|
|
218
|
-
`
|
|
219
|
-
`
|
|
220
|
-
`}`,
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
`//
|
|
224
|
-
`//
|
|
225
|
-
`// the
|
|
226
|
-
`static inline void
|
|
227
|
-
`
|
|
228
|
-
`
|
|
229
|
-
`
|
|
230
|
-
`
|
|
231
|
-
`
|
|
232
|
-
`
|
|
233
|
-
`
|
|
234
|
-
`
|
|
235
|
-
`
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
`
|
|
241
|
-
`
|
|
242
|
-
`
|
|
243
|
-
`
|
|
244
|
-
` return
|
|
245
|
-
`}`,
|
|
246
|
-
`static inline void
|
|
247
|
-
` __tc_prefs_put<
|
|
248
|
-
`}`,
|
|
249
|
-
`static inline
|
|
250
|
-
` return __tc_prefs_get<
|
|
251
|
-
`}`,
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
`static inline
|
|
257
|
-
`
|
|
258
|
-
`
|
|
259
|
-
`}
|
|
260
|
-
`
|
|
261
|
-
`
|
|
262
|
-
`
|
|
263
|
-
`
|
|
264
|
-
`
|
|
265
|
-
`
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
`
|
|
271
|
-
`
|
|
272
|
-
`
|
|
273
|
-
`
|
|
274
|
-
`
|
|
275
|
-
`
|
|
276
|
-
`
|
|
277
|
-
` (
|
|
278
|
-
`
|
|
279
|
-
`
|
|
280
|
-
`
|
|
281
|
-
`
|
|
282
|
-
`
|
|
283
|
-
`
|
|
284
|
-
`
|
|
285
|
-
`
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
case 'preferences.
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
case 'preferences.put_int':
|
|
329
|
-
return { code: `__tc_prefs_put_int(${s(o.key)}, ${s(o.value)});` };
|
|
330
|
-
case 'preferences.get_int':
|
|
331
|
-
return { expression: `__tc_prefs_get_int(${s(o.key)}, ${s(o.defaultValue)})` };
|
|
332
|
-
case 'preferences.put_uint':
|
|
333
|
-
return { code: `__tc_prefs_put_uint(${s(o.key)}, ${s(o.value)});` };
|
|
334
|
-
case 'preferences.get_uint':
|
|
335
|
-
return { expression: `__tc_prefs_get_uint(${s(o.key)}, ${s(o.defaultValue)})` };
|
|
336
|
-
case 'preferences.put_bool':
|
|
337
|
-
return { code: `__tc_prefs_put_bool(${s(o.key)}, ${o.value ? 'true' : 'false'});` };
|
|
338
|
-
case 'preferences.get_bool':
|
|
339
|
-
return { expression: `__tc_prefs_get_bool(${s(o.key)}, ${o.defaultValue ? 'true' : 'false'})` };
|
|
340
|
-
case 'preferences.put_float':
|
|
341
|
-
return { code: `__tc_prefs_put_float(${s(o.key)}, ${s(o.value)});` };
|
|
342
|
-
case 'preferences.get_float':
|
|
343
|
-
return { expression: `__tc_prefs_get_float(${s(o.key)}, ${s(o.defaultValue)})` };
|
|
344
|
-
case 'preferences.put_string':
|
|
345
|
-
return { code: `__tc_prefs_put_string(${s(o.key)}, ${s(o.value)});` };
|
|
346
|
-
case 'preferences.get_string':
|
|
347
|
-
return { expression: `__tc_prefs_get_string(${s(o.key)}, ${s(o.defaultValue)})` };
|
|
348
|
-
default:
|
|
349
|
-
throw new Error(
|
|
350
|
-
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
351
|
-
`Open an issue or use rawCpp() to emit it manually.`,
|
|
352
|
-
);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Preferences lowering — Zephyr settings subsystem (ZMS backend)
|
|
3
|
+
//
|
|
4
|
+
// The HAL Preferences surface is the ESP32-NVS session model: begin(ns) →
|
|
5
|
+
// typed put_*/get_* → end(). Zephyr's settings subsystem has no session — it
|
|
6
|
+
// is a flat dotted key-space plus a one-time settings_load() at boot that
|
|
7
|
+
// fills an in-RAM cache via the h_set callback. We model the session on top:
|
|
8
|
+
//
|
|
9
|
+
// begin("app") → records the active subtree prefix "tc/app/"
|
|
10
|
+
// putInt("k",v) → writes the cache + settings_save_one("tc/app/k", bytes, 4)
|
|
11
|
+
// getInt("k",d) → cache lookup, returns d if absent
|
|
12
|
+
// remove("k") → settings_delete("tc/app/k") + drop cache slot
|
|
13
|
+
// clear() → settings_delete each known tc/<ns>/* key + clear cache
|
|
14
|
+
// end() → clears the prefix (NOT the cache — end() is not a wipe on
|
|
15
|
+
// ESP32 either; it only closes the NVS handle)
|
|
16
|
+
//
|
|
17
|
+
// begin/end are intentionally lightweight on Zephyr. They stay in the IR so a
|
|
18
|
+
// future backend that genuinely needs a session/namespace (NVS, a crypto-
|
|
19
|
+
// sealed store) has the hook without lowering every read through setup. On
|
|
20
|
+
// Zephyr they only carry the key prefix.
|
|
21
|
+
//
|
|
22
|
+
// The settings backend is ZMS (Zephyr Memory Storage), selected by
|
|
23
|
+
// CONFIG_SETTINGS + CONFIG_ZMS + CONFIG_SETTINGS_ZMS. The backend locates the
|
|
24
|
+
// storage partition automatically: the fixed-partition labeled
|
|
25
|
+
// `storage_partition`, or whatever /chosen `zephyr,settings-partition` points
|
|
26
|
+
// at (see dt-config/overlay.ts). No partition macro is referenced here.
|
|
27
|
+
//
|
|
28
|
+
// EMIT BOUNDARY: emitted bytes land in user firmware. Covered by the TypeCAD
|
|
29
|
+
// Runtime Exception (RUNTIME_EXCEPTION.md at the repo root).
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
33
|
+
|
|
34
|
+
/** Render a HAL field: pass through (already rendered by the resolver). */
|
|
35
|
+
function unq(v: unknown): string {
|
|
36
|
+
return String(v).replace(/^"|"$/g, '');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function s(v: unknown): string {
|
|
40
|
+
return String(v);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Type tags for the cache slot payload. Scoped enum (AUTOSAR: enum class).
|
|
44
|
+
// The on-metal order matters: these are stored in the `type` byte and matched
|
|
45
|
+
// at h_set time, so do not renumber.
|
|
46
|
+
const TAG = {
|
|
47
|
+
INT: 1,
|
|
48
|
+
UINT: 2,
|
|
49
|
+
BOOL: 3,
|
|
50
|
+
FLOAT: 4,
|
|
51
|
+
STRING: 5,
|
|
52
|
+
} as const;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The preferences runtime shim. All helpers are `static`/`inline` so unused
|
|
56
|
+
* ones don't trip -Wunused-function in the single generated TU (mirrors
|
|
57
|
+
* wifi.ts / http.ts / mqtt.ts).
|
|
58
|
+
*
|
|
59
|
+
* The cache is the source of truth at runtime: settings_load() repopulates it
|
|
60
|
+
* once at boot via h_set, and every put / get / remove reads or writes it
|
|
61
|
+
* directly. settings_save_one and settings_delete keep flash in sync on
|
|
62
|
+
* writes; reads never touch flash. This is the same split the ESP32
|
|
63
|
+
* Preferences library uses (NVS is the cache, just in flash-backed RAM pages).
|
|
64
|
+
*/
|
|
65
|
+
export function preferencesInitLines(): string[] {
|
|
66
|
+
return [
|
|
67
|
+
`// CUTTLEFISH_PREFS_BEGIN`,
|
|
68
|
+
`#define __TC_PREFS_SLOT_COUNT 32`,
|
|
69
|
+
`#define __TC_PREFS_KEY_LEN 48`,
|
|
70
|
+
`#define __TC_PREFS_VAL_LEN 32`,
|
|
71
|
+
`#define __TC_PREFS_STR_LEN 31`,
|
|
72
|
+
``,
|
|
73
|
+
`// One cache slot. The full settings key (tc/<ns>/<key>) lives in key[] so`,
|
|
74
|
+
`// remove()/clear() can reconstruct the exact name to settings_delete. The`,
|
|
75
|
+
`// value is stored in its native wire form (little-endian for the numeric`,
|
|
76
|
+
`// types) so h_set can memcpy straight from the settings read callback.`,
|
|
77
|
+
`struct __tc_prefs_slot final {`,
|
|
78
|
+
` char key[__TC_PREFS_KEY_LEN];`,
|
|
79
|
+
` uint8_t type;`,
|
|
80
|
+
` uint8_t val[__TC_PREFS_VAL_LEN];`,
|
|
81
|
+
` uint8_t len;`,
|
|
82
|
+
` bool used;`,
|
|
83
|
+
`};`,
|
|
84
|
+
``,
|
|
85
|
+
`static struct {`,
|
|
86
|
+
` bool loaded;`,
|
|
87
|
+
` __tc_prefs_slot slots[__TC_PREFS_SLOT_COUNT];`,
|
|
88
|
+
`} __tc_prefs;`,
|
|
89
|
+
``,
|
|
90
|
+
`// ── settings_load() handler (the only mandatory callback) ───────────────`,
|
|
91
|
+
`// settings_load() calls h_set once per stored key it finds, handing us the`,
|
|
92
|
+
`// value via read_cb. We copy it into a cache slot keyed by the full dotted`,
|
|
93
|
+
`// path. h_get/h_commit are unused (the cache is the post-load source of`,
|
|
94
|
+
`// truth) so they return -ENOENT / 0 to satisfy the handler contract.`,
|
|
95
|
+
`static int __tc_prefs_h_set(const char* name, size_t len, settings_read_cb read_cb, void* cb_arg) {`,
|
|
96
|
+
` (void)len;`,
|
|
97
|
+
` for (int i = 0; i < __TC_PREFS_SLOT_COUNT; i++) {`,
|
|
98
|
+
` if (!__tc_prefs.slots[i].used) {`,
|
|
99
|
+
` // Stash the type byte (first val byte) by reading into the slot.`,
|
|
100
|
+
` ssize_t got = read_cb(cb_arg, __tc_prefs.slots[i].val, __TC_PREFS_VAL_LEN);`,
|
|
101
|
+
` if (got <= 0) { return static_cast<int>(got); }`,
|
|
102
|
+
` __tc_prefs.slots[i].len = static_cast<uint8_t>(got);`,
|
|
103
|
+
` // Type is encoded as the first byte of the stored value (see put_*).`,
|
|
104
|
+
` __tc_prefs.slots[i].type = __tc_prefs.slots[i].val[0];`,
|
|
105
|
+
` // h_set hands us the name RELATIVE to the handler's "tc"`,
|
|
106
|
+
` // subtree ("rig/marker") — the cache keys full names, so`,
|
|
107
|
+
` // re-attach the prefix or loaded entries never match a lookup.`,
|
|
108
|
+
` (void)snprintf(__tc_prefs.slots[i].key, __TC_PREFS_KEY_LEN, "tc/%s", name);`,
|
|
109
|
+
` __tc_prefs.slots[i].used = true;`,
|
|
110
|
+
` return 0;`,
|
|
111
|
+
` }`,
|
|
112
|
+
` }`,
|
|
113
|
+
` return 0; // cache full — silently drop (matches ESP32 NVS-full behavior)`,
|
|
114
|
+
`}`,
|
|
115
|
+
`static int __tc_prefs_h_get(const char* full, char* val, int val_len_max) {`,
|
|
116
|
+
` (void)full; (void)val; (void)val_len_max;`,
|
|
117
|
+
` return -ENOENT;`,
|
|
118
|
+
`}`,
|
|
119
|
+
`static int __tc_prefs_h_commit(void) { return 0; }`,
|
|
120
|
+
`SETTINGS_STATIC_HANDLER_DEFINE(tc_prefs, "tc", __tc_prefs_h_get, __tc_prefs_h_set,`,
|
|
121
|
+
` __tc_prefs_h_commit, NULL);`,
|
|
122
|
+
``,
|
|
123
|
+
`// One-time subsystem init + load. Idempotent — the HAL may call begin()`,
|
|
124
|
+
`// repeatedly. settings_subsys_init() is itself idempotent in Zephyr, but the`,
|
|
125
|
+
`// loaded flag short-circuits the (relatively expensive) settings_load() walk.`,
|
|
126
|
+
`static inline void __tc_prefs_ensure_loaded(void) {`,
|
|
127
|
+
` if (!__tc_prefs.loaded) {`,
|
|
128
|
+
` (void)settings_subsys_init();`,
|
|
129
|
+
` (void)settings_load();`,
|
|
130
|
+
` __tc_prefs.loaded = true;`,
|
|
131
|
+
` }`,
|
|
132
|
+
`}`,
|
|
133
|
+
``,
|
|
134
|
+
``,
|
|
135
|
+
`// Slot lookup by full settings name. Returns nullptr when absent (the get_*`,
|
|
136
|
+
`// helpers then fall back to the caller's default value, matching the ESP32`,
|
|
137
|
+
`// getInt(key, default) contract).`,
|
|
138
|
+
`static __tc_prefs_slot* __tc_prefs_find(const char* full) {`,
|
|
139
|
+
` for (int i = 0; i < __TC_PREFS_SLOT_COUNT; i++) {`,
|
|
140
|
+
` if (__tc_prefs.slots[i].used &&`,
|
|
141
|
+
` strncmp(__tc_prefs.slots[i].key, full, __TC_PREFS_KEY_LEN) == 0) {`,
|
|
142
|
+
` return &__tc_prefs.slots[i];`,
|
|
143
|
+
` }`,
|
|
144
|
+
` }`,
|
|
145
|
+
` return nullptr;`,
|
|
146
|
+
`}`,
|
|
147
|
+
``,
|
|
148
|
+
`// Allocate (or reuse) a slot for a full name. Eviction is last-write on a`,
|
|
149
|
+
`// free slot; a full cache returns nullptr and the put silently no-ops (the`,
|
|
150
|
+
`// in-RAM value is still returned to the program on get, just not persisted).`,
|
|
151
|
+
`static __tc_prefs_slot* __tc_prefs_slot_for(const char* full) {`,
|
|
152
|
+
` __tc_prefs_slot* existing = __tc_prefs_find(full);`,
|
|
153
|
+
` if (existing != nullptr) { return existing; }`,
|
|
154
|
+
` for (int i = 0; i < __TC_PREFS_SLOT_COUNT; i++) {`,
|
|
155
|
+
` if (!__tc_prefs.slots[i].used) { return &__tc_prefs.slots[i]; }`,
|
|
156
|
+
` }`,
|
|
157
|
+
` return nullptr;`,
|
|
158
|
+
`}`,
|
|
159
|
+
``,
|
|
160
|
+
`// Generic typed put: stamp the type byte, stash the value, persist via`,
|
|
161
|
+
`// settings_save_one, and mirror into the cache. The type byte rides along`,
|
|
162
|
+
`// as val[0] so h_set can recover it on the next boot without a separate`,
|
|
163
|
+
`// name→type map.`,
|
|
164
|
+
`template <typename T>`,
|
|
165
|
+
`static inline void __tc_prefs_put(const char* full, uint8_t tag, const T& value) {`,
|
|
166
|
+
` __tc_prefs_ensure_loaded(); // begin() is gone — mount lazily here`,
|
|
167
|
+
` uint8_t buf[1U + sizeof(T)];`,
|
|
168
|
+
` buf[0] = tag;`,
|
|
169
|
+
` (void)memcpy(&buf[1], &value, sizeof(T));`,
|
|
170
|
+
` (void)settings_save_one(full, buf, sizeof(buf));`,
|
|
171
|
+
` __tc_prefs_slot* slot = __tc_prefs_slot_for(full);`,
|
|
172
|
+
` if (slot != nullptr) {`,
|
|
173
|
+
` (void)snprintf(slot->key, __TC_PREFS_KEY_LEN, "%s", full);`,
|
|
174
|
+
` slot->type = tag;`,
|
|
175
|
+
` slot->len = static_cast<uint8_t>(sizeof(buf));`,
|
|
176
|
+
` (void)memcpy(slot->val, buf, sizeof(buf));`,
|
|
177
|
+
` slot->used = true;`,
|
|
178
|
+
` }`,
|
|
179
|
+
`}`,
|
|
180
|
+
``,
|
|
181
|
+
`template <typename T>`,
|
|
182
|
+
`static inline T __tc_prefs_get(const char* full, uint8_t tag, T def) {`,
|
|
183
|
+
` __tc_prefs_ensure_loaded();`,
|
|
184
|
+
` __tc_prefs_slot* slot = __tc_prefs_find(full);`,
|
|
185
|
+
` if (slot == nullptr || slot->type != tag || slot->len < (1U + sizeof(T))) {`,
|
|
186
|
+
` return def;`,
|
|
187
|
+
` }`,
|
|
188
|
+
` T out;`,
|
|
189
|
+
` (void)memcpy(&out, &slot->val[1], sizeof(T));`,
|
|
190
|
+
` return out;`,
|
|
191
|
+
`}`,
|
|
192
|
+
``,
|
|
193
|
+
`// ── Lifecycle (session model on top of the flat key-space) ──────────────`,
|
|
194
|
+
`// begin records "tc/<ns>/" as the prefix every subsequent key is built under.`,
|
|
195
|
+
`// end clears the prefix (NOT the cache). Both are cheap on Zephyr: the real`,
|
|
196
|
+
``,
|
|
197
|
+
`// remove: drop one key from flash and the cache. Falls back to no-op if the`,
|
|
198
|
+
`// slot isn't cached (settings_delete on a missing key returns -ENOENT, which`,
|
|
199
|
+
`// we swallow).`,
|
|
200
|
+
`static inline void __tc_prefs_remove(const char* full) {`,
|
|
201
|
+
` __tc_prefs_ensure_loaded();`,
|
|
202
|
+
` (void)settings_delete(full);`,
|
|
203
|
+
` __tc_prefs_slot* slot = __tc_prefs_find(full);`,
|
|
204
|
+
` if (slot != nullptr) { slot->used = false; }`,
|
|
205
|
+
`}`,
|
|
206
|
+
``,
|
|
207
|
+
`// clear: drop every key under the active namespace. We walk the cache (the`,
|
|
208
|
+
`// authoritative list of keys we have written) and settings_delete each whose`,
|
|
209
|
+
`// full name starts with the active ns prefix, then mark the slot free. Only`,
|
|
210
|
+
`// the active namespace is cleared — keys under other namespaces survive.`,
|
|
211
|
+
`static inline void __tc_prefs_clear(const char* prefix) {`,
|
|
212
|
+
` __tc_prefs_ensure_loaded();`,
|
|
213
|
+
` const size_t plen = strlen(prefix);`,
|
|
214
|
+
` for (int i = 0; i < __TC_PREFS_SLOT_COUNT; i++) {`,
|
|
215
|
+
` if (__tc_prefs.slots[i].used &&`,
|
|
216
|
+
` strncmp(__tc_prefs.slots[i].key, prefix, plen) == 0) {`,
|
|
217
|
+
` (void)settings_delete(__tc_prefs.slots[i].key);`,
|
|
218
|
+
` __tc_prefs.slots[i].used = false;`,
|
|
219
|
+
` }`,
|
|
220
|
+
` }`,
|
|
221
|
+
`}`,
|
|
222
|
+
``,
|
|
223
|
+
`// ── Typed accessors ─────────────────────────────────────────────────────`,
|
|
224
|
+
`// Each put_* stamps its tag byte and persists; each get_* reads the cache and`,
|
|
225
|
+
`// returns the default on miss/type-mismatch (mirrors ESP32 Preferences).`,
|
|
226
|
+
`static inline void __tc_prefs_put_int(const char* full, int32_t v) {`,
|
|
227
|
+
` __tc_prefs_put<int32_t>(full, ${TAG.INT}, v);`,
|
|
228
|
+
`}`,
|
|
229
|
+
`static inline int32_t __tc_prefs_get_int(const char* full, int32_t def) {`,
|
|
230
|
+
` return __tc_prefs_get<int32_t>(full, ${TAG.INT}, def);`,
|
|
231
|
+
`}`,
|
|
232
|
+
`static inline void __tc_prefs_put_uint(const char* full, uint32_t v) {`,
|
|
233
|
+
` __tc_prefs_put<uint32_t>(full, ${TAG.UINT}, v);`,
|
|
234
|
+
`}`,
|
|
235
|
+
`static inline uint32_t __tc_prefs_get_uint(const char* full, uint32_t def) {`,
|
|
236
|
+
` return __tc_prefs_get<uint32_t>(full, ${TAG.UINT}, def);`,
|
|
237
|
+
`}`,
|
|
238
|
+
`static inline void __tc_prefs_put_bool(const char* full, bool v) {`,
|
|
239
|
+
` uint8_t b = v ? 1U : 0U;`,
|
|
240
|
+
` __tc_prefs_put<uint8_t>(full, ${TAG.BOOL}, b);`,
|
|
241
|
+
`}`,
|
|
242
|
+
`static inline bool __tc_prefs_get_bool(const char* full, bool def) {`,
|
|
243
|
+
` uint8_t b = __tc_prefs_get<uint8_t>(full, ${TAG.BOOL}, def ? 1U : 0U);`,
|
|
244
|
+
` return b != 0U;`,
|
|
245
|
+
`}`,
|
|
246
|
+
`static inline void __tc_prefs_put_float(const char* full, float v) {`,
|
|
247
|
+
` __tc_prefs_put<float>(full, ${TAG.FLOAT}, v);`,
|
|
248
|
+
`}`,
|
|
249
|
+
`static inline float __tc_prefs_get_float(const char* full, float def) {`,
|
|
250
|
+
` return __tc_prefs_get<float>(full, ${TAG.FLOAT}, def);`,
|
|
251
|
+
`}`,
|
|
252
|
+
``,
|
|
253
|
+
`// Strings are length-prefixed into the value buffer (capped at STR_LEN so the`,
|
|
254
|
+
`// whole slot still fits in __TC_PREFS_VAL_LEN). get copies out with a NUL and`,
|
|
255
|
+
`// returns def when the slot is absent or the wrong type.`,
|
|
256
|
+
`static inline void __tc_prefs_put_string(const char* full, const char* v) {`,
|
|
257
|
+
` __tc_prefs_ensure_loaded();`,
|
|
258
|
+
` uint8_t buf[1U + __TC_PREFS_STR_LEN];`,
|
|
259
|
+
` buf[0] = ${TAG.STRING};`,
|
|
260
|
+
` size_t n = strlen(v);`,
|
|
261
|
+
` if (n > __TC_PREFS_STR_LEN) { n = __TC_PREFS_STR_LEN; }`,
|
|
262
|
+
` (void)memcpy(&buf[1], v, n);`,
|
|
263
|
+
` (void)settings_save_one(full, buf, 1U + n);`,
|
|
264
|
+
` __tc_prefs_slot* slot = __tc_prefs_slot_for(full);`,
|
|
265
|
+
` if (slot != nullptr) {`,
|
|
266
|
+
` (void)snprintf(slot->key, __TC_PREFS_KEY_LEN, "%s", full);`,
|
|
267
|
+
` slot->type = ${TAG.STRING};`,
|
|
268
|
+
` slot->len = static_cast<uint8_t>(1U + static_cast<uint8_t>(n));`,
|
|
269
|
+
` (void)memcpy(slot->val, buf, 1U + n);`,
|
|
270
|
+
` slot->used = true;`,
|
|
271
|
+
` }`,
|
|
272
|
+
`}`,
|
|
273
|
+
`static inline const char* __tc_prefs_get_string(const char* full, const char* def) {`,
|
|
274
|
+
` __tc_prefs_ensure_loaded();`,
|
|
275
|
+
` static char out[__TC_PREFS_STR_LEN + 1U];`,
|
|
276
|
+
` __tc_prefs_slot* slot = __tc_prefs_find(full);`,
|
|
277
|
+
` if (slot == nullptr || slot->type != ${TAG.STRING} || slot->len < 1U) {`,
|
|
278
|
+
` return def;`,
|
|
279
|
+
` }`,
|
|
280
|
+
` size_t n = slot->len - 1U;`,
|
|
281
|
+
` if (n > __TC_PREFS_STR_LEN) { n = __TC_PREFS_STR_LEN; }`,
|
|
282
|
+
` (void)memcpy(out, &slot->val[1], n);`,
|
|
283
|
+
` out[n] = '\\0';`,
|
|
284
|
+
` return out;`,
|
|
285
|
+
`}`,
|
|
286
|
+
`// CUTTLEFISH_PREFS_END`,
|
|
287
|
+
``,
|
|
288
|
+
];
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Resolve a HAL preferences.* op to Zephyr C++ via the __tc_prefs_* shim.
|
|
293
|
+
* Returns `{ code }` for statement ops, `{ expression }` for value-returning
|
|
294
|
+
* ops (the get_* family). The `default` arm throws the standard unsupported-op
|
|
295
|
+
* error so the manifest validator's per-op probe stays honest.
|
|
296
|
+
*/
|
|
297
|
+
export function lowerPreferences(op: HALOpIR): { code?: string; expression?: string } {
|
|
298
|
+
const o = op as any;
|
|
299
|
+
|
|
300
|
+
switch (op.operation) {
|
|
301
|
+
case 'preferences.clear':
|
|
302
|
+
return { code: `__tc_prefs_clear("tc/${unq(o.ns)}/");` };
|
|
303
|
+
case 'preferences.remove':
|
|
304
|
+
return { code: `__tc_prefs_remove("tc/${unq(o.ns)}/${unq(o.key)}");` };
|
|
305
|
+
case 'preferences.put_int':
|
|
306
|
+
return { code: `__tc_prefs_put_int("tc/${unq(o.ns)}/${unq(o.key)}", ${s(o.value)});` };
|
|
307
|
+
case 'preferences.get_int':
|
|
308
|
+
return { expression: `__tc_prefs_get_int("tc/${unq(o.ns)}/${unq(o.key)}", ${s(o.defaultValue)})` };
|
|
309
|
+
case 'preferences.put_bool':
|
|
310
|
+
return { code: `__tc_prefs_put_bool("tc/${unq(o.ns)}/${unq(o.key)}", ${o.value ? 'true' : 'false'});` };
|
|
311
|
+
case 'preferences.get_bool':
|
|
312
|
+
return { expression: `__tc_prefs_get_bool("tc/${unq(o.ns)}/${unq(o.key)}", ${o.defaultValue ? 'true' : 'false'})` };
|
|
313
|
+
case 'preferences.put_float':
|
|
314
|
+
return { code: `__tc_prefs_put_float("tc/${unq(o.ns)}/${unq(o.key)}", ${s(o.value)});` };
|
|
315
|
+
case 'preferences.get_float':
|
|
316
|
+
return { expression: `__tc_prefs_get_float("tc/${unq(o.ns)}/${unq(o.key)}", ${s(o.defaultValue)})` };
|
|
317
|
+
case 'preferences.put_string':
|
|
318
|
+
return { code: `__tc_prefs_put_string("tc/${unq(o.ns)}/${unq(o.key)}", ${s(o.value)});` };
|
|
319
|
+
case 'preferences.get_string':
|
|
320
|
+
return { expression: `__tc_prefs_get_string("tc/${unq(o.ns)}/${unq(o.key)}", ${s(o.defaultValue)})` };
|
|
321
|
+
default:
|
|
322
|
+
throw new Error(
|
|
323
|
+
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
324
|
+
`Open an issue or use rawCpp() to emit it manually.`,
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
}
|