@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.
Files changed (191) hide show
  1. package/README.md +22 -35
  2. package/dist/as-built.d.ts +33 -0
  3. package/dist/as-built.js +188 -0
  4. package/dist/async/timer-polyfill.js +1 -1
  5. package/dist/boardgen.d.ts +128 -0
  6. package/dist/boardgen.js +1366 -0
  7. package/dist/chips/board-overrides.d.ts +7 -0
  8. package/dist/chips/board-overrides.js +11 -0
  9. package/dist/chips/controllers.d.ts +28 -8
  10. package/dist/chips/controllers.js +49 -12
  11. package/dist/chips/esp32s3.js +49 -0
  12. package/dist/chips/index.d.ts +6 -12
  13. package/dist/chips/index.js +18 -34
  14. package/dist/chips/resolve.d.ts +16 -2
  15. package/dist/chips/resolve.js +298 -15
  16. package/dist/chips/soc/.d.ts +2 -0
  17. package/dist/chips/soc/.js +129 -0
  18. package/dist/chips/soc/esp32.d.ts +2 -0
  19. package/dist/chips/soc/esp32.js +120 -0
  20. package/dist/chips/soc/esp32c3.d.ts +2 -0
  21. package/dist/chips/soc/esp32c3.js +90 -0
  22. package/dist/chips/soc/esp32c6.d.ts +2 -0
  23. package/dist/chips/soc/esp32c6.js +109 -0
  24. package/dist/chips/soc/esp32s3.d.ts +2 -0
  25. package/dist/chips/soc/esp32s3.js +189 -0
  26. package/dist/chips/soc/index.d.ts +2 -0
  27. package/dist/chips/soc/index.js +23 -0
  28. package/dist/chips/soc/nrf52840.d.ts +2 -0
  29. package/dist/chips/soc/nrf52840.js +130 -0
  30. package/dist/chips/soc/rp2040.d.ts +2 -0
  31. package/dist/chips/soc/rp2040.js +141 -0
  32. package/dist/chips/soc/rp2350a.d.ts +2 -0
  33. package/dist/chips/soc/rp2350a.js +145 -0
  34. package/dist/chips/soc/samd21g18a.d.ts +2 -0
  35. package/dist/chips/soc/samd21g18a.js +143 -0
  36. package/dist/chips/soc/stm32f411xe.d.ts +2 -0
  37. package/dist/chips/soc/stm32f411xe.js +251 -0
  38. package/dist/chips/types.d.ts +382 -12
  39. package/dist/chips/xiao-ble.js +33 -0
  40. package/dist/display/profiles.js +1 -1
  41. package/dist/doctor.js +38 -4
  42. package/dist/dt-config/custom-board.d.ts +23 -0
  43. package/dist/dt-config/custom-board.js +227 -0
  44. package/dist/dt-config/kconfig.d.ts +83 -1
  45. package/dist/dt-config/kconfig.js +116 -27
  46. package/dist/dt-config/overlay.js +623 -18
  47. package/dist/framework.manifest.d.ts +20 -30
  48. package/dist/framework.manifest.js +124 -178
  49. package/dist/index.d.ts +4 -1
  50. package/dist/index.js +8 -2
  51. package/dist/lowering/adc.d.ts +26 -5
  52. package/dist/lowering/adc.js +137 -31
  53. package/dist/lowering/ble.js +31 -28
  54. package/dist/lowering/dac.js +9 -9
  55. package/dist/lowering/fs.js +18 -10
  56. package/dist/lowering/gpio.d.ts +2 -0
  57. package/dist/lowering/gpio.js +90 -10
  58. package/dist/lowering/http.js +39 -14
  59. package/dist/lowering/hwtimer.d.ts +4 -0
  60. package/dist/lowering/hwtimer.js +35 -10
  61. package/dist/lowering/i2c.js +46 -54
  62. package/dist/lowering/index.d.ts +5 -5
  63. package/dist/lowering/index.js +15 -16
  64. package/dist/lowering/interrupts.d.ts +22 -5
  65. package/dist/lowering/interrupts.js +104 -22
  66. package/dist/lowering/mqtt.js +12 -6
  67. package/dist/lowering/power.js +0 -4
  68. package/dist/lowering/preferences.js +49 -77
  69. package/dist/lowering/pulse.js +5 -36
  70. package/dist/lowering/pwm.d.ts +32 -3
  71. package/dist/lowering/pwm.js +105 -17
  72. package/dist/lowering/random.js +3 -3
  73. package/dist/lowering/sensor.d.ts +37 -0
  74. package/dist/lowering/sensor.js +119 -0
  75. package/dist/lowering/spi.d.ts +12 -0
  76. package/dist/lowering/spi.js +65 -40
  77. package/dist/lowering/thread.d.ts +14 -0
  78. package/dist/lowering/thread.js +55 -0
  79. package/dist/lowering/timing.js +20 -46
  80. package/dist/lowering/tone.js +18 -5
  81. package/dist/lowering/uart.d.ts +13 -0
  82. package/dist/lowering/uart.js +72 -51
  83. package/dist/lowering/usb.d.ts +34 -0
  84. package/dist/lowering/usb.js +206 -0
  85. package/dist/lowering/wdt.d.ts +1 -1
  86. package/dist/lowering/wdt.js +17 -7
  87. package/dist/lowering/wifi.d.ts +3 -2
  88. package/dist/lowering/wifi.js +120 -111
  89. package/dist/sdk/board-catalog-sync.d.ts +16 -0
  90. package/dist/sdk/board-catalog-sync.js +41 -0
  91. package/dist/sdk/board-data.generated.d.ts +2 -0
  92. package/dist/sdk/board-data.generated.js +4 -0
  93. package/dist/sdk/catalog-walker.d.ts +90 -0
  94. package/dist/sdk/catalog-walker.js +682 -0
  95. package/dist/sdk/dts-reader.d.ts +83 -0
  96. package/dist/sdk/dts-reader.js +596 -0
  97. package/dist/strategy.d.ts +136 -17
  98. package/dist/strategy.js +881 -212
  99. package/dist/toolchain/bossac-touch.d.ts +18 -0
  100. package/dist/toolchain/bossac-touch.js +88 -0
  101. package/dist/toolchain/compat.d.ts +2 -2
  102. package/dist/toolchain/compat.js +8 -3
  103. package/dist/toolchain/debug-config.d.ts +21 -26
  104. package/dist/toolchain/debug-config.js +212 -72
  105. package/dist/toolchain/env-check.d.ts +4 -4
  106. package/dist/toolchain/env-check.js +5 -5
  107. package/dist/toolchain/index.d.ts +66 -1
  108. package/dist/toolchain/index.js +713 -58
  109. package/dist/toolchain/scaffold.d.ts +9 -0
  110. package/dist/toolchain/scaffold.js +84 -7
  111. package/dist/toolchain/west-discover.d.ts +8 -1
  112. package/dist/toolchain/west-discover.js +19 -6
  113. package/dist/toolchain/west-spawn.js +17 -5
  114. package/installer/CHANGELOG.md +473 -0
  115. package/installer/README.md +328 -0
  116. package/installer/environment.yml +46 -0
  117. package/installer/etc/conda/activate.d/zephyr.bat +7 -0
  118. package/installer/etc/conda/activate.d/zephyr.ps1 +12 -0
  119. package/installer/etc/conda/activate.d/zephyr.sh +20 -0
  120. package/installer/etc/conda/deactivate.d/zephyr.bat +6 -0
  121. package/installer/etc/conda/deactivate.d/zephyr.ps1 +6 -0
  122. package/installer/etc/conda/deactivate.d/zephyr.sh +4 -0
  123. package/installer/install.mjs +580 -0
  124. package/installer/install.ps1 +619 -0
  125. package/installer/install.sh +310 -0
  126. package/installer/lib/detect-platform.sh +62 -0
  127. package/installer/lib/fetch-sdk.sh +304 -0
  128. package/installer/lib/init-workspace.sh +153 -0
  129. package/installer/lib/write-activation.sh +76 -0
  130. package/installer/patches/tfm-c-include-separators.patch +19 -0
  131. package/installer/patches/zephyr-tfm-nordic-zephyr-include.patch +24 -0
  132. package/installer/templates/project/.typecad/activate-zephyr.ps1 +31 -0
  133. package/installer/templates/project/.typecad/activate-zephyr.sh +31 -0
  134. package/installer/templates/project/.vscode/settings.json +30 -0
  135. package/installer/templates/project/README.md +58 -0
  136. package/installer/versions.env +110 -0
  137. package/package.json +16 -16
  138. package/src/as-built.ts +206 -0
  139. package/src/boardgen.ts +1428 -0
  140. package/src/chips/controllers.ts +61 -12
  141. package/src/chips/index.ts +35 -54
  142. package/src/chips/resolve.ts +316 -14
  143. package/src/chips/types.ts +388 -13
  144. package/src/display/profiles.ts +1 -1
  145. package/src/doctor.ts +110 -77
  146. package/src/dt-config/custom-board.ts +325 -0
  147. package/src/dt-config/kconfig.ts +177 -19
  148. package/src/dt-config/overlay.ts +1058 -450
  149. package/src/framework.manifest.ts +125 -178
  150. package/src/index.ts +57 -41
  151. package/src/lowering/adc.ts +222 -102
  152. package/src/lowering/ble.ts +32 -28
  153. package/src/lowering/dac.ts +82 -82
  154. package/src/lowering/fs.ts +18 -10
  155. package/src/lowering/gpio.ts +242 -152
  156. package/src/lowering/http.ts +512 -488
  157. package/src/lowering/hwtimer.ts +139 -101
  158. package/src/lowering/i2c.ts +116 -126
  159. package/src/lowering/index.ts +91 -93
  160. package/src/lowering/interrupts.ts +113 -21
  161. package/src/lowering/mqtt.ts +12 -6
  162. package/src/lowering/preferences.ts +327 -354
  163. package/src/lowering/pwm.ts +167 -74
  164. package/src/lowering/random.ts +3 -3
  165. package/src/lowering/sensor.ts +155 -0
  166. package/src/lowering/spi.ts +164 -124
  167. package/src/lowering/thread.ts +63 -0
  168. package/src/lowering/timing.ts +46 -72
  169. package/src/lowering/uart.ts +73 -51
  170. package/src/lowering/usb.ts +221 -0
  171. package/src/lowering/wdt.ts +95 -84
  172. package/src/lowering/wifi.ts +120 -111
  173. package/src/sdk/board-catalog-sync.ts +62 -0
  174. package/src/strategy.ts +888 -229
  175. package/src/toolchain/bossac-touch.ts +112 -0
  176. package/src/toolchain/compat.ts +8 -3
  177. package/src/toolchain/debug-config.ts +666 -522
  178. package/src/toolchain/env-check.ts +9 -9
  179. package/src/toolchain/index.ts +765 -44
  180. package/src/toolchain/scaffold.ts +81 -7
  181. package/src/toolchain/west-discover.ts +334 -316
  182. package/src/toolchain/west-spawn.ts +17 -5
  183. package/src/async/timer-polyfill.ts +0 -107
  184. package/src/chips/esp32.ts +0 -74
  185. package/src/chips/esp32s3.ts +0 -57
  186. package/src/chips/xiao-ble.ts +0 -70
  187. package/src/lowering/power.ts +0 -70
  188. package/src/lowering/pulse.ts +0 -93
  189. package/src/lowering/tone.ts +0 -60
  190. package/src/lowering/worker-backing.ts +0 -94
  191. package/src/lowering/worker.ts +0 -17
@@ -7,9 +7,9 @@
7
7
  // (from the MCU package's zephyr field) with board-level overrides (from the
8
8
  // board package's zephyr field).
9
9
  //
10
- // When a board package carries Zephyr config, this path replaces the
11
- // hardcoded chip descriptor registry. When it doesn't (legacy), chipForTarget
12
- // still works as the fallback.
10
+ // This is the ONE resolution path: every board's chip view reconstructs
11
+ // from its generated manifest there is no curated registry to fall back
12
+ // to.
13
13
  // ---------------------------------------------------------------------------
14
14
  /** Collect an indexed array of objects reconstructed from flat dot-path keys. */
15
15
  function collectIndexed(bc, prefix, build) {
@@ -34,23 +34,64 @@ function collectIndexed(bc, prefix, build) {
34
34
  function collectBusControllers(bc, prefix) {
35
35
  return collectIndexed(bc, prefix, (m, i) => {
36
36
  const nodeLabel = m.get(`${prefix}.${i}.nodeLabel`);
37
- return nodeLabel ? { nodeLabel } : null;
37
+ if (!nodeLabel)
38
+ return null;
39
+ // Optional pinctrl synthesis data (nested object; string arrays arrive
40
+ // comma-joined from the board-constants flattener).
41
+ const splitCsv = (v) => typeof v === 'string' && v.length > 0
42
+ ? v.split(',').map((s) => s.trim()).filter(Boolean)
43
+ : undefined;
44
+ const include = m.get(`${prefix}.${i}.pinctrl.include`);
45
+ const pinmux = splitCsv(m.get(`${prefix}.${i}.pinctrl.pinmux`));
46
+ const inputPinmux = splitCsv(m.get(`${prefix}.${i}.pinctrl.inputPinmux`));
47
+ const defines = splitCsv(m.get(`${prefix}.${i}.pinctrl.defines`));
48
+ const pinctrlRef = m.get(`${prefix}.${i}.pinctrlRef`);
49
+ const props = splitCsv(m.get(`${prefix}.${i}.props`));
50
+ return {
51
+ nodeLabel,
52
+ ...(include && pinmux
53
+ ? {
54
+ pinctrl: {
55
+ include,
56
+ pinmux,
57
+ ...(inputPinmux ? { inputPinmux } : {}),
58
+ ...(defines ? { defines } : {}),
59
+ },
60
+ }
61
+ : {}),
62
+ ...(pinctrlRef ? { pinctrlRef } : {}),
63
+ ...(props ? { props } : {}),
64
+ };
38
65
  });
39
66
  }
40
67
  /**
41
68
  * Try to derive a ZephyrChipDescriptor from board/MCU package constants.
42
69
  *
43
70
  * Returns null when no zephyr info is available in the board constants
44
- * (the caller should fall back to the hardcoded chipForTarget registry).
71
+ * (the caller should treat the board as unresolved NO_BOARD_CHIP).
45
72
  */
46
73
  export function resolveChipFromBoard(bc) {
47
74
  if (!bc)
48
75
  return null;
49
76
  const boardTarget = bc.get('build.frameworks.zephyr');
50
- if (!boardTarget)
77
+ // MCU-silicon entry: an MCU-only config (no board package) carries the
78
+ // chip facts under zephyr.* without any build.frameworks target (the
79
+ // build target comes from frameworkData instead — a custom board name).
80
+ const socsRaw = bc.get('zephyr.socs');
81
+ if (!boardTarget && !socsRaw)
51
82
  return null;
83
+ const socs = typeof socsRaw === 'string' && socsRaw.length > 0
84
+ ? socsRaw.split(',').map((s) => s.trim()).filter(Boolean)
85
+ : [];
86
+ // Chip identity: the board target when a board resolved it, else the SoC
87
+ // (an MCU-only chip — its "board" is the generated custom board).
88
+ const id = boardTarget ?? socs[0] ?? 'custom';
52
89
  const zGpioController = bc.get('zephyr.gpioController');
53
- const soc = bc.get('mcu.id') ?? '';
90
+ // The soc name: MCU packages key it under mcu.id; generated board
91
+ // manifests carry it as the second segment of the qualified target.
92
+ const soc = bc.get('mcu.id')
93
+ ?? (socs.length > 0 ? socs[0] : undefined)
94
+ ?? (boardTarget && boardTarget.includes('/') ? boardTarget.split('/')[1] : '');
54
95
  // ── Build mutable sub-objects, then construct the final descriptor ──────
55
96
  const gc = collectIndexed(bc, 'zephyr.gpioControllers', (m, i) => {
56
97
  const nodelabel = m.get(`zephyr.gpioControllers.${i}.nodelabel`);
@@ -81,29 +122,177 @@ export function resolveChipFromBoard(bc) {
81
122
  const pwmSpecs = collectIndexed(bc, 'zephyr.pwm.specs', (m, i) => {
82
123
  const pin = m.get(`zephyr.pwm.specs.${i}.pin`);
83
124
  const dtSpec = m.get(`zephyr.pwm.specs.${i}.dtSpec`);
84
- if (pin != null && dtSpec)
85
- return { pin, dtSpec };
86
- return null;
125
+ const controller = m.get(`zephyr.pwm.specs.${i}.controller`);
126
+ const channel = m.get(`zephyr.pwm.specs.${i}.channel`);
127
+ const periodNs = m.get(`zephyr.pwm.specs.${i}.periodNs`);
128
+ const polarity = m.get(`zephyr.pwm.specs.${i}.polarity`);
129
+ const pinctrl = m.get(`zephyr.pwm.specs.${i}.pinctrl`);
130
+ // Board-shipped alias form (dtSpec) or synthesized form (controller +
131
+ // channel → overlay-generated alias) — at least one, else drop the entry.
132
+ if (pin == null || !(dtSpec || (controller && channel != null)))
133
+ return null;
134
+ return {
135
+ pin,
136
+ ...(dtSpec ? { dtSpec } : {}),
137
+ ...(controller ? { controller } : {}),
138
+ ...(channel != null ? { channel } : {}),
139
+ ...(periodNs != null ? { periodNs } : {}),
140
+ ...(polarity ? { polarity } : {}),
141
+ ...(pinctrl ? { pinctrl } : {}),
142
+ };
87
143
  });
88
144
  const adcNodeLabel = bc.get('zephyr.adc.nodeLabel');
145
+ // PWM timer input clock — feeds the overlay's 16-bit prescaler derivation.
146
+ const pwmClockHz = bc.get('zephyr.pwm.clockHz');
147
+ // PWM matrix (ESP32 LEDC): any listed pin can carry any channel; channels
148
+ // are assigned to the driven pins at build time (dt-config/overlay.ts).
149
+ const matrixController = bc.get('zephyr.pwm.matrix.controller');
150
+ const matrixChannelCount = bc.get('zephyr.pwm.matrix.channelCount');
151
+ const matrixPins = collectIndexed(bc, 'zephyr.pwm.matrix.pins', (m, i) => m.get(`zephyr.pwm.matrix.pins.${i}`) ?? null);
152
+ const pwmMatrix = matrixController && matrixChannelCount
153
+ ? { controller: matrixController, channelCount: matrixChannelCount, pins: matrixPins }
154
+ : undefined;
89
155
  const adcResolution = bc.get('zephyr.adc.resolution');
90
156
  const adcVref = bc.get('zephyr.adc.vrefMv');
157
+ const adcGain = bc.get('zephyr.adc.gain');
158
+ const adcReference = bc.get('zephyr.adc.reference');
91
159
  const adcChannels = collectIndexed(bc, 'zephyr.adc.channels', (m, i) => {
92
160
  const pin = m.get(`zephyr.adc.channels.${i}.pin`);
93
161
  const channel = m.get(`zephyr.adc.channels.${i}.channel`);
94
- if (pin != null && channel != null)
95
- return { pin, channel };
162
+ const pinctrl = m.get(`zephyr.adc.channels.${i}.pinctrl`);
163
+ const controller = m.get(`zephyr.adc.channels.${i}.controller`);
164
+ if (pin != null && channel != null) {
165
+ return { pin, channel, ...(pinctrl ? { pinctrl } : {}), ...(controller ? { controller } : {}) };
166
+ }
167
+ return null;
168
+ });
169
+ const dacDevice = bc.get('zephyr.dac.device');
170
+ const dacChannels = collectIndexed(bc, 'zephyr.dac.channels', (m, i) => {
171
+ const pin = m.get(`zephyr.dac.channels.${i}.pin`);
172
+ const channel = m.get(`zephyr.dac.channels.${i}.channel`);
173
+ const resolution = m.get(`zephyr.dac.channels.${i}.resolution`);
174
+ if (pin != null && channel != null) {
175
+ return { pin, channel, resolution: resolution ?? 12 };
176
+ }
96
177
  return null;
97
178
  });
98
179
  const wdtNodeLabel = bc.get('zephyr.wdt.nodeLabel');
180
+ // Hardware counters (Zephyr counter devices): nodeLabel always; the child
181
+ // form carries the timer parent the overlay attaches the (label-less)
182
+ // counter child to.
183
+ const hwtimerControllers = collectIndexed(bc, 'zephyr.hwtimer.controllers', (m, i) => {
184
+ const nodeLabel = m.get(`zephyr.hwtimer.controllers.${i}.nodeLabel`);
185
+ const counterParent = m.get(`zephyr.hwtimer.controllers.${i}.counterParent`);
186
+ if (!nodeLabel)
187
+ return null;
188
+ return { nodeLabel, ...(counterParent ? { counterParent } : {}) };
189
+ });
190
+ // Storage partition synthesis (boards whose DTS ships no storage_partition
191
+ // — see ZephyrChipDescriptor.storage).
192
+ const storageOffset = bc.get('zephyr.storage.offset');
193
+ const storageSize = bc.get('zephyr.storage.size');
194
+ const storagePreexisting = bc.get('zephyr.storage.preexisting');
195
+ // USB device (CDC-ACM): zephyr.usb.controller + zephyr.usb.cdcInstances
196
+ // (+ optional vid/pid for the device descriptor).
197
+ const usbController = bc.get('zephyr.usb.controller');
198
+ const usbCdcInstances = bc.get('zephyr.usb.cdcInstances');
199
+ const usbVid = bc.get('zephyr.usb.vid');
200
+ const usbPid = bc.get('zephyr.usb.pid');
201
+ // Optional 1200-baud touch-to-reset data (BOSSA-bootloader boards).
202
+ const trFlag = bc.get('zephyr.usb.touchReset.flagAddress');
203
+ const trMagic = bc.get('zephyr.usb.touchReset.magic');
204
+ const trVid = bc.get('zephyr.usb.touchReset.bootloaderVid');
205
+ const trPid = bc.get('zephyr.usb.touchReset.bootloaderPid');
206
+ const probeMethods = collectIndexed(bc, 'zephyr.probeMethods', (m, i) => {
207
+ const id = m.get(`zephyr.probeMethods.${i}.id`);
208
+ const runner = m.get(`zephyr.probeMethods.${i}.runner`);
209
+ if (!id || !runner)
210
+ return null;
211
+ const argsRaw = m.get(`zephyr.probeMethods.${i}.args`);
212
+ const description = m.get(`zephyr.probeMethods.${i}.description`);
213
+ const debugRaw = m.get(`zephyr.probeMethods.${i}.debug`);
214
+ const debugInterface = m.get(`zephyr.probeMethods.${i}.debugInterface`);
215
+ const debugDevice = m.get(`zephyr.probeMethods.${i}.debugDevice`);
216
+ const debugCfgRaw = m.get(`zephyr.probeMethods.${i}.debugCfg`);
217
+ const debugCfgSourceRaw = m.get(`zephyr.probeMethods.${i}.debugCfgSource`);
218
+ // Args are comma-joined (west flags never carry commas); cfg lines are
219
+ // newline-joined (tcl legally contains commas).
220
+ const split = (v) => typeof v === 'string' && v.length > 0 ? v.split(',') : undefined;
221
+ const splitLines = (v) => typeof v === 'string' && v.length > 0 ? v.split('\n') : undefined;
222
+ const args = split(argsRaw);
223
+ return {
224
+ id,
225
+ runner,
226
+ ...(args ? { args } : {}),
227
+ ...(description ? { description } : {}),
228
+ ...(debugRaw !== undefined ? { debug: debugRaw } : {}),
229
+ ...(debugInterface ? { debugInterface: debugInterface } : {}),
230
+ ...(debugDevice ? { debugDevice } : {}),
231
+ ...(split(debugCfgRaw) ? { debugCfg: splitLines(debugCfgRaw) } : {}),
232
+ ...(split(debugCfgSourceRaw) ? { debugCfgSource: splitLines(debugCfgSourceRaw) } : {}),
233
+ };
234
+ });
99
235
  const wifiSupported = bc.get('zephyr.wifi.supported');
236
+ // ── Custom-board generator inputs (MCU silicon) ─────────────────────────
237
+ // Only complete when the MCU package carried a default console + clock
238
+ // plan — without those there is nothing to generate a board from.
239
+ const consoleNodeLabel = bc.get('zephyr.console.nodeLabel');
240
+ const consoleTx = bc.get('zephyr.console.tx');
241
+ const consoleRx = bc.get('zephyr.console.rx');
242
+ const consoleSpeed = bc.get('zephyr.console.speed');
243
+ const hseMHz = bc.get('zephyr.clocks.hseMHz');
244
+ const pllDivM = bc.get('zephyr.clocks.pll.divM');
245
+ const pllMulN = bc.get('zephyr.clocks.pll.mulN');
246
+ const pllDivP = bc.get('zephyr.clocks.pll.divP');
247
+ const pllDivQ = bc.get('zephyr.clocks.pll.divQ');
248
+ const sysMHz = bc.get('zephyr.clocks.sysMHz');
249
+ const dtsIncludesRaw = bc.get('zephyr.dtsIncludes');
250
+ const usbNode = bc.get('zephyr.usb.usbNode');
251
+ const usbPinctrlRaw = bc.get('zephyr.usb.pinctrl');
252
+ const usbPinctrl = typeof usbPinctrlRaw === 'string' && usbPinctrlRaw.length > 0
253
+ ? usbPinctrlRaw.split(',').map((s) => s.trim()).filter(Boolean)
254
+ : undefined;
255
+ const cbAdcNodeLabel = bc.get('zephyr.adcNode.nodeLabel');
256
+ const cbAdcClockSource = bc.get('zephyr.adcNode.clockSource');
257
+ const cbAdcPrescaler = bc.get('zephyr.adcNode.prescaler');
258
+ const cbAdcPinctrl = bc.get('zephyr.adcNode.pinctrl');
259
+ const customBoard = socs.length > 0 &&
260
+ consoleNodeLabel && consoleTx && consoleRx &&
261
+ hseMHz != null && pllDivM != null && pllMulN != null && pllDivP != null &&
262
+ pllDivQ != null && sysMHz != null
263
+ ? {
264
+ socs,
265
+ dtsIncludes: typeof dtsIncludesRaw === 'string' && dtsIncludesRaw.length > 0
266
+ ? dtsIncludesRaw.split(',').map((s) => s.trim()).filter(Boolean)
267
+ : [],
268
+ console: {
269
+ nodeLabel: consoleNodeLabel,
270
+ tx: consoleTx,
271
+ rx: consoleRx,
272
+ speed: consoleSpeed ?? 115200,
273
+ },
274
+ clocks: {
275
+ hseMHz,
276
+ pll: { divM: pllDivM, mulN: pllMulN, divP: pllDivP, divQ: pllDivQ },
277
+ sysMHz,
278
+ ahbPrescaler: bc.get('zephyr.clocks.ahbPrescaler') ?? 1,
279
+ apb1Prescaler: bc.get('zephyr.clocks.apb1Prescaler') ?? 1,
280
+ apb2Prescaler: bc.get('zephyr.clocks.apb2Prescaler') ?? 1,
281
+ },
282
+ ...(usbNode ? { usbNode } : {}),
283
+ ...(usbPinctrl ? { usbPinctrl } : {}),
284
+ ...(cbAdcNodeLabel && cbAdcClockSource && cbAdcPrescaler != null && cbAdcPinctrl
285
+ ? { adcNode: { nodeLabel: cbAdcNodeLabel, clockSource: cbAdcClockSource, prescaler: cbAdcPrescaler, pinctrl: cbAdcPinctrl } }
286
+ : {}),
287
+ }
288
+ : undefined;
100
289
  // ── Construct the final readonly descriptor ─────────────────────────────
101
290
  const gpio = {
102
291
  dtSpecs,
103
292
  ...(intPins.length > 0 ? { interruptPins: intPins } : {}),
104
293
  };
105
294
  return {
106
- id: boardTarget,
295
+ id,
107
296
  soc,
108
297
  gpioController: zGpioController ?? 'gpio0',
109
298
  ...(gc.length > 0 ? { gpioControllers: gc } : {}),
@@ -111,11 +300,105 @@ export function resolveChipFromBoard(bc) {
111
300
  ...(i2cControllers.length > 0 ? { i2c: { controllers: i2cControllers } } : {}),
112
301
  ...(spiControllers.length > 0 ? { spi: { controllers: spiControllers } } : {}),
113
302
  ...(uartControllers.length > 0 ? { uart: { controllers: uartControllers } } : {}),
114
- ...(pwmSpecs.length > 0 ? { pwm: { specs: pwmSpecs } } : {}),
303
+ ...(pwmSpecs.length > 0 || pwmMatrix
304
+ ? {
305
+ pwm: {
306
+ specs: pwmSpecs,
307
+ ...(pwmMatrix ? { matrix: pwmMatrix } : {}),
308
+ ...(pwmClockHz ? { clockHz: pwmClockHz } : {}),
309
+ },
310
+ }
311
+ : {}),
115
312
  ...(adcNodeLabel || adcResolution != null || adcVref != null || adcChannels.length > 0
116
- ? { adc: { nodeLabel: adcNodeLabel ?? 'adc', resolution: adcResolution ?? 12, vrefMv: adcVref ?? 3000, channels: adcChannels } }
313
+ ? {
314
+ adc: {
315
+ nodeLabel: adcNodeLabel ?? 'adc',
316
+ resolution: adcResolution ?? 12,
317
+ vrefMv: adcVref ?? 3000,
318
+ channels: adcChannels,
319
+ ...(adcGain ? { gain: adcGain } : {}),
320
+ ...(adcReference ? { reference: adcReference } : {}),
321
+ },
322
+ }
117
323
  : {}),
324
+ ...(dacDevice && dacChannels.length > 0 ? { dac: { device: dacDevice, channels: dacChannels } } : {}),
118
325
  ...(wdtNodeLabel ? { wdt: { nodeLabel: wdtNodeLabel } } : {}),
326
+ ...(hwtimerControllers.length > 0 ? { hwtimer: { controllers: hwtimerControllers } } : {}),
327
+ ...(storageOffset != null && storageSize != null
328
+ ? { storage: { offset: storageOffset, size: storageSize, ...(storagePreexisting ? { preexisting: true } : {}) } }
329
+ : {}),
330
+ ...(usbController && usbCdcInstances && usbCdcInstances > 0
331
+ ? {
332
+ usb: {
333
+ controller: usbController,
334
+ cdcInstances: usbCdcInstances,
335
+ ...(usbVid ? { vid: usbVid } : {}),
336
+ ...(usbPid ? { pid: usbPid } : {}),
337
+ ...(trFlag != null && trMagic != null
338
+ ? {
339
+ touchReset: {
340
+ flagAddress: trFlag,
341
+ magic: trMagic,
342
+ ...(trVid ? { bootloaderVid: trVid } : {}),
343
+ ...(trPid ? { bootloaderPid: trPid } : {}),
344
+ },
345
+ }
346
+ : {}),
347
+ },
348
+ }
349
+ : {}),
119
350
  ...(wifiSupported ? { wifi: { supported: true } } : {}),
351
+ ...(probeMethods.length > 0 ? { probeMethods } : {}),
352
+ ...(customBoard ? { customBoard } : {}),
353
+ };
354
+ }
355
+ /**
356
+ * Board-level PWM specs from the generated board manifest (zephyr.pwm.specs.*
357
+ * — the pwm-leds facts boardgen emits on virtual pins 8192+). The active
358
+ * chip's spec table is silicon-curated; these JOIN it (see mergeBoardPwmSpecs)
359
+ * so a board's own devicetree-aliased PWM LED is addressable without curation.
360
+ */
361
+ export function boardPwmSpecsFromConstants(bc) {
362
+ if (!bc)
363
+ return [];
364
+ const specs = [];
365
+ for (let i = 0; i < 256; i++) {
366
+ const pin = bc.get(`zephyr.pwm.specs.${i}.pin`);
367
+ if (pin == null)
368
+ break;
369
+ const dtSpec = bc.get(`zephyr.pwm.specs.${i}.dtSpec`);
370
+ const controller = bc.get(`zephyr.pwm.specs.${i}.controller`);
371
+ const channel = bc.get(`zephyr.pwm.specs.${i}.channel`);
372
+ if (!(dtSpec || (controller && channel != null)))
373
+ continue;
374
+ specs.push({
375
+ pin,
376
+ ...(dtSpec ? { dtSpec } : {}),
377
+ ...(controller ? { controller } : {}),
378
+ ...(channel != null ? { channel } : {}),
379
+ });
380
+ }
381
+ return specs;
382
+ }
383
+ /**
384
+ * Merge board-level PWM specs into a chip descriptor. Collision rule: a
385
+ * board spec whose pin OR dtSpec already exists in the chip's table is
386
+ * dropped (the curated entry wins — e.g. the XIAO's hand-tuned pwm-led0
387
+ * spec). Returns the chip unchanged when nothing joins.
388
+ */
389
+ export function mergeBoardPwmSpecs(chip, boardSpecs) {
390
+ if (boardSpecs.length === 0)
391
+ return chip;
392
+ const existing = chip.pwm?.specs ?? [];
393
+ const joining = boardSpecs.filter((s) => !existing.some((e) => e.pin === s.pin || (s.dtSpec != null && e.dtSpec === s.dtSpec)));
394
+ if (joining.length === 0)
395
+ return chip;
396
+ return {
397
+ ...chip,
398
+ pwm: {
399
+ specs: [...existing, ...joining],
400
+ ...(chip.pwm?.matrix ? { matrix: chip.pwm.matrix } : {}),
401
+ ...(chip.pwm?.clockHz ? { clockHz: chip.pwm.clockHz } : {}),
402
+ },
120
403
  };
121
404
  }
@@ -0,0 +1,2 @@
1
+ import type { ZephyrChipDescriptor } from '../types.js';
2
+ export declare const _SOC: ZephyrChipDescriptor;
@@ -0,0 +1,129 @@
1
+ // GENERATED by scripts/gen-soc-descriptors.mjs — consolidated from the
2
+ // board-xiao-nrf52840 + mcu-nrf52840 package data (the exact flatten+reconstruct the build
3
+ // performed). Curated additions: tier/pinNaming/excludedPins. Regenerate
4
+ // only alongside a descriptor-type change; hand-edit the curated table in
5
+ // the script, not this file.
6
+ export const _SOC = {
7
+ "id": "xiao_ble/nrf52840",
8
+ "soc": "",
9
+ "gpioController": "gpio0",
10
+ "gpioControllers": [
11
+ {
12
+ "nodelabel": "gpio0",
13
+ "minPin": 0,
14
+ "maxPin": 31
15
+ },
16
+ {
17
+ "nodelabel": "gpio1",
18
+ "minPin": 32,
19
+ "maxPin": 47
20
+ }
21
+ ],
22
+ "gpio": {
23
+ "dtSpecs": [
24
+ {
25
+ "pin": 26,
26
+ "dtSpec": "led0"
27
+ },
28
+ {
29
+ "pin": 30,
30
+ "dtSpec": "led1"
31
+ },
32
+ {
33
+ "pin": 6,
34
+ "dtSpec": "led2"
35
+ }
36
+ ]
37
+ },
38
+ "i2c": {
39
+ "controllers": [
40
+ {
41
+ "nodeLabel": "i2c1"
42
+ }
43
+ ]
44
+ },
45
+ "spi": {
46
+ "controllers": [
47
+ {
48
+ "nodeLabel": "spi2"
49
+ }
50
+ ]
51
+ },
52
+ "uart": {
53
+ "controllers": [
54
+ {
55
+ "nodeLabel": "uart0"
56
+ }
57
+ ]
58
+ },
59
+ "pwm": {
60
+ "specs": [
61
+ {
62
+ "pin": 17,
63
+ "dtSpec": "pwm-led0"
64
+ }
65
+ ],
66
+ "maxFrequencyHz": 2000000,
67
+ "resolutionBits": 16
68
+ },
69
+ "adc": {
70
+ "nodeLabel": "adc",
71
+ "resolution": 12,
72
+ "vrefMv": 3000,
73
+ "channels": [
74
+ {
75
+ "pin": 2,
76
+ "channel": 0
77
+ },
78
+ {
79
+ "pin": 3,
80
+ "channel": 1
81
+ },
82
+ {
83
+ "pin": 28,
84
+ "channel": 2
85
+ },
86
+ {
87
+ "pin": 29,
88
+ "channel": 3
89
+ }
90
+ ]
91
+ },
92
+ "wdt": {
93
+ "nodeLabel": "wdt0"
94
+ },
95
+ "usb": {
96
+ "controller": "zephyr_udc0",
97
+ "cdcInstances": 1,
98
+ "vid": "0x2FE3",
99
+ "pid": "0x0003"
100
+ },
101
+ "probeMethods": [
102
+ {
103
+ "id": "jlink",
104
+ "runner": "jlink",
105
+ "description": "J-Link probe (SWD)",
106
+ "debug": true,
107
+ "debugInterface": "swd",
108
+ "debugDevice": "nRF52840_xxAA"
109
+ },
110
+ {
111
+ "id": "openocd",
112
+ "runner": "openocd",
113
+ "description": "Any SWD probe openocd supports (CMSIS-DAP, cheap clones)",
114
+ "debug": true,
115
+ "debugInterface": "swd",
116
+ "debugCfgSource": [
117
+ "interface/stlink.cfg",
118
+ "target/nrf52.cfg"
119
+ ]
120
+ },
121
+ {
122
+ "id": "uf2",
123
+ "runner": "uf2",
124
+ "description": "Bootloader UF2 drag-and-drop: double-tap reset",
125
+ "debug": false
126
+ }
127
+ ],
128
+ "tier": "validated"
129
+ };
@@ -0,0 +1,2 @@
1
+ import type { ZephyrChipDescriptor } from '../types.js';
2
+ export declare const ESP32_SOC: ZephyrChipDescriptor;
@@ -0,0 +1,120 @@
1
+ // Hand-maintained descriptor table — mechanically migrated from the
2
+ // board-esp32-devkit + mcu-esp32 package data (the exact flatten+reconstruct the build
3
+ // performed). Curated additions: tier/pinNaming/excludedPins. Regenerate
4
+ // only alongside a descriptor-type change (edit this file; the original
5
+ // migration script was never committed).
6
+ export const ESP32_SOC = {
7
+ "id": "esp32_devkitc/esp32/procpu",
8
+ "soc": "esp32",
9
+ "gpioController": "gpio0",
10
+ "gpioControllers": [
11
+ {
12
+ "nodelabel": "gpio0",
13
+ "minPin": 0,
14
+ "maxPin": 31
15
+ },
16
+ {
17
+ "nodelabel": "gpio1",
18
+ "minPin": 32,
19
+ "maxPin": 39
20
+ }
21
+ ],
22
+ "gpio": {
23
+ "dtSpecs": [
24
+ {
25
+ "pin": 0,
26
+ "dtSpec": "sw0"
27
+ }
28
+ ],
29
+ "interruptPins": [
30
+ {
31
+ "pin": 0,
32
+ "dtSpec": "sw0"
33
+ }
34
+ ]
35
+ },
36
+ "i2c": {
37
+ "controllers": [
38
+ {
39
+ "nodeLabel": "i2c0"
40
+ }
41
+ ]
42
+ },
43
+ "spi": {
44
+ "controllers": [
45
+ {
46
+ "nodeLabel": "spi2"
47
+ },
48
+ {
49
+ "nodeLabel": "spi3"
50
+ }
51
+ ]
52
+ },
53
+ "uart": {
54
+ "controllers": [
55
+ {
56
+ "nodeLabel": "uart1"
57
+ },
58
+ {
59
+ "nodeLabel": "uart2"
60
+ }
61
+ ]
62
+ },
63
+ "adc": {
64
+ "nodeLabel": "adc0",
65
+ "resolution": 12,
66
+ "vrefMv": 1100,
67
+ "channels": [
68
+ {
69
+ "pin": 36,
70
+ "channel": 0
71
+ },
72
+ {
73
+ "pin": 37,
74
+ "channel": 1
75
+ },
76
+ {
77
+ "pin": 38,
78
+ "channel": 2
79
+ },
80
+ {
81
+ "pin": 39,
82
+ "channel": 3
83
+ },
84
+ {
85
+ "pin": 32,
86
+ "channel": 4
87
+ },
88
+ {
89
+ "pin": 33,
90
+ "channel": 5
91
+ },
92
+ {
93
+ "pin": 34,
94
+ "channel": 6
95
+ },
96
+ {
97
+ "pin": 35,
98
+ "channel": 7
99
+ }
100
+ ]
101
+ },
102
+ "wdt": {
103
+ "nodeLabel": "wdt0"
104
+ },
105
+ "wifi": {
106
+ "supported": true
107
+ },
108
+ "tier": "validated",
109
+ "pinNaming": "esp32-gpio",
110
+ "excludedPins": [
111
+ 6,
112
+ 7,
113
+ 8,
114
+ 9,
115
+ 10,
116
+ 11,
117
+ 16,
118
+ 17
119
+ ]
120
+ };
@@ -0,0 +1,2 @@
1
+ import type { ZephyrChipDescriptor } from '../types.js';
2
+ export declare const ESP32C3_SOC: ZephyrChipDescriptor;