@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
package/src/dt-config/kconfig.ts
CHANGED
|
@@ -1,505 +1,647 @@
|
|
|
1
|
-
import { SENSOR_PART_INFO } from '@typecad/hal';
|
|
2
|
-
|
|
3
|
-
/** A sensor part's catalog facts, as the exceptions helper consumes them. */
|
|
4
|
-
interface SensorKconfigSource {
|
|
5
|
-
kconfig: readonly string[];
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Apply the per-part Kconfig exceptions the generated catalog records, for
|
|
10
|
-
* exactly the parts the program constructs. Lines are CONFIG_<SYM>=<value>
|
|
11
|
-
* strings parsed into the map; a symbol the user set explicitly in
|
|
12
|
-
* zephyr.kconfig is left alone (scaffold.ts already skips user overrides for
|
|
13
|
-
* auto symbols, and Map.set idempotence covers the rest). The lookup is a
|
|
14
|
-
* parameter so tests can drive it with a synthetic catalog.
|
|
15
|
-
*/
|
|
16
|
-
export function applySensorKconfigExceptions(
|
|
17
|
-
m: Map<string, string>,
|
|
18
|
-
parts: readonly { part: string }[] | undefined,
|
|
19
|
-
lookup: Readonly<Record<string, SensorKconfigSource>> = SENSOR_PART_INFO,
|
|
20
|
-
): void {
|
|
21
|
-
if (!parts) return;
|
|
22
|
-
for (const sp of parts) {
|
|
23
|
-
for (const line of lookup[sp.part]?.kconfig ?? []) {
|
|
24
|
-
const eq = line.indexOf('=');
|
|
25
|
-
if (eq <= 0) continue;
|
|
26
|
-
m.set(line.slice(0, eq), line.slice(eq + 1));
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
|
-
// Kconfig fragment resolver — extracts the prj.conf symbol logic
|
|
33
|
-
//
|
|
34
|
-
// Previously inline in scaffold.ts as token-scanning of the emitted source.
|
|
35
|
-
// Formalized here as a typed, unit-testable function keyed off a usage-analysis
|
|
36
|
-
// object (the same ctx.analysis.usesX flags the strategy uses). scaffold.ts
|
|
37
|
-
// calls this instead of inlining the scan, keeping prj.conf generation honest
|
|
38
|
-
// and testable.
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
|
|
41
|
-
export interface KconfigUsage {
|
|
42
|
-
usesAdc?: boolean;
|
|
43
|
-
usesPwm?: boolean;
|
|
44
|
-
usesDac?: boolean;
|
|
45
|
-
usesFS?: boolean;
|
|
46
|
-
usesHwtimer?: boolean;
|
|
47
|
-
usesI2c?: boolean;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
*
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
*
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
*
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
*
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
*
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
*
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (usage.
|
|
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
|
-
|
|
226
|
-
|
|
227
|
-
//
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
// (
|
|
231
|
-
//
|
|
232
|
-
|
|
233
|
-
//
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
//
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
if (usage.
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
m.set('
|
|
297
|
-
//
|
|
298
|
-
//
|
|
299
|
-
//
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
m.set('
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
//
|
|
384
|
-
|
|
385
|
-
m.set('
|
|
386
|
-
m.set('
|
|
387
|
-
|
|
388
|
-
//
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
//
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
m.set('
|
|
396
|
-
m.set('
|
|
397
|
-
m.set('
|
|
398
|
-
//
|
|
399
|
-
//
|
|
400
|
-
//
|
|
401
|
-
//
|
|
402
|
-
|
|
403
|
-
//
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
//
|
|
409
|
-
|
|
410
|
-
//
|
|
411
|
-
//
|
|
412
|
-
//
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
m.set('
|
|
424
|
-
m.set('
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
m.set('
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
m.set('
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
1
|
+
import { SENSOR_PART_INFO } from '@typecad/hal';
|
|
2
|
+
|
|
3
|
+
/** A sensor part's catalog facts, as the exceptions helper consumes them. */
|
|
4
|
+
interface SensorKconfigSource {
|
|
5
|
+
kconfig: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Apply the per-part Kconfig exceptions the generated catalog records, for
|
|
10
|
+
* exactly the parts the program constructs. Lines are CONFIG_<SYM>=<value>
|
|
11
|
+
* strings parsed into the map; a symbol the user set explicitly in
|
|
12
|
+
* zephyr.kconfig is left alone (scaffold.ts already skips user overrides for
|
|
13
|
+
* auto symbols, and Map.set idempotence covers the rest). The lookup is a
|
|
14
|
+
* parameter so tests can drive it with a synthetic catalog.
|
|
15
|
+
*/
|
|
16
|
+
export function applySensorKconfigExceptions(
|
|
17
|
+
m: Map<string, string>,
|
|
18
|
+
parts: readonly { part: string }[] | undefined,
|
|
19
|
+
lookup: Readonly<Record<string, SensorKconfigSource>> = SENSOR_PART_INFO,
|
|
20
|
+
): void {
|
|
21
|
+
if (!parts) return;
|
|
22
|
+
for (const sp of parts) {
|
|
23
|
+
for (const line of lookup[sp.part]?.kconfig ?? []) {
|
|
24
|
+
const eq = line.indexOf('=');
|
|
25
|
+
if (eq <= 0) continue;
|
|
26
|
+
m.set(line.slice(0, eq), line.slice(eq + 1));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Kconfig fragment resolver — extracts the prj.conf symbol logic
|
|
33
|
+
//
|
|
34
|
+
// Previously inline in scaffold.ts as token-scanning of the emitted source.
|
|
35
|
+
// Formalized here as a typed, unit-testable function keyed off a usage-analysis
|
|
36
|
+
// object (the same ctx.analysis.usesX flags the strategy uses). scaffold.ts
|
|
37
|
+
// calls this instead of inlining the scan, keeping prj.conf generation honest
|
|
38
|
+
// and testable.
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
export interface KconfigUsage {
|
|
42
|
+
usesAdc?: boolean;
|
|
43
|
+
usesPwm?: boolean;
|
|
44
|
+
usesDac?: boolean;
|
|
45
|
+
usesFS?: boolean;
|
|
46
|
+
usesHwtimer?: boolean;
|
|
47
|
+
usesI2c?: boolean;
|
|
48
|
+
/** I2C target mode used (i2c.resp_* ops — the responder). Enables the
|
|
49
|
+
* i2c_target API paths: driver implementations are gated on it (e.g.
|
|
50
|
+
* STM32 compiles target support + selects interrupt mode only under
|
|
51
|
+
* I2C_TARGET); controllers without target support still build and
|
|
52
|
+
* return -ENOSYS at registration, which the shim prints loudly. */
|
|
53
|
+
usesI2cTarget?: boolean;
|
|
54
|
+
usesSpi?: boolean;
|
|
55
|
+
usesUart?: boolean;
|
|
56
|
+
/** USB CDC-ACM serial used (usb.* ops). Selects the "next" USB device
|
|
57
|
+
* stack + CDC class; the class instances themselves are composed in the
|
|
58
|
+
* DT overlay and auto-default on once the node exists (assigning the
|
|
59
|
+
* class symbol keeps prj.conf explicit and survives DT-only probes). */
|
|
60
|
+
usesUsb?: boolean;
|
|
61
|
+
usesWdt?: boolean;
|
|
62
|
+
usesBle?: boolean;
|
|
63
|
+
usesDisplay?: boolean;
|
|
64
|
+
/** How the UI adapter reaches the panel. 'zephyr-display' binds the
|
|
65
|
+
* in-tree drivers (CONFIG_MIPI_DBI_SPI on); 'direct-spi' (default)
|
|
66
|
+
* force-disables them — the adapter drives the panel itself. */
|
|
67
|
+
displayTransport?: 'direct-spi' | 'zephyr-display';
|
|
68
|
+
/** Panel controller for the display Kconfig symbol when the transport
|
|
69
|
+
* needs one explicitly. Synthesized (compatible-driven) profiles carry
|
|
70
|
+
* none — their driver symbol auto-defaults on from the DT node
|
|
71
|
+
* (`default y depends on DT_HAS_<COMPATIBLE>_ENABLED`), so no symbol
|
|
72
|
+
* is assigned at all. */
|
|
73
|
+
displayController?: 'st7796s' | 'ili9341' | 'ssd16xx' | 'uc81xx';
|
|
74
|
+
/** Panel bus family from the binding harvest: i2c-family panels (mono
|
|
75
|
+
* OLEDs) get I2C and no SPI/MIPI/DMA block at all. */
|
|
76
|
+
displayBus?: 'i2c' | 'spi';
|
|
77
|
+
/** Profile-required Kconfig fragments, appended verbatim (e.g. the SDL
|
|
78
|
+
* panel's mono pixel-format choice on native_sim). */
|
|
79
|
+
displayKconfigExtra?: readonly string[];
|
|
80
|
+
usesWifi?: boolean;
|
|
81
|
+
usesHttp?: boolean;
|
|
82
|
+
usesMqtt?: boolean;
|
|
83
|
+
usesPreferences?: boolean;
|
|
84
|
+
usesRandom?: boolean;
|
|
85
|
+
/** A printf-family format specifier with a float conversion (%f, %.2f, %e,
|
|
86
|
+
* …) appears in the emitted source — Zephyr's cbprintf only links float
|
|
87
|
+
* conversions with FP_SUPPORT (which itself needs the COMPLETE impl). */
|
|
88
|
+
usesFloatFormat?: boolean;
|
|
89
|
+
/** DT-bound sensor parts used (sensor.* ops — the generic catalog). The
|
|
90
|
+
* umbrella under which every driver sensor Kconfig lives (`if SENSOR`);
|
|
91
|
+
* the per-driver symbols default on from their DT node presence. */
|
|
92
|
+
usesSensor?: boolean;
|
|
93
|
+
/** Addressable LED strip (strip.* ops → ws2812-spi child). */
|
|
94
|
+
usesStrip?: boolean;
|
|
95
|
+
/** Strips the program drives: SPI controller index → chain length.
|
|
96
|
+
* Scanned from the emitted shim's buffer declarations. */
|
|
97
|
+
strips?: Array<{ index: number; count: number }>;
|
|
98
|
+
/** USB HID keyboard/mouse (hid.* ops → zephyr,hid-device node). */
|
|
99
|
+
usesHid?: boolean;
|
|
100
|
+
/** Which HID protocol the program drives — picks the DT node's
|
|
101
|
+
* protocol-code and the report descriptor. */
|
|
102
|
+
hidProtocol?: 'keyboard' | 'mouse';
|
|
103
|
+
/** GPIO key matrix (matrix.* ops → gpio-kbd-matrix node). */
|
|
104
|
+
usesMatrix?: boolean;
|
|
105
|
+
/** The matrix's construction pad lists (from the lowering marker). */
|
|
106
|
+
matrix?: { rows: number[]; cols: number[] };
|
|
107
|
+
/** Explicit power-state entry (power.* ops → sys_poweroff). */
|
|
108
|
+
usesPower?: boolean;
|
|
109
|
+
/** Wall-clock time (clock.* ops → rtc alias). */
|
|
110
|
+
usesClock?: boolean;
|
|
111
|
+
/** CAN bus (can.* ops → the harvested can@ controller). */
|
|
112
|
+
usesCan?: boolean;
|
|
113
|
+
/** I2S audio (i2s.* ops → the harvested i2s@ controller). */
|
|
114
|
+
usesI2s?: boolean;
|
|
115
|
+
/** CAN loopback constructed (CAN_MODE_LOOPBACK in the emission) — the
|
|
116
|
+
* overlay routes both TWAI functions onto one pad (no transceiver). */
|
|
117
|
+
canLoopback?: boolean;
|
|
118
|
+
/** The counter the rtc shim wraps (label + optional timer parent for
|
|
119
|
+
* the child-form ESP32 counters). Omitted when the board ships its own
|
|
120
|
+
* rtc alias — the lowering uses the hardware node. */
|
|
121
|
+
clockShimCounter?: { label: string; parent?: string };
|
|
122
|
+
/** Distinct constructed sensors — only the overlay generator consumes this
|
|
123
|
+
* (one DT child node per entry, on the given I2C controller index); prj.conf
|
|
124
|
+
* ignores it. Same adcReadPins/pwmUsedPins pattern. */
|
|
125
|
+
sensorParts?: readonly { part: string; busIndex: number; port: number; busKind: 'i2c' | 'spi' | 'w1'; spiHz?: number; spiMode?: number; alertPin?: number; resolution?: number }[];
|
|
126
|
+
/** Distinct thin SPI targets (hal/spi-target.ts) — one DT child node per
|
|
127
|
+
* entry (no compatible — a raw spi_dt_spec peer), appended after sensor
|
|
128
|
+
* CS entries in the controller's merged cs-gpios. */
|
|
129
|
+
spiTargets?: readonly { busIndex: number; cs: number; hz?: number; mode?: number }[];
|
|
130
|
+
/** Touch controller referenced (UI touch adapter emits DT_NODELABEL(ft6336u)
|
|
131
|
+
* or DT_NODELABEL(xpt2046)). Selects the bus driver the node needs. */
|
|
132
|
+
usesTouch?: boolean;
|
|
133
|
+
/** Which touch controller the program uses — FT6336U rides I2C, XPT2046
|
|
134
|
+
* rides the display's SPI bus. Only meaningful with usesTouch. */
|
|
135
|
+
touchController?: 'ft6336u' | 'xpt2046';
|
|
136
|
+
/** The emitted shim carries the STM32F4 DBGMCU keep-SWD-alive init
|
|
137
|
+
* (__tc_stm32_dbgmcu token). Selects Zephyr's own "debugger attach in
|
|
138
|
+
* stop/sleep" init (sets DBG_STOP via the LL headers); the shim's raw
|
|
139
|
+
* register poke additionally covers DBG_SLEEP, which the Zephyr F4 path
|
|
140
|
+
* does not set. */
|
|
141
|
+
usesStm32DebugSleep?: boolean;
|
|
142
|
+
/** PSRAM type ('opi' | 'quad') when the target board has PSRAM. Emits the
|
|
143
|
+
* CONFIG_SPIRAM symbols so the ESP heap serves PSRAM for canvas allocations. */
|
|
144
|
+
psram?: 'opi' | 'quad';
|
|
145
|
+
/** HAL pin numbers the program reads with adc.* — scanned from the emitted
|
|
146
|
+
* `__tc_adc<N>_setup()` calls at compile time. Only the overlay generator
|
|
147
|
+
* consumes this (to rewrite the ADC node's pinctrl-0 to the used channels
|
|
148
|
+
* on SoCs that need pad muxing, e.g. STM32); prj.conf ignores it. */
|
|
149
|
+
adcReadPins?: readonly number[];
|
|
150
|
+
/** HAL pin numbers the program drives with dac.* — scanned from the
|
|
151
|
+
* emitted lazy-setup guards (__tc_dact<pin>_done) at compile time. Only
|
|
152
|
+
* the overlay generator consumes this (the DAC node's pinctrl-0 lists
|
|
153
|
+
* the used channels); prj.conf ignores it. */
|
|
154
|
+
dacWritePins?: readonly number[];
|
|
155
|
+
/** HAL pin numbers the program drives with pwm.* — scanned from the
|
|
156
|
+
* emitted `__tc_pwm_*` spec references at compile time. Only the overlay
|
|
157
|
+
* generator consumes this (synthesized pwm-leds consumers + aliases are
|
|
158
|
+
* emitted per used pin, so the DT carries no dead channels); prj.conf
|
|
159
|
+
* ignores it. */
|
|
160
|
+
pwmUsedPins?: readonly number[];
|
|
161
|
+
/** Controller indexes per bus the program actually drives — scanned from
|
|
162
|
+
* the emitted `__tc_<bus><N>_dev` state blocks at compile time. The
|
|
163
|
+
* overlay enables only those controllers (an enabled-but-unused
|
|
164
|
+
* controller claims its default pins — e.g. i2c0's GP4/GP5 on the Pico —
|
|
165
|
+
* which a program using the OTHER controller may want as GPIO). Absent
|
|
166
|
+
* (prepare-time overlays, driver-API-only users like the display
|
|
167
|
+
* adapter) → every declared controller is enabled, preserving the old
|
|
168
|
+
* behavior. prj.conf ignores these. */
|
|
169
|
+
i2cUsedInstances?: readonly number[];
|
|
170
|
+
spiUsedInstances?: readonly number[];
|
|
171
|
+
uartUsedInstances?: readonly number[];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Resolve the Kconfig symbol→value map for a prj.conf. Returns a Map preserving
|
|
176
|
+
* insertion order (callers join with '\n'). Core GPIO + C++ + workqueue symbols
|
|
177
|
+
* are always present; driver symbols are usage-gated.
|
|
178
|
+
*/
|
|
179
|
+
export function resolveKconfigFragments(
|
|
180
|
+
usage: KconfigUsage,
|
|
181
|
+
debug: boolean,
|
|
182
|
+
): Map<string, string> {
|
|
183
|
+
const m = new Map<string, string>();
|
|
184
|
+
|
|
185
|
+
// Core driver + console.
|
|
186
|
+
m.set('CONFIG_GPIO', 'y');
|
|
187
|
+
m.set('CONFIG_PRINTK', 'y');
|
|
188
|
+
m.set('CONFIG_PRINTK_SYNC', 'y');
|
|
189
|
+
m.set('CONFIG_CONSOLE', 'y');
|
|
190
|
+
|
|
191
|
+
if (usage.usesAdc) m.set('CONFIG_ADC', 'y');
|
|
192
|
+
// Sensors: only the umbrella — each in-tree driver is `default y` on its
|
|
193
|
+
// DT_HAS_<COMPAT>_ENABLED, so the overlay's child node enables the driver.
|
|
194
|
+
if (usage.usesSensor) m.set('CONFIG_SENSOR', 'y');
|
|
195
|
+
// 1-Wire masters: the w1 core + the bit-banged GPIO driver (default-on
|
|
196
|
+
// via the synthesized node, but the core W1 menuconfig gates the
|
|
197
|
+
// drivers — set it explicitly so the menu default cannot hide it).
|
|
198
|
+
if ((usage.sensorParts ?? []).some((sp) => sp.busKind === 'w1')) m.set('CONFIG_W1', 'y');
|
|
199
|
+
// The rare driver that is NOT DT-default-on: the catalog records its
|
|
200
|
+
// Kconfig lines (from the driver's own Kconfig) and they are applied for
|
|
201
|
+
// exactly the parts the program constructs. Empty for every in-tree part
|
|
202
|
+
// today — this path is insurance for the next exception.
|
|
203
|
+
applySensorKconfigExceptions(m, usage.sensorParts);
|
|
204
|
+
// Float formatting: cbprintf builds float conversions only under
|
|
205
|
+
// FP_SUPPORT, which depends on the COMPLETE implementation — without these,
|
|
206
|
+
// %f silently prints garbage instead of the value.
|
|
207
|
+
if (usage.usesFloatFormat) {
|
|
208
|
+
m.set('CONFIG_CBPRINTF_COMPLETE', 'y');
|
|
209
|
+
m.set('CONFIG_CBPRINTF_FP_SUPPORT', 'y');
|
|
210
|
+
}
|
|
211
|
+
if (usage.usesPwm) m.set('CONFIG_PWM', 'y');
|
|
212
|
+
if (usage.usesStrip) m.set('CONFIG_LED_STRIP', 'y');
|
|
213
|
+
// HID rides the same "next" device stack as CDC — the class is selected by
|
|
214
|
+
// the zephyr,hid-device node the overlay synthesizes.
|
|
215
|
+
if (usage.usesHid) {
|
|
216
|
+
m.set('CONFIG_USB_DEVICE_STACK_NEXT', 'y');
|
|
217
|
+
m.set('CONFIG_USBD_HID_SUPPORT', 'y');
|
|
218
|
+
}
|
|
219
|
+
if (usage.usesMatrix) {
|
|
220
|
+
m.set('CONFIG_INPUT', 'y');
|
|
221
|
+
m.set('CONFIG_INPUT_GPIO_KBD_MATRIX', 'y');
|
|
222
|
+
}
|
|
223
|
+
// sys_poweroff() only exists when the kernel builds the poweroff service
|
|
224
|
+
// (the SoC hook compiles under this symbol — without it the link fails
|
|
225
|
+
// with an undefined reference).
|
|
226
|
+
if (usage.usesPower) m.set('CONFIG_POWEROFF', 'y');
|
|
227
|
+
// The rtc subsystem; the counter shim driver defaults on when the
|
|
228
|
+
// synthesized zephyr,rtc-counter node exists. RTC_INIT_PRIORITY defaults
|
|
229
|
+
// to KERNEL_INIT_PRIORITY_DEVICE (=50) which is BELOW the counter driver
|
|
230
|
+
// (=60) — the shim asserts it inits after its parent counter, so raise
|
|
231
|
+
// it whenever the shim is in play.
|
|
232
|
+
if (usage.usesCan) m.set('CONFIG_CAN', 'y');
|
|
233
|
+
// I2S needs the DMA umbrella + the ESP32 GDMA driver (the controller
|
|
234
|
+
// DMA-runs through the gdma node the overlay enables — the driver is
|
|
235
|
+
// default-y once the node is on, but the umbrella needs the explicit
|
|
236
|
+
// set because nothing else pulls it in).
|
|
237
|
+
if (usage.usesI2s) {
|
|
238
|
+
m.set('CONFIG_I2S', 'y');
|
|
239
|
+
m.set('CONFIG_DMA', 'y');
|
|
240
|
+
}
|
|
241
|
+
if (usage.usesClock) {
|
|
242
|
+
m.set('CONFIG_RTC', 'y');
|
|
243
|
+
m.set('CONFIG_RTC_INIT_PRIORITY', '70');
|
|
244
|
+
}
|
|
245
|
+
if (usage.usesDac) m.set('CONFIG_DAC', 'y');
|
|
246
|
+
if (usage.usesI2c) m.set('CONFIG_I2C', 'y');
|
|
247
|
+
if (usage.usesI2cTarget) m.set('CONFIG_I2C_TARGET', 'y');
|
|
248
|
+
if (usage.usesSpi) m.set('CONFIG_SPI', 'y');
|
|
249
|
+
// USB CDC-ACM serial: the "next" USB device stack + the CDC-ACM class.
|
|
250
|
+
// Symbol names verified against Zephyr 4.3 (subsys/usb/device_next/Kconfig):
|
|
251
|
+
// - USB_DEVICE_STACK_NEXT is the new stack (selects UDC_DRIVER);
|
|
252
|
+
// USB_DEVICE_STACK is the LEGACY stack — deprecated in 4.3 (selects
|
|
253
|
+
// DEPRECATED) and its assignment is what trips the build.
|
|
254
|
+
// - USBD_CDC_ACM_CLASS is the class (note the USBD_ prefix — a bare
|
|
255
|
+
// CDC_ACM_CLASS is an undefined symbol). It depends on SERIAL +
|
|
256
|
+
// DT_HAS_ZEPHYR_CDC_ACM_UART_ENABLED (the overlay's cdc-acm-uart node)
|
|
257
|
+
// and selects UART_INTERRUPT_DRIVEN/RING_BUFFER itself; assigning it
|
|
258
|
+
// keeps prj.conf explicit.
|
|
259
|
+
// - UART_LINE_CTRL gates the driver's line_ctrl_get — usb.connected()
|
|
260
|
+
// polls DTR through it.
|
|
261
|
+
if (usage.usesUsb) {
|
|
262
|
+
m.set('CONFIG_USB_DEVICE_STACK_NEXT', 'y');
|
|
263
|
+
m.set('CONFIG_USBD_CDC_ACM_CLASS', 'y');
|
|
264
|
+
m.set('CONFIG_UART_LINE_CTRL', 'y');
|
|
265
|
+
m.set('CONFIG_SERIAL', 'y');
|
|
266
|
+
// The device presents a serial-number string descriptor sourced from
|
|
267
|
+
// hwinfo (the SoC's unique ID). Without it Windows keys the CDC devnode
|
|
268
|
+
// on the physical USB port: replugs reuse stale nodes and repeated flash
|
|
269
|
+
// cycles wedge them into permanent "access denied" opens. A serial makes
|
|
270
|
+
// the instance path identity-based — stable across ports, immune to the
|
|
271
|
+
// port-keyed ghost pool.
|
|
272
|
+
m.set('CONFIG_HWINFO', 'y');
|
|
273
|
+
}
|
|
274
|
+
if (usage.usesWdt) m.set('CONFIG_WATCHDOG', 'y');
|
|
275
|
+
// STM32: keep the debugger attachable in sleep/stop (see the shim's
|
|
276
|
+
// DBGMCU init — this covers the Zephyr-side DBG_STOP bit via LL headers).
|
|
277
|
+
if (usage.usesStm32DebugSleep) m.set('CONFIG_STM32_ENABLE_DEBUG_SLEEP_STOP', 'y');
|
|
278
|
+
// Hardware timers via the counter driver.
|
|
279
|
+
if (usage.usesHwtimer) m.set('CONFIG_COUNTER', 'y');
|
|
280
|
+
if (usage.usesDisplay) {
|
|
281
|
+
m.set('CONFIG_DISPLAY', 'y');
|
|
282
|
+
if (usage.displayBus === 'i2c' || usage.displayKconfigExtra) {
|
|
283
|
+
// Self-describing panels — no SPI bridge, no DMA:
|
|
284
|
+
// - i2c-family (mono OLEDs, ssd1306-class): an I2C child node; the
|
|
285
|
+
// panel driver self-builds from it.
|
|
286
|
+
// - board-provided panels (native_sim's sdl_dc): the board's own DTS
|
|
287
|
+
// wires the display; the profile's extra fragments (e.g. the SDL
|
|
288
|
+
// panel's mono pixel-format choice) land here verbatim.
|
|
289
|
+
if (usage.displayBus === 'i2c') m.set('CONFIG_I2C', 'y');
|
|
290
|
+
for (const frag of usage.displayKconfigExtra ?? []) {
|
|
291
|
+
const eq = frag.indexOf('=');
|
|
292
|
+
if (eq > 0) m.set(frag.slice(0, eq).trim(), frag.slice(eq + 1).trim());
|
|
293
|
+
}
|
|
294
|
+
} else {
|
|
295
|
+
m.set('CONFIG_SPI', 'y');
|
|
296
|
+
m.set('CONFIG_MIPI_DBI', 'y');
|
|
297
|
+
// Enable GDMA so the ESP32 SPI driver uses DMA for panel transfers instead
|
|
298
|
+
// of PIO through the 64-byte hardware FIFO. Without DMA a full 480x320 fill
|
|
299
|
+
// takes ~110ms (effectively ~4MHz); with DMA the same transfer runs at the
|
|
300
|
+
// configured SPI clock (~80MHz) and drops into the low tens of ms. The
|
|
301
|
+
// display overlay pairs this with dma-enabled + dmas on the spi2 node.
|
|
302
|
+
m.set('CONFIG_DMA', 'y');
|
|
303
|
+
if (usage.displayTransport === 'zephyr-display') {
|
|
304
|
+
// Native display-API transport: the mipi-dbi SPI bridge hosts the
|
|
305
|
+
// panel driver, which owns init/rotation/wire format. Controller-
|
|
306
|
+
// specific exceptions and the drop-in (compatible-driven) path:
|
|
307
|
+
// - st7796s (registry profile): the stock bridge deasserts CS
|
|
308
|
+
// between command and parameters (scrambles clone panels), so it
|
|
309
|
+
// stays OFF — the adapter emits an app-local CS-holding host.
|
|
310
|
+
// - ili9341 (registry profile): assign the prompted symbol explicitly
|
|
311
|
+
// (survives DT-only probes; not the hidden ILI9XXX).
|
|
312
|
+
// - synthesized profiles (no controller): assign NOTHING — panel
|
|
313
|
+
// drivers are `default y depends on DT_HAS_<COMPATIBLE>_ENABLED`,
|
|
314
|
+
// so the overlay's enabled node builds its own driver.
|
|
315
|
+
if (usage.displayController === 'st7796s') {
|
|
316
|
+
m.set('CONFIG_MIPI_DBI_SPI', 'n');
|
|
317
|
+
m.set('CONFIG_ST7796S', 'y');
|
|
318
|
+
} else if (usage.displayController === 'ili9341') {
|
|
319
|
+
m.set('CONFIG_MIPI_DBI_SPI', 'y');
|
|
320
|
+
m.set('CONFIG_ILI9341', 'y');
|
|
321
|
+
} else {
|
|
322
|
+
m.set('CONFIG_MIPI_DBI_SPI', 'y');
|
|
323
|
+
}
|
|
324
|
+
// E-ink families (Stage 4): the panel driver under the mipi-dbi SPI
|
|
325
|
+
// bridge — ssd16xx/uc81xx own the flash-cycle refresh + BUSY wait.
|
|
326
|
+
if (usage.displayController === 'ssd16xx') {
|
|
327
|
+
m.set('CONFIG_SSD16XX', 'y');
|
|
328
|
+
} else if (usage.displayController === 'uc81xx') {
|
|
329
|
+
m.set('CONFIG_UC81XX', 'y');
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
// Direct-spi transport (default): the display adapter drives the panel
|
|
333
|
+
// directly via spi_write. Disable the MIPI DBI SPI bridge + in-tree panel
|
|
334
|
+
// drivers (ILI9341, ST7796S) — binding them would allocate a
|
|
335
|
+
// tearing-effect GPIO interrupt that conflicts with the SPI/I2C driver
|
|
336
|
+
// interrupts — the VECDESC_FL_SHARED assertion crashes on touch.
|
|
337
|
+
// ILI9341 matters as much as the bridge: the driver auto-defaults on
|
|
338
|
+
// from the overlay's ilitek,ili9341 node and references the (disabled)
|
|
339
|
+
// mipi-dbi-spi controller's device struct, failing at link time with
|
|
340
|
+
// "undefined reference to __device_dts_ord_N".
|
|
341
|
+
m.set('CONFIG_MIPI_DBI_SPI', 'n');
|
|
342
|
+
m.set('CONFIG_ILI9341', 'n');
|
|
343
|
+
m.set('CONFIG_ST7796S', 'n');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (usage.usesTouch) {
|
|
348
|
+
if (usage.touchController === 'xpt2046') {
|
|
349
|
+
// XPT2046 rides the display's SPI bus — the raw adapter owns the chip
|
|
350
|
+
// (CONFIG_INPUT stays off: the in-tree driver's DT min/max scaling
|
|
351
|
+
// would double-apply the runtime calibration — see touch-adapter.ts).
|
|
352
|
+
m.set('CONFIG_SPI', 'y');
|
|
353
|
+
} else {
|
|
354
|
+
// FT6336U through the input subsystem: the in-tree focaltech driver
|
|
355
|
+
// owns the controller in polling mode (no int-gpios on the node — no
|
|
356
|
+
// GPIO IRQ is registered, sidestepping the ESP32 VECDESC_FL_SHARED
|
|
357
|
+
// crash the interrupt path hit). The adapter listens for its events.
|
|
358
|
+
m.set('CONFIG_INPUT', 'y');
|
|
359
|
+
m.set('CONFIG_INPUT_FT5336', 'y');
|
|
360
|
+
m.set('CONFIG_I2C', 'y');
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// PSRAM: enable the ESP SPIRAM driver + route malloc/heap to external RAM so
|
|
364
|
+
// large canvas allocations (scroll viewports, lists) can use PSRAM instead of
|
|
365
|
+
// failing in internal SRAM. Zephyr's ESP32 PSRAM support uses CONFIG_ESP_SPIRAM
|
|
366
|
+
// (not CONFIG_SPIRAM — that's an ESP-IDF symbol). The mode choice selects the
|
|
367
|
+
// PSRAM type: OCT for OPI (ESP32-S3), QUAD for quad-spi. CONFIG_ESP_SPIRAM
|
|
368
|
+
// selects SHARED_MULTI_HEAP automatically, which routes heap_caps_malloc to
|
|
369
|
+
// PSRAM. The SoC dtsi already carries the psram0 DT node.
|
|
370
|
+
if (usage.psram) {
|
|
371
|
+
m.set('CONFIG_ESP_SPIRAM', 'y');
|
|
372
|
+
if (usage.psram === 'opi') {
|
|
373
|
+
m.set('CONFIG_SPIRAM_MODE_OCT', 'y');
|
|
374
|
+
} else {
|
|
375
|
+
m.set('CONFIG_SPIRAM_MODE_QUAD', 'y');
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
if (usage.usesWifi) {
|
|
379
|
+
// Master networking switch — every CONFIG_NET_* symbol depends on NETWORKING
|
|
380
|
+
// (without it, Kconfig silently forces them all to n).
|
|
381
|
+
m.set('CONFIG_NETWORKING', 'y');
|
|
382
|
+
m.set('CONFIG_WIFI', 'y');
|
|
383
|
+
m.set('CONFIG_WIFI_ESP32', 'y'); // family-wide ESP32 driver (esp32/s3/c3/c6)
|
|
384
|
+
m.set('CONFIG_NET_L2_ETHERNET', 'y');
|
|
385
|
+
m.set('CONFIG_NET_IPV4', 'y');
|
|
386
|
+
m.set('CONFIG_NET_UDP', 'y'); // transitive dep of NET_DHCPV4
|
|
387
|
+
m.set('CONFIG_NET_DHCPV4', 'y');
|
|
388
|
+
// NOT CONFIG_NET_CONFIG_SETTINGS: that runs net_config_init() at boot which
|
|
389
|
+
// BLOCKS up to NET_CONFIG_INIT_TIMEOUT (default 30s) waiting for the iface
|
|
390
|
+
// to come up — but our shim brings the iface up itself in main() (connect),
|
|
391
|
+
// so net_config waits the full 30s, then the dual management of the same
|
|
392
|
+
// iface crashes the driver. Our shim owns connectivity (net_mgmt connect/
|
|
393
|
+
// disconnect + conn_mgr monitor for L4), exactly like the standalone Zephyr
|
|
394
|
+
// WiFi samples that omit NET_CONFIG_SETTINGS.
|
|
395
|
+
m.set('CONFIG_NET_MGMT', 'y');
|
|
396
|
+
m.set('CONFIG_NET_MGMT_EVENT', 'y'); // required for the net_mgmt callbacks
|
|
397
|
+
m.set('CONFIG_NET_CONNECTION_MANAGER', 'y'); // conn_mgr — the connect portability layer
|
|
398
|
+
// Networking stack sizes. The defaults are tiny (NET_MGMT_EVENT_STACK_SIZE
|
|
399
|
+
// is 768 on non-x86) and the WiFi connect result/event handlers run on that
|
|
400
|
+
// stack — overflowing it freezes the chip mid-connect (silent hard fault,
|
|
401
|
+
// no panic dump). The official Zephyr WiFi samples (samples/net/wifi/*)
|
|
402
|
+
// bump exactly these; mirror them. MAIN_STACK 4096→5200 because esp_wifi
|
|
403
|
+
// device init is stack-hungry and 4096 is marginal on the ESP32-S3.
|
|
404
|
+
m.set('CONFIG_NET_MGMT_EVENT_STACK_SIZE', '4096');
|
|
405
|
+
m.set('CONFIG_NET_TX_STACK_SIZE', '2048');
|
|
406
|
+
m.set('CONFIG_NET_RX_STACK_SIZE', '2048');
|
|
407
|
+
m.set('CONFIG_MAIN_STACK_SIZE', '5200');
|
|
408
|
+
// NOTE: wifi.set_tx_power needs no Kconfig symbol. esp_wifi_set_max_tx_power
|
|
409
|
+
// programs the radio at runtime; its ceiling is baked into the prebuilt
|
|
410
|
+
// libphy.a / PHY init data, not a prj.conf knob. The ESP-IDF symbol
|
|
411
|
+
// ESP_PHY_MAX_WIFI_TX_POWER lives in components/esp_phy/Kconfig, which the
|
|
412
|
+
// Zephyr module integration does NOT source — assigning it here would abort
|
|
413
|
+
// the build ("undefined symbol").
|
|
414
|
+
}
|
|
415
|
+
if (usage.usesHttp) {
|
|
416
|
+
// HTTP/S rides on the networking stack. The shim does its own
|
|
417
|
+
// socket/getaddrinfo/connect, so it needs the BSD socket layer + POSIX
|
|
418
|
+
// DNS surface + the http client lib, plus the TLS sockopt layer (which
|
|
419
|
+
// selects mbedTLS) and the DNS resolver. HTTP needs the same IP base as
|
|
420
|
+
// WiFi, so this emits the networking primitives even when usesWifi is
|
|
421
|
+
// false — an http-only program still has to reach the internet. Map.set
|
|
422
|
+
// is idempotent, so overlaps with the wifi block are harmless.
|
|
423
|
+
m.set('CONFIG_NETWORKING', 'y');
|
|
424
|
+
m.set('CONFIG_NET_IPV4', 'y');
|
|
425
|
+
m.set('CONFIG_NET_DHCPV4', 'y');
|
|
426
|
+
m.set('CONFIG_NET_TCP', 'y'); // http_client_req needs a TCP socket
|
|
427
|
+
// NET_MAX_CONTEXTS caps the network 5-tuple (socket) pool — the default 6 is
|
|
428
|
+
// exhausted after a handful of sequential HTTP requests even when each is
|
|
429
|
+
// closed (closed TCP contexts linger in TIME_WAIT), and socket() then returns
|
|
430
|
+
// -EPERM. The hardware CRUD harness makes ~17 sequential requests, so raise
|
|
431
|
+
// this well above the default.
|
|
432
|
+
m.set('CONFIG_NET_MAX_CONTEXTS', '16');
|
|
433
|
+
// NET_MAX_CONN is the connection-registry pool (default 8 with v4+v6), a
|
|
434
|
+
// *separate* limit from NET_MAX_CONTEXTS. Closed TCP entries linger briefly
|
|
435
|
+
// in the registry, so rapid sequential HTTP requests exhaust the default and
|
|
436
|
+
// connect() then returns -EPERM. Pair it with NET_MAX_CONTEXTS so both the
|
|
437
|
+
// socket (5-tuple) and connection-registry pools have headroom.
|
|
438
|
+
m.set('CONFIG_NET_MAX_CONN', '16');
|
|
439
|
+
// ZVFS_OPEN_MAX must be set above 0 or socket() returns -EPERM (errno 1): the
|
|
440
|
+
// fd table is allocated to exactly ZVFS_OPEN_MAX entries, and the default 0
|
|
441
|
+
// (even with the ZVFS_OPEN_ADD_SIZE_* "min" contributors) yields zero usable
|
|
442
|
+
// descriptors. HTTP tests open/close a socket per request; give headroom over
|
|
443
|
+
// the per-subsystem contributors (NET=6, POSIX=3).
|
|
444
|
+
m.set('CONFIG_ZVFS_OPEN_MAX', '16');
|
|
445
|
+
// NET_SOCKETS is the user-facing switch for the BSD socket API + ZVFS. The
|
|
446
|
+
// shim uses bare POSIX names (connect/socket/close/getaddrinfo/freeaddrinfo)
|
|
447
|
+
// rather than the zsock_ forms; those bare names resolve under CONFIG_POSIX_API
|
|
448
|
+
// (the official samples/net/sockets/http_client sample sets exactly this).
|
|
449
|
+
// Without it, <zephyr/posix/unistd.h> gates `int close(int)` behind
|
|
450
|
+
// #ifdef CONFIG_POSIX_API and the build fails with "'close' was not declared".
|
|
451
|
+
m.set('CONFIG_NET_SOCKETS', 'y');
|
|
452
|
+
m.set('CONFIG_POSIX_API', 'y');
|
|
453
|
+
m.set('CONFIG_DNS_RESOLVER', 'y'); // getaddrinfo for hostnames
|
|
454
|
+
m.set('CONFIG_DNS_SERVER_IP_ADDRESSES', 'y');
|
|
455
|
+
m.set('CONFIG_HTTP_CLIENT', 'y'); // <zephyr/net/http/client.h> + http_client_req
|
|
456
|
+
// HTTPS via Zephyr socket TLS (IPPROTO_TLS_1_2 + SOL_TLS sockopts, driven by
|
|
457
|
+
// the shim's __tc_http_open_socket https branch). NET_SOCKETS_SOCKOPT_TLS
|
|
458
|
+
// selects mbedTLS, but its ssl layer (mbedtls_ssl_*) needs the rest of this
|
|
459
|
+
// matrix to actually link + a working TLS 1.2 protocol + key exchange.
|
|
460
|
+
m.set('CONFIG_NET_SOCKETS_SOCKOPT_TLS', 'y');
|
|
461
|
+
m.set('CONFIG_TLS_CREDENTIALS', 'y'); // tls_credential_add for caCert()
|
|
462
|
+
m.set('CONFIG_MBEDTLS', 'y');
|
|
463
|
+
m.set('CONFIG_MBEDTLS_BUILTIN', 'y');
|
|
464
|
+
// Enable TLS 1.2 via a single ciphersuite rather than the broad
|
|
465
|
+
// SSL_PROTO_TLS1_2 + KEY_EXCHANGE_ALL_ENABLED (the latter selects KEXes whose
|
|
466
|
+
// PSA_WANT_* deps are unsatisfied → Kconfig abort) or a bare
|
|
467
|
+
// SSL_PROTO_TLS1_2 (no key exchange → check_config.h "no key exchange
|
|
468
|
+
// methods defined"). A ciphersuite is the proven path the in-tree HTTPS
|
|
469
|
+
// samples use (samples/net/prometheus): it transitively selects
|
|
470
|
+
// MBEDTLS_SSL_PROTO_TLS1_2 + its one key exchange + every PSA_WANT_* key/alg
|
|
471
|
+
// that key exchange needs, with no dangling deps. ECDHE_RSA matches the test
|
|
472
|
+
// server's RSA cert (rsa:2048) and is widely offered; add more ciphersuites
|
|
473
|
+
// here to broaden server compatibility.
|
|
474
|
+
m.set('CONFIG_MBEDTLS_CIPHERSUITE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', 'y');
|
|
475
|
+
// Ciphersuites only *depend on* X509_CRT_PARSE_C (they don't select it) —
|
|
476
|
+
// without it sockets_tls.c compiles out mbedtls_x509_crt_parse and every
|
|
477
|
+
// pinned-CA handshake fails with EPERM at connect (the insecure path
|
|
478
|
+
// skips verification, so it works either way).
|
|
479
|
+
m.set('CONFIG_MBEDTLS_X509_CRT_PARSE_C', 'y');
|
|
480
|
+
// KNOWN LIMITATION on this Zephyr tree: pinned-CA (verified TLS) was
|
|
481
|
+
// observed failing at connect with EPERM — the tf-psa-crypto mbedTLS
|
|
482
|
+
// needs a wider symbol matrix (RSA public-key parse + PEM/DER glue)
|
|
483
|
+
// than the single-ciphersuite select pulls in, and forcing the extra
|
|
484
|
+
// symbols regressed the insecure path (two hardware cycles proved it
|
|
485
|
+
// upstream). CAVEAT: that diagnosis predates the 2026-09 fix of the
|
|
486
|
+
// request-fact reset ordering (every option — including caCert — was
|
|
487
|
+
// being wiped before each send, which alone reproduces connect
|
|
488
|
+
// failures); the matrix limitation needs a hardware re-run to confirm
|
|
489
|
+
// it still applies. insecure() HTTPS and no-CA https are unaffected.
|
|
490
|
+
// Handshake/protocol buffers allocate from the mbedTLS heap; MBEDTLS_HEAP_SIZE
|
|
491
|
+
// must hold ~2x MBEDTLS_SSL_MAX_CONTENT_LEN plus working state. 65000 fits on
|
|
492
|
+
// the ESP32; mbedTLS requires the full libc and PEM (not DER) cert format.
|
|
493
|
+
m.set('CONFIG_MBEDTLS_ENABLE_HEAP', 'y');
|
|
494
|
+
// 2x SSL_MAX_CONTENT_LEN record buffers + CA-chain parse state +
|
|
495
|
+
// handshake working memory. 65000 fit insecure-mode handshakes but the
|
|
496
|
+
// pinned-CA path (verification state) overflowed → EPERM at connect.
|
|
497
|
+
m.set('CONFIG_MBEDTLS_HEAP_SIZE', '100000');
|
|
498
|
+
m.set('CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN', '16384');
|
|
499
|
+
m.set('CONFIG_PSA_CRYPTO', 'y');
|
|
500
|
+
m.set('CONFIG_REQUIRES_FULL_LIBC', 'y');
|
|
501
|
+
// The http client + TLS handshake are stack-hungry; mirror the wifi bumps
|
|
502
|
+
// (NET_*_STACK_SIZE) and keep the larger main-stack value (TLS handshake
|
|
503
|
+
// overflows the default main stack).
|
|
504
|
+
m.set('CONFIG_NET_MGMT_EVENT_STACK_SIZE', '4096');
|
|
505
|
+
m.set('CONFIG_NET_TX_STACK_SIZE', '2048');
|
|
506
|
+
m.set('CONFIG_NET_RX_STACK_SIZE', '2048');
|
|
507
|
+
if (!usage.usesWifi) m.set('CONFIG_MAIN_STACK_SIZE', '5200');
|
|
508
|
+
}
|
|
509
|
+
if (usage.usesMqtt) {
|
|
510
|
+
// MQTT rides on the networking stack. CONFIG_MQTT_LIB selects NET_SOCKETS;
|
|
511
|
+
// the shim getaddrinfo-resolves the broker and runs its own poll k_thread.
|
|
512
|
+
// CONFIG_MQTT_LIB_TLS enables MQTT_TRANSPORT_SECURE + mqtt_sec_config; the
|
|
513
|
+
// mbedTLS matrix is the same one HTTP uses (it's idempotent via Map.set).
|
|
514
|
+
m.set('CONFIG_NETWORKING', 'y');
|
|
515
|
+
m.set('CONFIG_NET_IPV4', 'y');
|
|
516
|
+
m.set('CONFIG_NET_DHCPV4', 'y');
|
|
517
|
+
m.set('CONFIG_NET_TCP', 'y');
|
|
518
|
+
m.set('CONFIG_NET_SOCKETS', 'y');
|
|
519
|
+
m.set('CONFIG_MQTT_LIB', 'y');
|
|
520
|
+
m.set('CONFIG_MQTT_LIB_TLS', 'y');
|
|
521
|
+
// The shim getaddrinfo-resolves the broker host — without the DNS
|
|
522
|
+
// resolver linked, getaddrinfo fails numeric AND hostname lookups with
|
|
523
|
+
// EAI_FAIL even while plain HTTP (which selects DNS via its own block)
|
|
524
|
+
// works.
|
|
525
|
+
m.set('CONFIG_DNS_RESOLVER', 'y');
|
|
526
|
+
m.set('CONFIG_DNS_SERVER_IP_ADDRESSES', 'y');
|
|
527
|
+
// NET_MAX_CONTEXTS / NET_MAX_CONN: same exhaustion risk as HTTP — sequential
|
|
528
|
+
// connections linger after close. Give the broker session + headroom.
|
|
529
|
+
m.set('CONFIG_NET_MAX_CONTEXTS', '16');
|
|
530
|
+
m.set('CONFIG_NET_MAX_CONN', '16');
|
|
531
|
+
m.set('CONFIG_ZVFS_OPEN_MAX', '16');
|
|
532
|
+
// mbedTLS matrix for mqtts:// (mirrors the HTTP block; overlaps are harmless).
|
|
533
|
+
m.set('CONFIG_NET_SOCKETS_SOCKOPT_TLS', 'y');
|
|
534
|
+
m.set('CONFIG_TLS_CREDENTIALS', 'y');
|
|
535
|
+
m.set('CONFIG_MBEDTLS', 'y');
|
|
536
|
+
m.set('CONFIG_MBEDTLS_BUILTIN', 'y');
|
|
537
|
+
m.set('CONFIG_MBEDTLS_CIPHERSUITE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', 'y');
|
|
538
|
+
// Ciphersuites only *depend on* X509_CRT_PARSE_C (they don't select it) —
|
|
539
|
+
// without it sockets_tls.c compiles out mbedtls_x509_crt_parse and every
|
|
540
|
+
// pinned-CA handshake fails with EPERM at connect (the insecure path
|
|
541
|
+
// skips verification, so it works either way).
|
|
542
|
+
m.set('CONFIG_MBEDTLS_X509_CRT_PARSE_C', 'y');
|
|
543
|
+
// KNOWN LIMITATION on this Zephyr tree: pinned-CA (verified TLS) was
|
|
544
|
+
// observed failing at connect with EPERM — the tf-psa-crypto mbedTLS
|
|
545
|
+
// needs a wider symbol matrix (RSA public-key parse + PEM/DER glue)
|
|
546
|
+
// than the single-ciphersuite select pulls in. CAVEAT: that diagnosis
|
|
547
|
+
// was made on the HTTPS path and predates the 2026-09 request-fact
|
|
548
|
+
// reset-ordering fix (options were wiped before every send, which
|
|
549
|
+
// alone reproduces connect failures); it is shared here because mqtts
|
|
550
|
+
// pins its CA through the same matrix — re-verify on hardware.
|
|
551
|
+
m.set('CONFIG_MBEDTLS_ENABLE_HEAP', 'y');
|
|
552
|
+
// 2x SSL_MAX_CONTENT_LEN record buffers + CA-chain parse state +
|
|
553
|
+
// handshake working memory. 65000 fit insecure-mode handshakes but the
|
|
554
|
+
// pinned-CA path (verification state) overflowed → EPERM at connect.
|
|
555
|
+
m.set('CONFIG_MBEDTLS_HEAP_SIZE', '100000');
|
|
556
|
+
m.set('CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN', '16384');
|
|
557
|
+
m.set('CONFIG_PSA_CRYPTO', 'y');
|
|
558
|
+
m.set('CONFIG_REQUIRES_FULL_LIBC', 'y');
|
|
559
|
+
m.set('CONFIG_NET_TX_STACK_SIZE', '2048');
|
|
560
|
+
m.set('CONFIG_NET_RX_STACK_SIZE', '2048');
|
|
561
|
+
if (!usage.usesWifi && !usage.usesHttp) m.set('CONFIG_MAIN_STACK_SIZE', '5200');
|
|
562
|
+
}
|
|
563
|
+
if (usage.usesBle) {
|
|
564
|
+
m.set('CONFIG_BT', 'y');
|
|
565
|
+
m.set('CONFIG_BT_PERIPHERAL', 'y');
|
|
566
|
+
m.set('CONFIG_BT_GATT_DYNAMIC_DB', 'y');
|
|
567
|
+
}
|
|
568
|
+
// Preferences: ZMS-backed settings. CONFIG_SETTINGS_ZMS depends on ZMS +
|
|
569
|
+
// FLASH_MAP (it does NOT select them), so all three must be set explicitly.
|
|
570
|
+
// The backend locates the storage_partition fixed-partition automatically
|
|
571
|
+
// (or the /chosen zephyr,settings-partition — see dt-config/overlay.ts); no
|
|
572
|
+
// partition macro is needed in the shim. ZMS is preferred over NVS per the
|
|
573
|
+
// Zephyr docs ("as of 4.1 the recommended backend is NVS or ZMS").
|
|
574
|
+
if (usage.usesPreferences) {
|
|
575
|
+
m.set('CONFIG_FLASH', 'y');
|
|
576
|
+
m.set('CONFIG_FLASH_MAP', 'y');
|
|
577
|
+
m.set('CONFIG_ZMS', 'y');
|
|
578
|
+
m.set('CONFIG_SETTINGS', 'y');
|
|
579
|
+
m.set('CONFIG_SETTINGS_ZMS', 'y');
|
|
580
|
+
}
|
|
581
|
+
// Filesystem: littlefs on the storage partition. CONFIG_FILE_SYSTEM_LITTLEFS
|
|
582
|
+
// selects the littlefs backend but NOT FLASH/FLASH_MAP (the partition lookup
|
|
583
|
+
// needs them), so all three are set explicitly — same shape as the
|
|
584
|
+
// preferences/ZMS block. The overlay points the storage_partition at the FS
|
|
585
|
+
// (see dt-config/overlay.ts). NOTE: a program using BOTH fs.* and
|
|
586
|
+
// preferences.* shares the one storage_partition between littlefs and ZMS —
|
|
587
|
+
// dedicate separate partitions if both are needed (the manifest flags this).
|
|
588
|
+
if (usage.usesFS) {
|
|
589
|
+
m.set('CONFIG_FLASH', 'y');
|
|
590
|
+
m.set('CONFIG_FLASH_MAP', 'y');
|
|
591
|
+
m.set('CONFIG_FILE_SYSTEM', 'y');
|
|
592
|
+
m.set('CONFIG_FILE_SYSTEM_LITTLEFS', 'y');
|
|
593
|
+
// fs_mkfs (the lazy first-use format in the shim) is gated behind this —
|
|
594
|
+
// without it the mount path links fine but the format call is undefined.
|
|
595
|
+
m.set('CONFIG_FILE_SYSTEM_MKFS', 'y');
|
|
596
|
+
}
|
|
597
|
+
// usesUart: the board enables the console UART by default; the overlay (not
|
|
598
|
+
// Kconfig) is where a UART node would be enabled, so no symbol here.
|
|
599
|
+
// Random: <zephyr/random/random.h> sys_rand_get is backed by the random
|
|
600
|
+
// generator subsystem's RNG_GENERATOR_CHOICE. There is no umbrella symbol —
|
|
601
|
+
// CONFIG_RANDOM_GENERATOR is a phantom in 4.x (assigning an undefined symbol
|
|
602
|
+
// aborts the build). The choice defaults to the entropy-device generator
|
|
603
|
+
// when the board has a driver (ENTROPY_HAS_DRIVER: nRF52840, ESP32, …);
|
|
604
|
+
// RNG-less SoCs (STM32F411 has no hardware RNG) need
|
|
605
|
+
// CONFIG_TEST_RANDOM_GENERATOR to unlock the timer-clock fallback, which
|
|
606
|
+
// the choice then picks by default. Setting both keys gets the best
|
|
607
|
+
// available source per board.
|
|
608
|
+
if (usage.usesRandom) {
|
|
609
|
+
m.set('CONFIG_ENTROPY_GENERATOR', 'y');
|
|
610
|
+
m.set('CONFIG_TEST_RANDOM_GENERATOR', 'y');
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// System workqueue — bumped for worker-offload AND timer callbacks. The
|
|
614
|
+
// workqueue itself is unconditionally built (no CONFIG_SYSTEM_WORKQUEUE symbol
|
|
615
|
+
// exists in Zephyr — that was a phantom that broke real builds); only the
|
|
616
|
+
// stack size is a real Kconfig knob.
|
|
617
|
+
m.set('CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE', '8192');
|
|
618
|
+
|
|
619
|
+
// C++ support.
|
|
620
|
+
m.set('CONFIG_CPP', 'y');
|
|
621
|
+
m.set('CONFIG_NEWLIB_LIBC', 'y');
|
|
622
|
+
m.set('CONFIG_REQUIRES_FULL_LIBCPP', 'y');
|
|
623
|
+
m.set('CONFIG_STD_CPP14', 'y');
|
|
624
|
+
|
|
625
|
+
// Main thread stack. WiFi already bumps this to 5200 (esp_wifi device init
|
|
626
|
+
// is stack-hungry); HTTP/MQTT + TLS also bump it (the mbedTLS handshake is
|
|
627
|
+
// stack-hungry). The UI runtime (ui_tick) renders a large node tree with AA
|
|
628
|
+
// text + canvas compositing per frame, so 4096 is marginal headroom and we
|
|
629
|
+
// bump to 8192 for displays. NOTE: a Zephyr panic dump that prints
|
|
630
|
+
// `EXCCAUSE 63` is NOT necessarily a stack overflow — on the Zephyr Xtensa
|
|
631
|
+
// port EXCCAUSE 63 is the reserved software-exception used for k_oops/abort,
|
|
632
|
+
// and the ESP32 port reaches it via abort() in intc_esp32.c (the
|
|
633
|
+
// esp_intr_noniram_disable/enable unbalanced-flag guards). Resolve the dump's
|
|
634
|
+
// PC against the .elf (xtensa_arch_except → abort) before treating it as a
|
|
635
|
+
// stack overflow; 8192 is kept here because deep ui_tick call nesting still
|
|
636
|
+
// wants the headroom.
|
|
637
|
+
if (!usage.usesWifi && !usage.usesHttp && !usage.usesMqtt) {
|
|
638
|
+
m.set('CONFIG_MAIN_STACK_SIZE', usage.usesDisplay ? '8192' : '4096');
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
if (debug) {
|
|
642
|
+
m.set('CONFIG_DEBUG', 'y');
|
|
643
|
+
m.set('CONFIG_DEBUG_OPTIMIZATIONS', 'y');
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
return m;
|
|
647
|
+
}
|