@typecad/framework-zephyr 1.0.0-alpha.18 → 1.0.0-alpha.20

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 (114) hide show
  1. package/dist/audit.d.ts +111 -0
  2. package/dist/audit.js +416 -0
  3. package/dist/boardgen.js +63 -5
  4. package/dist/chips/resolve.js +20 -0
  5. package/dist/chips/types.d.ts +21 -0
  6. package/dist/display/bindings.d.ts +55 -0
  7. package/dist/display/bindings.js +316 -0
  8. package/dist/display/gfx.d.ts +2 -3
  9. package/dist/display/gfx.js +166 -154
  10. package/dist/display/index.js +20 -1
  11. package/dist/display/mipi-dbi-host.d.ts +9 -0
  12. package/dist/display/mipi-dbi-host.js +174 -0
  13. package/dist/display/profiles.d.ts +109 -4
  14. package/dist/display/profiles.js +270 -7
  15. package/dist/display/touch-adapter.js +118 -48
  16. package/dist/display/ui-adapter-eink.d.ts +2 -0
  17. package/dist/display/ui-adapter-eink.js +4 -0
  18. package/dist/display/ui-adapter-gray.d.ts +8 -0
  19. package/dist/display/ui-adapter-gray.js +170 -0
  20. package/dist/display/ui-adapter-mono.d.ts +13 -0
  21. package/dist/display/ui-adapter-mono.js +230 -0
  22. package/dist/display/ui-adapter-native.d.ts +10 -0
  23. package/dist/display/ui-adapter-native.js +295 -0
  24. package/dist/display/ui-adapter-shared.d.ts +11 -0
  25. package/dist/display/ui-adapter-shared.js +122 -0
  26. package/dist/display/ui-adapter.js +53 -101
  27. package/dist/dt-config/kconfig.d.ts +62 -1
  28. package/dist/dt-config/kconfig.js +123 -26
  29. package/dist/dt-config/overlay.d.ts +13 -0
  30. package/dist/dt-config/overlay.js +431 -16
  31. package/dist/framework.manifest.d.ts +9 -3
  32. package/dist/framework.manifest.js +123 -10
  33. package/dist/index.d.ts +2 -0
  34. package/dist/index.js +9 -1
  35. package/dist/licenses.js +5 -84
  36. package/dist/lowering/can.d.ts +25 -0
  37. package/dist/lowering/can.js +97 -0
  38. package/dist/lowering/clock.d.ts +17 -0
  39. package/dist/lowering/clock.js +58 -0
  40. package/dist/lowering/hid.d.ts +27 -0
  41. package/dist/lowering/hid.js +244 -0
  42. package/dist/lowering/i2c.d.ts +8 -0
  43. package/dist/lowering/i2c.js +140 -0
  44. package/dist/lowering/i2s.d.ts +27 -0
  45. package/dist/lowering/i2s.js +98 -0
  46. package/dist/lowering/index.d.ts +9 -1
  47. package/dist/lowering/index.js +25 -1
  48. package/dist/lowering/matrix.d.ts +15 -0
  49. package/dist/lowering/matrix.js +63 -0
  50. package/dist/lowering/power.d.ts +10 -0
  51. package/dist/lowering/power.js +35 -0
  52. package/dist/lowering/pwm.js +25 -0
  53. package/dist/lowering/sensor.d.ts +2 -2
  54. package/dist/lowering/sensor.js +8 -4
  55. package/dist/lowering/strip.d.ts +16 -0
  56. package/dist/lowering/strip.js +70 -0
  57. package/dist/lowering/thread.js +5 -1
  58. package/dist/lowering/trace.d.ts +44 -0
  59. package/dist/lowering/trace.js +239 -0
  60. package/dist/lowering/uart.js +6 -1
  61. package/dist/lowering/usb.d.ts +3 -1
  62. package/dist/lowering/usb.js +6 -3
  63. package/dist/sbom.d.ts +181 -0
  64. package/dist/sbom.js +901 -0
  65. package/dist/strategy.d.ts +60 -2
  66. package/dist/strategy.js +485 -25
  67. package/dist/toolchain/index.d.ts +12 -1
  68. package/dist/toolchain/index.js +115 -27
  69. package/dist/toolchain/scaffold.d.ts +4 -1
  70. package/dist/toolchain/scaffold.js +67 -3
  71. package/dist/west-inventory.d.ts +25 -0
  72. package/dist/west-inventory.js +97 -0
  73. package/package.json +6 -6
  74. package/src/audit.ts +529 -0
  75. package/src/boardgen.ts +54 -5
  76. package/src/chips/resolve.ts +21 -0
  77. package/src/chips/types.ts +576 -567
  78. package/src/display/bindings.ts +347 -0
  79. package/src/display/gfx.ts +318 -306
  80. package/src/display/index.ts +87 -70
  81. package/src/display/mipi-dbi-host.ts +183 -0
  82. package/src/display/profiles.ts +458 -139
  83. package/src/display/touch-adapter.ts +274 -204
  84. package/src/display/ui-adapter-eink.ts +13 -0
  85. package/src/display/ui-adapter-gray.ts +178 -0
  86. package/src/display/ui-adapter-mono.ts +238 -0
  87. package/src/display/ui-adapter-native.ts +304 -0
  88. package/src/display/ui-adapter-shared.ts +125 -0
  89. package/src/display/ui-adapter.ts +51 -100
  90. package/src/dt-config/kconfig.ts +647 -511
  91. package/src/dt-config/overlay.ts +433 -16
  92. package/src/framework.manifest.ts +131 -10
  93. package/src/index.ts +11 -1
  94. package/src/licenses.ts +5 -84
  95. package/src/lowering/can.ts +140 -0
  96. package/src/lowering/clock.ts +91 -0
  97. package/src/lowering/hid.ts +261 -0
  98. package/src/lowering/i2c.ts +146 -0
  99. package/src/lowering/i2s.ts +143 -0
  100. package/src/lowering/index.ts +18 -1
  101. package/src/lowering/matrix.ts +70 -0
  102. package/src/lowering/power.ts +41 -0
  103. package/src/lowering/pwm.ts +192 -167
  104. package/src/lowering/sensor.ts +159 -155
  105. package/src/lowering/strip.ts +81 -0
  106. package/src/lowering/thread.ts +5 -1
  107. package/src/lowering/trace.ts +270 -0
  108. package/src/lowering/uart.ts +6 -1
  109. package/src/lowering/usb.ts +224 -221
  110. package/src/sbom.ts +1117 -0
  111. package/src/strategy.ts +440 -25
  112. package/src/toolchain/index.ts +117 -28
  113. package/src/toolchain/scaffold.ts +62 -3
  114. package/src/west-inventory.ts +102 -0
@@ -0,0 +1,270 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Trace heartbeat — the runtime-stats sampler behind `typecad-hal trace`
3
+ //
4
+ // Emits a self-starting sampler into the ENTRY translation unit only (the
5
+ // block compiles under CUTTLEFISH_ENTRY_TU, which the emitter defines once
6
+ // per program — a copy in a split-file TU would register the SYS_INIT hook
7
+ // twice and double every heartbeat). A k_work_delayable on the system work
8
+ // queue samples, every intervalMs:
9
+ //
10
+ // - per-thread execution cycles (CONFIG_THREAD_RUNTIME_STATS)
11
+ // - per-thread stack unused/size (CONFIG_INIT_STACKS / THREAD_STACK_INFO)
12
+ // - the system-wide cycle counter (k_thread_runtime_stats_all_get — the
13
+ // CPU-time denominator; per-thread CPU% is computed HOST-side as
14
+ // delta_thread_exec / delta_sys_exec, so no cycle/Hz units leak onto
15
+ // the wire and idle shows up as its own thread)
16
+ //
17
+ // and prints `[TR:` lines on the console (printf → STDOUT_CONSOLE, the same
18
+ // channel the test-runner protocol uses). Sampling, not event tracing: the
19
+ // device cost is O(live threads) arithmetic per interval — no context-switch
20
+ // hook, no ring buffer, no per-frame work — so the probe effect on the
21
+ // measured system is one short work-queue visit per interval.
22
+ //
23
+ // Heap usage is deliberately NOT sampled: engine-emitted C++ is no-malloc by
24
+ // construction (AUTOSAR rule set), so a heap series would be a constant line.
25
+ //
26
+ // The whole block also gates on CONFIG_THREAD_MONITOR + CONFIG_THREAD_RUNTIME
27
+ // _STATS: the scaffold enables both when zephyr.trace.enabled is set, but a
28
+ // user override in zephyr.kconfig compiles the sampler out instead of
29
+ // failing the link (k_thread_foreach lives in kernel/thread_monitor.c and
30
+ // only builds under THREAD_MONITOR).
31
+ // ---------------------------------------------------------------------------
32
+
33
+ import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
34
+
35
+ /**
36
+ * Resolve a HAL trace.* op to Zephyr C++. The device helpers
37
+ * (__tc_trace_mark / __tc_trace_event) are emitted unconditionally by
38
+ * shimLines — they are two printf calls, and a Trace.mark() call site must
39
+ * never fail to link because tracing was disabled (the lines simply have no
40
+ * capture listening).
41
+ */
42
+ export function lowerTrace(op: HALOpIR): { code?: string; expression?: string } {
43
+ const o = op as { operation: string; name?: string; value?: string | number };
44
+
45
+ switch (op.operation) {
46
+ case 'trace.mark':
47
+ return { code: `__tc_trace_mark(${o.name ?? '""'});` };
48
+ case 'trace.event':
49
+ // The value may be a runtime expression (variable, ternary) — the
50
+ // plugin resolved it as text; interpolate inside static_cast so any
51
+ // numeric C++ expression is valid here.
52
+ return { code: `__tc_trace_event(${o.name ?? '""'}, static_cast<double>(${o.value ?? 0}));` };
53
+ default:
54
+ throw new Error(
55
+ `framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
56
+ `Open an issue or use rawCpp() to emit it manually.`,
57
+ );
58
+ }
59
+ }
60
+
61
+ /** Default heartbeat interval (ms) when zephyr.trace.intervalMs is absent. */
62
+ export const TRACE_HB_DEFAULT_INTERVAL_MS = 1000;
63
+
64
+ /** Clamp for zephyr.trace.intervalMs — faster than 50 ms floods the console
65
+ * and skews the measured CPU load; slower than a minute adds nothing. */
66
+ export function clampTraceIntervalMs(intervalMs: number | undefined): number {
67
+ if (typeof intervalMs !== 'number' || !Number.isFinite(intervalMs)) {
68
+ return TRACE_HB_DEFAULT_INTERVAL_MS;
69
+ }
70
+ return Math.min(60_000, Math.max(50, Math.round(intervalMs)));
71
+ }
72
+
73
+ /**
74
+ * UI frame-time trace block — emitted UNCONDITIONALLY for UI-mounted
75
+ * programs (the call site the emitter stamps after ui_tick must never fail
76
+ * to link), but every body compiles away unless the heartbeat block defined
77
+ * CUTTLEFISH_TRACE_UI (zephyr.trace enabled). Wall-time stats only: frame
78
+ * count / total / max ms per heartbeat interval — the per-phase breakdown
79
+ * inside ui_tick stays a ui-engine change for a later stage.
80
+ */
81
+ /**
82
+ * On-device alarm thresholds (zephyr.trace.alarms) — the sampler prints
83
+ * [TR:ALARM:<seq>:<code>:<detail>] the moment one is breached, so an
84
+ * untethered device still DETECTS the degradation; reading it only needs a
85
+ * capture (or a serial console) after the fact.
86
+ */
87
+ export interface TraceAlarmThresholds {
88
+ /** Alarm when a thread's unused stack falls below this (bytes). */
89
+ stackMinBytes?: number;
90
+ /** Alarm when an interval's worst UI frame exceeds this (ms). */
91
+ frameMaxMs?: number;
92
+ }
93
+
94
+ export function uiFrameTraceLines(frameAlarmMs?: number): string[] {
95
+ const alarmDefine = frameAlarmMs !== undefined ? [`#define __TC_TRACE_ALARM_FRAME ${frameAlarmMs}U`] : [];
96
+ const frameAlarm = frameAlarmMs !== undefined
97
+ ? [
98
+ ' // Continual monitoring: the worst frame breaching the ceiling is an',
99
+ ' // alarm, not a statistic — printed the moment it happens.',
100
+ ' if (__tc_trace_ui_max_ms > __TC_TRACE_ALARM_FRAME) {',
101
+ ' printf("[TR:ALARM:%u:frame:%u\\n", static_cast<unsigned int>(seq),',
102
+ ' static_cast<unsigned int>(__tc_trace_ui_max_ms));',
103
+ ' }',
104
+ ]
105
+ : [];
106
+ return [
107
+ '// CUTTLEFISH_TRACE_UI_BEGIN',
108
+ '#if defined(CUTTLEFISH_TRACE_UI)',
109
+ ...alarmDefine,
110
+ 'static uint32_t __tc_trace_ui_frames = 0U;',
111
+ 'static uint32_t __tc_trace_ui_total_ms = 0U;',
112
+ 'static uint32_t __tc_trace_ui_max_ms = 0U;',
113
+ 'static uint64_t __tc_trace_ui_phase[5];',
114
+ '#endif',
115
+ 'static inline void __tc_trace_ui_frame(uint32_t frame_delta_ms) {',
116
+ '#if defined(CUTTLEFISH_TRACE_UI)',
117
+ ' __tc_trace_ui_frames += 1U;',
118
+ ' __tc_trace_ui_total_ms += frame_delta_ms;',
119
+ ' if (frame_delta_ms > __tc_trace_ui_max_ms) { __tc_trace_ui_max_ms = frame_delta_ms; }',
120
+ '#else',
121
+ ' (void)frame_delta_ms;',
122
+ '#endif',
123
+ '}',
124
+ // Called from the seams the ui-engine's emitTick interleaves between its
125
+ // five phase slices (bindings / transitions / draw / scroll / flush).
126
+ // Cycles are accumulated raw; the report converts to µs once per
127
+ // heartbeat via sys_clock_hw_cycles_per_sec().
128
+ 'static inline void __tc_trace_ui_phase_add(uint8_t idx, uint64_t cycles) {',
129
+ '#if defined(CUTTLEFISH_TRACE_UI)',
130
+ ' if (idx < 5U) { __tc_trace_ui_phase[idx] += cycles; }',
131
+ '#else',
132
+ ' (void)idx; (void)cycles;',
133
+ '#endif',
134
+ '}',
135
+ 'static inline void __tc_trace_ui_report(uint32_t seq) {',
136
+ '#if defined(CUTTLEFISH_TRACE_UI)',
137
+ ' if (__tc_trace_ui_frames > 0U) {',
138
+ ' const uint32_t avg_x10 = (__tc_trace_ui_total_ms * 10U) / __tc_trace_ui_frames;',
139
+ ' printf("[TR:UI:%u:%u:%u:%u\\n", static_cast<unsigned int>(seq),',
140
+ ' static_cast<unsigned int>(__tc_trace_ui_frames),',
141
+ ' static_cast<unsigned int>(avg_x10),',
142
+ ' static_cast<unsigned int>(__tc_trace_ui_max_ms));',
143
+ ' printf("[TR:UP:%u:%llu:%llu:%llu:%llu:%llu\\n", static_cast<unsigned int>(seq),',
144
+ ' static_cast<unsigned long long>((__tc_trace_ui_phase[0] * 1000000ULL) / sys_clock_hw_cycles_per_sec()),',
145
+ ' static_cast<unsigned long long>((__tc_trace_ui_phase[1] * 1000000ULL) / sys_clock_hw_cycles_per_sec()),',
146
+ ' static_cast<unsigned long long>((__tc_trace_ui_phase[2] * 1000000ULL) / sys_clock_hw_cycles_per_sec()),',
147
+ ' static_cast<unsigned long long>((__tc_trace_ui_phase[3] * 1000000ULL) / sys_clock_hw_cycles_per_sec()),',
148
+ ' static_cast<unsigned long long>((__tc_trace_ui_phase[4] * 1000000ULL) / sys_clock_hw_cycles_per_sec()));',
149
+ ...frameAlarm,
150
+ ' }',
151
+ '#else',
152
+ ' (void)seq;',
153
+ '#endif',
154
+ '}',
155
+ 'static inline void __tc_trace_ui_reset(void) {',
156
+ '#if defined(CUTTLEFISH_TRACE_UI)',
157
+ ' __tc_trace_ui_frames = 0U;',
158
+ ' __tc_trace_ui_total_ms = 0U;',
159
+ ' __tc_trace_ui_max_ms = 0U;',
160
+ ' for (uint8_t i = 0U; i < 5U; i++) { __tc_trace_ui_phase[i] = 0ULL; }',
161
+ '#endif',
162
+ '}',
163
+ '// CUTTLEFISH_TRACE_UI_END',
164
+ ];
165
+ }
166
+
167
+ /**
168
+ * The heartbeat shim lines (definitions + SYS_INIT self-start). Emitted by
169
+ * shimLines when the platform context carries zephyr.trace.enabled.
170
+ * `withUi` adds the [TR:UI: frame-stats line (UI-mounted programs).
171
+ */
172
+ export function traceHeartbeatLines(intervalMs: number, withUi: boolean, alarms?: TraceAlarmThresholds): string[] {
173
+ const ms = clampTraceIntervalMs(intervalMs);
174
+ const stackAlarmDefine = alarms?.stackMinBytes !== undefined
175
+ ? [`#define __TC_TRACE_ALARM_STACK ${alarms.stackMinBytes}U`]
176
+ : [];
177
+ const stackAlarm = alarms?.stackMinBytes !== undefined
178
+ ? [
179
+ ' // Continual monitoring: headroom under the floor is an alarm, printed',
180
+ ' // the moment the sampler sees it (once per interval while held).',
181
+ '#ifdef __TC_TRACE_ALARM_STACK',
182
+ ' if (stack_ok && unused < __TC_TRACE_ALARM_STACK) {',
183
+ ' printf("[TR:ALARM:%u:stack:%s:%u\\n", static_cast<unsigned int>(seq), name,',
184
+ ' static_cast<unsigned int>(unused));',
185
+ ' }',
186
+ '#endif',
187
+ ]
188
+ : [];
189
+ return [
190
+ '// CUTTLEFISH_TRACE_BEGIN',
191
+ '#if defined(CUTTLEFISH_ENTRY_TU) && defined(CONFIG_THREAD_MONITOR) && defined(CONFIG_THREAD_RUNTIME_STATS)',
192
+ `#define __TC_TRACE_HB_MS ${ms}U`,
193
+ ...stackAlarmDefine,
194
+ 'static uint32_t __tc_trace_seq = 0U;',
195
+ // One [TR:TH:<seq>:<name>:<exec>:<unused>:<size>] line per live thread.
196
+ // Stack fields print -1 when the platform cannot inspect that thread
197
+ // (ARC-style NO_UNUSED_STACK_INSPECTION faults) — the host reads the
198
+ // sentinel as "unknown", not zero.
199
+ 'static void __tc_trace_thread_line(const struct k_thread* cthread, void* user_data) {',
200
+ ' (void)user_data;',
201
+ ' // The foreach callback hands out a const thread; the stats/name',
202
+ ' // syscalls take k_tid_t (non-const) — the same const_cast Zephyr\'s',
203
+ ' // own thread_analyzer performs at this exact boundary.',
204
+ ' struct k_thread* thread = const_cast<struct k_thread*>(cthread);',
205
+ ' const uint32_t seq = __tc_trace_seq;',
206
+ ' k_thread_runtime_stats_t stats;',
207
+ ' uint64_t exec = 0U;',
208
+ ' if (k_thread_runtime_stats_get(thread, &stats) == 0) {',
209
+ ' exec = stats.execution_cycles;',
210
+ ' }',
211
+ ' size_t unused = 0U;',
212
+ ' const bool stack_ok = k_thread_stack_space_get(thread, &unused) == 0;',
213
+ '#ifdef CONFIG_THREAD_STACK_INFO',
214
+ ' const size_t size = thread->stack_info.size;',
215
+ '#else',
216
+ ' const size_t size = 0U;',
217
+ '#endif',
218
+ ' char name[24];',
219
+ ' const char* thread_name = k_thread_name_get(thread);',
220
+ ' uint32_t n = 0U;',
221
+ ' if (thread_name != nullptr) {',
222
+ ' for (; thread_name[n] != \'\\0\' && n < (sizeof(name) - 1U); n++) {',
223
+ ' const char c = thread_name[n];',
224
+ ' const bool plain = (c >= \'a\' && c <= \'z\') || (c >= \'A\' && c <= \'Z\')',
225
+ ' || (c >= \'0\' && c <= \'9\') || c == \'_\' || c == \'-\' || c == \'.\';',
226
+ ' name[n] = plain ? c : \'_\';',
227
+ ' }',
228
+ ' }',
229
+ ' name[n] = \'\\0\';',
230
+ ' if (n == 0U) { name[0] = \'u\'; name[1] = \'n\'; name[2] = \'\\0\'; }',
231
+ ' printf("[TR:TH:%u:%s:%llu:%lld:%u\\n",',
232
+ ' static_cast<unsigned int>(seq), name,',
233
+ ' static_cast<unsigned long long>(exec),',
234
+ ' stack_ok ? static_cast<long long>(unused) : -1LL,',
235
+ ' static_cast<unsigned int>(size));',
236
+ ...stackAlarm,
237
+ '}',
238
+ 'static void __tc_trace_hb_work(struct k_work* work);',
239
+ 'static K_WORK_DELAYABLE_DEFINE(__tc_trace_hb_dwork, __tc_trace_hb_work);',
240
+ 'static void __tc_trace_hb_work(struct k_work* work) {',
241
+ ' (void)work;',
242
+ ' k_thread_runtime_stats_t all;',
243
+ ' uint64_t sys_exec = 0U;',
244
+ ' if (k_thread_runtime_stats_all_get(&all) == 0) {',
245
+ ' sys_exec = all.execution_cycles;',
246
+ ' }',
247
+ ' __tc_trace_seq += 1U;',
248
+ ' printf("[TR:HB:%u:%u:%llu\\n",',
249
+ ' static_cast<unsigned int>(__tc_trace_seq),',
250
+ ' static_cast<unsigned int>(k_uptime_get_32()),',
251
+ ' static_cast<unsigned long long>(sys_exec));',
252
+ ...(withUi
253
+ ? [
254
+ ' __tc_trace_ui_report(__tc_trace_seq);',
255
+ ' __tc_trace_ui_reset();',
256
+ ]
257
+ : []),
258
+ ' k_thread_foreach(__tc_trace_thread_line, nullptr);',
259
+ ' k_work_reschedule(&__tc_trace_hb_dwork, K_MSEC(__TC_TRACE_HB_MS));',
260
+ '}',
261
+ 'static int __tc_trace_hb_boot(void) {',
262
+ ` printf("[TR:CFG:1:${ms}]\\n");`,
263
+ ' k_work_schedule(&__tc_trace_hb_dwork, K_MSEC(__TC_TRACE_HB_MS));',
264
+ ' return 0;',
265
+ '}',
266
+ 'SYS_INIT(__tc_trace_hb_boot, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);',
267
+ '#endif // CUTTLEFISH_ENTRY_TU && THREAD_MONITOR && THREAD_RUNTIME_STATS',
268
+ '// CUTTLEFISH_TRACE_END',
269
+ ];
270
+ }
@@ -30,7 +30,12 @@ export function uartInitLines(chip: ZephyrChipDescriptor, controllerIndex: numbe
30
30
  '// CUTTLEFISH_UART_BEGIN',
31
31
  `static const struct device* ${p}_dev = DEVICE_DT_GET(DT_NODELABEL(${ctrl.nodeLabel}));`,
32
32
  `static void ${p}_init(uint32_t baud) {`,
33
- ` const struct uart_config cfg = { .baudrate = (baud ? baud : 115200), .parity = UART_CFG_PARITY_NONE, .stop_bits = UART_CFG_STOP_BITS_1, .data_bits = UART_CFG_DATA_BITS_8, .flow_ctrl = UART_CFG_FLOW_CTRL_NONE };`,
33
+ // 115200 8N1 is the console default — reconfiguring an already-matching
34
+ // port RESETS the ESP32 UART's TX path and silently eats the FIRST write
35
+ // that follows (poll_out completes into a reconfiguring FIFO). Only a
36
+ // genuinely different rate reconfigures.
37
+ ` if (baud == 0U || baud == 115200U) { return; }`,
38
+ ` const struct uart_config cfg = { .baudrate = baud, .parity = UART_CFG_PARITY_NONE, .stop_bits = UART_CFG_STOP_BITS_1, .data_bits = UART_CFG_DATA_BITS_8, .flow_ctrl = UART_CFG_FLOW_CTRL_NONE };`,
34
39
  ` uart_configure(${p}_dev, &cfg);`,
35
40
  `}`,
36
41
  '// CUTTLEFISH_UART_END',