tan-cli 0.7.0__py3-none-any.whl

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 (330) hide show
  1. tan/__init__.py +0 -0
  2. tan/__main__.py +120 -0
  3. tan/cli.py +939 -0
  4. tan/command_table.py +265 -0
  5. tan/commands/__init__.py +8 -0
  6. tan/commands/bootstrap_cmd.py +4856 -0
  7. tan/commands/bootstrap_patches.py +164 -0
  8. tan/commands/bootstrap_toolchain_fetch.py +155 -0
  9. tan/commands/bootstrap_toolchain_pin.py +36 -0
  10. tan/commands/build/__init__.py +1 -0
  11. tan/commands/build/configure_inputs.py +277 -0
  12. tan/commands/build/execute.py +1852 -0
  13. tan/commands/build/host_python.py +59 -0
  14. tan/commands/build/link_stale.py +78 -0
  15. tan/commands/build/manifest.py +428 -0
  16. tan/commands/build/materialise.py +81 -0
  17. tan/commands/build/token_substitution.py +381 -0
  18. tan/commands/build/toolchain.py +482 -0
  19. tan/commands/build/user_defines_wipe.py +115 -0
  20. tan/commands/build/workspace_patches.py +65 -0
  21. tan/commands/build_cmd.py +2236 -0
  22. tan/commands/build_output.py +331 -0
  23. tan/commands/clean_cmd.py +1183 -0
  24. tan/commands/completion_cmd.py +786 -0
  25. tan/commands/debug_config_cmd.py +2425 -0
  26. tan/commands/diff_cmd.py +940 -0
  27. tan/commands/doctor_cmd.py +4767 -0
  28. tan/commands/examples_cmd.py +644 -0
  29. tan/commands/explain_cmd.py +1319 -0
  30. tan/commands/faultdecode_cmd.py +931 -0
  31. tan/commands/flash_atoc_guard.py +240 -0
  32. tan/commands/flash_cmd.py +5731 -0
  33. tan/commands/flash_mram_guard.py +150 -0
  34. tan/commands/flash_ram.py +578 -0
  35. tan/commands/flash_raw.py +583 -0
  36. tan/commands/generate_cmd.py +1456 -0
  37. tan/commands/image_cmd.py +753 -0
  38. tan/commands/init_cmd.py +1740 -0
  39. tan/commands/inspect_cmd.py +377 -0
  40. tan/commands/kconfig_cmd.py +734 -0
  41. tan/commands/model_cmd.py +1514 -0
  42. tan/commands/model_device_cmd.py +351 -0
  43. tan/commands/model_device_live.py +234 -0
  44. tan/commands/model_host_cmd.py +430 -0
  45. tan/commands/model_zoo_cmd.py +363 -0
  46. tan/commands/monitor_actions.py +125 -0
  47. tan/commands/monitor_cmd.py +626 -0
  48. tan/commands/monitor_session.py +505 -0
  49. tan/commands/new_som_cmd.py +1522 -0
  50. tan/commands/pinmux_cmd.py +568 -0
  51. tan/commands/presets_cmd.py +1123 -0
  52. tan/commands/probe_cmd.py +421 -0
  53. tan/commands/reset_cmd.py +354 -0
  54. tan/commands/reset_confirm.py +168 -0
  55. tan/commands/run_cmd.py +637 -0
  56. tan/commands/scaffold_cmd.py +490 -0
  57. tan/commands/sdk_cmd.py +1723 -0
  58. tan/commands/size_cmd.py +1020 -0
  59. tan/commands/support_bundle_cmd.py +1073 -0
  60. tan/commands/trace_cmd.py +341 -0
  61. tan/commands/validate_cmd.py +2009 -0
  62. tan/commands/west_forward_cmd.py +736 -0
  63. tan/commands/workspace_patch_check.py +296 -0
  64. tan/core/__init__.py +1 -0
  65. tan/core/alp_conf_pregen.py +100 -0
  66. tan/core/artifact_provenance.py +240 -0
  67. tan/core/atoc_guard.py +276 -0
  68. tan/core/atoc_guard_messages.py +232 -0
  69. tan/core/atoc_replacement.py +118 -0
  70. tan/core/atomic_write.py +178 -0
  71. tan/core/board_context.py +351 -0
  72. tan/core/board_diagnostic.py +111 -0
  73. tan/core/board_files.py +221 -0
  74. tan/core/board_validator.py +542 -0
  75. tan/core/board_validator_compat.py +196 -0
  76. tan/core/board_validator_run.py +129 -0
  77. tan/core/board_validator_schema.py +186 -0
  78. tan/core/board_validator_skew.py +46 -0
  79. tan/core/board_yaml_edit.py +295 -0
  80. tan/core/board_yaml_pos.py +118 -0
  81. tan/core/bootstrap.py +2572 -0
  82. tan/core/build_plan.py +625 -0
  83. tan/core/consent.py +104 -0
  84. tan/core/console_filter.py +245 -0
  85. tan/core/debug_launch.py +1803 -0
  86. tan/core/devicetree_lint.py +168 -0
  87. tan/core/dir_removal.py +229 -0
  88. tan/core/doctor_git.py +172 -0
  89. tan/core/doctor_libraries.py +253 -0
  90. tan/core/doctor_render.py +185 -0
  91. tan/core/doctor_scope.py +66 -0
  92. tan/core/doctor_setools.py +237 -0
  93. tan/core/doctor_stale.py +180 -0
  94. tan/core/document_guards.py +723 -0
  95. tan/core/dp_id.py +97 -0
  96. tan/core/elf_load.py +63 -0
  97. tan/core/error_catalog.py +171 -0
  98. tan/core/example_catalog.py +499 -0
  99. tan/core/example_facets.py +151 -0
  100. tan/core/faultdecode.py +521 -0
  101. tan/core/flash_plan.py +2501 -0
  102. tan/core/flow_d_report.py +381 -0
  103. tan/core/flow_d_uptime.py +164 -0
  104. tan/core/fs_confine.py +130 -0
  105. tan/core/global_flags.py +230 -0
  106. tan/core/host_python.py +210 -0
  107. tan/core/image_bundle.py +247 -0
  108. tan/core/inert.py +147 -0
  109. tan/core/jlink_binary.py +128 -0
  110. tan/core/jlink_probe.py +481 -0
  111. tan/core/jsonc_splice.py +404 -0
  112. tan/core/launch_provenance.py +257 -0
  113. tan/core/link_refusal.py +76 -0
  114. tan/core/metadata_schema.py +376 -0
  115. tan/core/model_check.py +227 -0
  116. tan/core/model_device.py +449 -0
  117. tan/core/model_doctor.py +198 -0
  118. tan/core/model_host.py +48 -0
  119. tan/core/model_list.py +112 -0
  120. tan/core/model_zoo.py +353 -0
  121. tan/core/module_template.py +340 -0
  122. tan/core/mram_link.py +87 -0
  123. tan/core/new_som_ospi.py +94 -0
  124. tan/core/os_class.py +159 -0
  125. tan/core/patch_paths.py +87 -0
  126. tan/core/pending.py +40 -0
  127. tan/core/plain_zephyr_plan.py +138 -0
  128. tan/core/plan_exec.py +373 -0
  129. tan/core/plan_tokens.py +600 -0
  130. tan/core/probe.py +155 -0
  131. tan/core/probe_plan.py +237 -0
  132. tan/core/proxy.py +168 -0
  133. tan/core/publish.py +31 -0
  134. tan/core/python_floor.py +178 -0
  135. tan/core/ram_run.py +694 -0
  136. tan/core/ram_watch.py +231 -0
  137. tan/core/raw_write.py +160 -0
  138. tan/core/reset_plan.py +56 -0
  139. tan/core/run.py +161 -0
  140. tan/core/scaffold.py +2203 -0
  141. tan/core/scaffold_selftest_identity.py +225 -0
  142. tan/core/sdk_default_registry.py +565 -0
  143. tan/core/sdk_discovery.py +996 -0
  144. tan/core/sdk_removal.py +465 -0
  145. tan/core/serial_actions.py +175 -0
  146. tan/core/serial_capture.py +185 -0
  147. tan/core/serial_url.py +45 -0
  148. tan/core/setools.py +608 -0
  149. tan/core/setools_scratch.py +243 -0
  150. tan/core/shapes.py +194 -0
  151. tan/core/size.py +610 -0
  152. tan/core/som_buildability.py +204 -0
  153. tan/core/som_schema_version.py +62 -0
  154. tan/core/subprocess_env.py +201 -0
  155. tan/core/sysbuild_image.py +94 -0
  156. tan/core/system_manifest.py +827 -0
  157. tan/core/text_layout.py +73 -0
  158. tan/core/timestamp.py +182 -0
  159. tan/core/tool_lookup.py +383 -0
  160. tan/core/toolchain_pin.py +117 -0
  161. tan/core/toolchain_provision.py +1224 -0
  162. tan/core/trusted_path.py +134 -0
  163. tan/core/uboot_breakin.py +154 -0
  164. tan/core/uri_reference.py +415 -0
  165. tan/core/user_defines.py +152 -0
  166. tan/core/venv.py +332 -0
  167. tan/core/west_patches.py +143 -0
  168. tan/core/west_workspace_refusal.py +159 -0
  169. tan/core/zephyr_env.py +124 -0
  170. tan/env.py +185 -0
  171. tan/envelope.py +647 -0
  172. tan/exit_codes.py +12 -0
  173. tan/lazy_typer.py +185 -0
  174. tan/model/__init__.py +2 -0
  175. tan/model/_gen_fixture.py +132 -0
  176. tan/model/adapters/__init__.py +116 -0
  177. tan/model/adapters/cpu.py +26 -0
  178. tan/model/adapters/deepx.py +94 -0
  179. tan/model/adapters/drpai.py +242 -0
  180. tan/model/adapters/ethos_u.py +951 -0
  181. tan/model/adapters/executorch.py +55 -0
  182. tan/model/analyze.py +694 -0
  183. tan/model/build.py +304 -0
  184. tan/model/check.py +682 -0
  185. tan/model/manifest.py +625 -0
  186. tan/model/measure.py +216 -0
  187. tan/model/npu_ops_validate.py +130 -0
  188. tan/model/package.py +125 -0
  189. tan/model/perf.py +635 -0
  190. tan/model/perf_apply.py +721 -0
  191. tan/model/prep.py +193 -0
  192. tan/model/sram_fit.py +502 -0
  193. tan/model/targets.py +374 -0
  194. tan/model/tensorio.py +287 -0
  195. tan/net.py +73 -0
  196. tan/output_format.py +213 -0
  197. tan/planner/__init__.py +219 -0
  198. tan/planner/aperture.py +202 -0
  199. tan/planner/buildplan.py +1092 -0
  200. tan/planner/camera_owner.py +192 -0
  201. tan/planner/cameras.py +132 -0
  202. tan/planner/carveout.py +755 -0
  203. tan/planner/cli.py +274 -0
  204. tan/planner/headers.py +315 -0
  205. tan/planner/kconfig.py +2435 -0
  206. tan/planner/kconfig_symbols.py +473 -0
  207. tan/planner/libraries.py +677 -0
  208. tan/planner/link_target.py +237 -0
  209. tan/planner/linux_ownership.py +216 -0
  210. tan/planner/loader.py +1525 -0
  211. tan/planner/manifest.py +116 -0
  212. tan/planner/memory.py +161 -0
  213. tan/planner/memregion.py +56 -0
  214. tan/planner/models.py +533 -0
  215. tan/planner/orchestrator.py +874 -0
  216. tan/planner/ownership.py +203 -0
  217. tan/planner/partition.py +1160 -0
  218. tan/planner/paths.py +32 -0
  219. tan/planner/plain_slice.py +139 -0
  220. tan/planner/project_emit/__init__.py +60 -0
  221. tan/planner/project_emit/bom_netlist.py +375 -0
  222. tan/planner/project_emit/dts.py +580 -0
  223. tan/planner/project_emit/hw_info.py +221 -0
  224. tan/planner/project_emit/native_sim.py +136 -0
  225. tan/planner/project_emit/west_libs.py +213 -0
  226. tan/planner/project_loader.py +264 -0
  227. tan/planner/sdk_capability.py +203 -0
  228. tan/planner/sdk_compat.py +395 -0
  229. tan/planner/secure.py +350 -0
  230. tan/planner/slugs.py +394 -0
  231. tan/planner/som_metadata.py +325 -0
  232. tan/planner/strict_loaders.py +131 -0
  233. tan/planner/template.py +1037 -0
  234. tan/planner/template_pins.py +535 -0
  235. tan/planner/template_rewrite.py +714 -0
  236. tan/planner/topology.py +208 -0
  237. tan/planner/validate.py +365 -0
  238. tan/planner/whole_device_alias.py +67 -0
  239. tan/planner/zephyr_board.py +3510 -0
  240. tan/planner_cli.py +97 -0
  241. tan/planner_emit.py +617 -0
  242. tan/planner_root.py +119 -0
  243. tan/soc_ref.py +58 -0
  244. tan/templates/__init__.py +34 -0
  245. tan/templates/vendored/MANIFEST.md +1862 -0
  246. tan/templates/vendored/diagnostics/E1M-AEN801/CMakeLists.txt +8 -0
  247. tan/templates/vendored/diagnostics/E1M-AEN801/README.md +112 -0
  248. tan/templates/vendored/diagnostics/E1M-AEN801/board.yaml +38 -0
  249. tan/templates/vendored/diagnostics/E1M-AEN801/boards/native_sim_native_64.conf +11 -0
  250. tan/templates/vendored/diagnostics/E1M-AEN801/boards/native_sim_native_64.overlay +29 -0
  251. tan/templates/vendored/diagnostics/E1M-AEN801/prj.conf +5 -0
  252. tan/templates/vendored/diagnostics/E1M-AEN801/src/main.c +266 -0
  253. tan/templates/vendored/diagnostics/E1M-AEN801/testcase.yaml +53 -0
  254. tan/templates/vendored/diagnostics/E1M-V2N101/CMakeLists.txt +8 -0
  255. tan/templates/vendored/diagnostics/E1M-V2N101/README.md +112 -0
  256. tan/templates/vendored/diagnostics/E1M-V2N101/board.yaml +38 -0
  257. tan/templates/vendored/diagnostics/E1M-V2N101/boards/native_sim_native_64.conf +11 -0
  258. tan/templates/vendored/diagnostics/E1M-V2N101/boards/native_sim_native_64.overlay +29 -0
  259. tan/templates/vendored/diagnostics/E1M-V2N101/prj.conf +5 -0
  260. tan/templates/vendored/diagnostics/E1M-V2N101/src/main.c +266 -0
  261. tan/templates/vendored/diagnostics/E1M-V2N101/testcase.yaml +53 -0
  262. tan/templates/vendored/edge-ai/E1M-AEN801/CMakeLists.txt +10 -0
  263. tan/templates/vendored/edge-ai/E1M-AEN801/README.md +75 -0
  264. tan/templates/vendored/edge-ai/E1M-AEN801/board.yaml +38 -0
  265. tan/templates/vendored/edge-ai/E1M-AEN801/prj.conf +8 -0
  266. tan/templates/vendored/edge-ai/E1M-AEN801/src/cold_chain.c +371 -0
  267. tan/templates/vendored/edge-ai/E1M-AEN801/src/cold_chain.h +178 -0
  268. tan/templates/vendored/edge-ai/E1M-AEN801/src/main.c +373 -0
  269. tan/templates/vendored/edge-ai/E1M-AEN801/testcase.yaml +62 -0
  270. tan/templates/vendored/edge-ai/E1M-V2N101/CMakeLists.txt +10 -0
  271. tan/templates/vendored/edge-ai/E1M-V2N101/README.md +75 -0
  272. tan/templates/vendored/edge-ai/E1M-V2N101/board.yaml +37 -0
  273. tan/templates/vendored/edge-ai/E1M-V2N101/prj.conf +8 -0
  274. tan/templates/vendored/edge-ai/E1M-V2N101/src/cold_chain.c +371 -0
  275. tan/templates/vendored/edge-ai/E1M-V2N101/src/cold_chain.h +178 -0
  276. tan/templates/vendored/edge-ai/E1M-V2N101/src/main.c +373 -0
  277. tan/templates/vendored/edge-ai/E1M-V2N101/testcase.yaml +62 -0
  278. tan/templates/vendored/iot/E1M-AEN801/CMakeLists.txt +14 -0
  279. tan/templates/vendored/iot/E1M-AEN801/README.md +103 -0
  280. tan/templates/vendored/iot/E1M-AEN801/board.yaml +69 -0
  281. tan/templates/vendored/iot/E1M-AEN801/prj.conf +15 -0
  282. tan/templates/vendored/iot/E1M-AEN801/src/cc3501e_bridge.c +196 -0
  283. tan/templates/vendored/iot/E1M-AEN801/src/cc3501e_bridge.h +173 -0
  284. tan/templates/vendored/iot/E1M-AEN801/src/main.c +262 -0
  285. tan/templates/vendored/iot/E1M-AEN801/testcase.yaml +68 -0
  286. tan/templates/vendored/minimal/E1M-AEN801/CMakeLists.txt +8 -0
  287. tan/templates/vendored/minimal/E1M-AEN801/README.md +108 -0
  288. tan/templates/vendored/minimal/E1M-AEN801/board.yaml +32 -0
  289. tan/templates/vendored/minimal/E1M-AEN801/prj.conf +8 -0
  290. tan/templates/vendored/minimal/E1M-AEN801/src/main.c +111 -0
  291. tan/templates/vendored/minimal/E1M-AEN801/testcase.yaml +49 -0
  292. tan/templates/vendored/minimal/E1M-V2N101/CMakeLists.txt +8 -0
  293. tan/templates/vendored/minimal/E1M-V2N101/README.md +108 -0
  294. tan/templates/vendored/minimal/E1M-V2N101/board.yaml +32 -0
  295. tan/templates/vendored/minimal/E1M-V2N101/prj.conf +8 -0
  296. tan/templates/vendored/minimal/E1M-V2N101/src/main.c +111 -0
  297. tan/templates/vendored/minimal/E1M-V2N101/testcase.yaml +49 -0
  298. tan/templates/vendored/multicore-mailbox/E1M-AEN801/CMakeLists.txt +8 -0
  299. tan/templates/vendored/multicore-mailbox/E1M-AEN801/README.md +120 -0
  300. tan/templates/vendored/multicore-mailbox/E1M-AEN801/board.yaml +57 -0
  301. tan/templates/vendored/multicore-mailbox/E1M-AEN801/boards/native_sim_native_64.overlay +40 -0
  302. tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/CMakeLists.txt +13 -0
  303. tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/main.c +171 -0
  304. tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/prj.conf +17 -0
  305. tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/testcase.yaml +23 -0
  306. tan/templates/vendored/multicore-mailbox/E1M-AEN801/prj.conf +22 -0
  307. tan/templates/vendored/multicore-mailbox/E1M-AEN801/src/main.c +185 -0
  308. tan/templates/vendored/multicore-mailbox/E1M-AEN801/testcase.yaml +26 -0
  309. tan/templates/vendored/sensor/E1M-AEN801/CMakeLists.txt +8 -0
  310. tan/templates/vendored/sensor/E1M-AEN801/README.md +112 -0
  311. tan/templates/vendored/sensor/E1M-AEN801/board.yaml +57 -0
  312. tan/templates/vendored/sensor/E1M-AEN801/boards/native_sim_native_64.conf +10 -0
  313. tan/templates/vendored/sensor/E1M-AEN801/boards/native_sim_native_64.overlay +28 -0
  314. tan/templates/vendored/sensor/E1M-AEN801/prj.conf +5 -0
  315. tan/templates/vendored/sensor/E1M-AEN801/src/main.c +186 -0
  316. tan/templates/vendored/sensor/E1M-AEN801/testcase.yaml +52 -0
  317. tan/templates/vendored/sensor/E1M-V2N101/CMakeLists.txt +8 -0
  318. tan/templates/vendored/sensor/E1M-V2N101/README.md +112 -0
  319. tan/templates/vendored/sensor/E1M-V2N101/board.yaml +57 -0
  320. tan/templates/vendored/sensor/E1M-V2N101/boards/native_sim_native_64.conf +10 -0
  321. tan/templates/vendored/sensor/E1M-V2N101/boards/native_sim_native_64.overlay +28 -0
  322. tan/templates/vendored/sensor/E1M-V2N101/prj.conf +5 -0
  323. tan/templates/vendored/sensor/E1M-V2N101/src/main.c +186 -0
  324. tan/templates/vendored/sensor/E1M-V2N101/testcase.yaml +52 -0
  325. tan/version.py +102 -0
  326. tan_cli-0.7.0.dist-info/METADATA +125 -0
  327. tan_cli-0.7.0.dist-info/RECORD +330 -0
  328. tan_cli-0.7.0.dist-info/WHEEL +5 -0
  329. tan_cli-0.7.0.dist-info/entry_points.txt +2 -0
  330. tan_cli-0.7.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,38 @@
1
+ # board.yaml -- per-app project configuration for the
2
+ # board-selftest example.
3
+ #
4
+ # A board bring-up / self-test app: reads the SoM + SoC identity,
5
+ # reads the RUN operating-point profile (core rail + clock), and
6
+ # scans the on-module I2C management bus, then prints a pass/fail
7
+ # report. Portable <alp/*> APIs only -- no chip driver, so the
8
+ # SAME source runs on every E1M family; the checks degrade
9
+ # gracefully (ALP_ERR_NOSUPPORT) on a backend that lacks a probe.
10
+ #
11
+ # Customer workflow: `tan init --from-example bringup/board-selftest`, change `som.sku` to
12
+ # your MPN, edit the `preset:` (or use an inline board) if you're on a non-EVK board,
13
+ # and `tan build`, which plans alp.conf from this file; twister and a bare
14
+ # west build read the pre-generated generated/alp.conf instead
15
+ # (`tan generate --target zephyr-conf`, see README.md).
16
+ som:
17
+ sku: E1M-V2N101
18
+
19
+ preset: e1m-x-evk
20
+ supported_boards:
21
+ - e1m-evk
22
+ - e1m-x-evk
23
+
24
+ # E1M pads this app uses (subset of the EVK preset's `e1m_routes:`).
25
+ # The self-test scans this bus for ACKing devices; it is also the
26
+ # bus the SoM EEPROM identity manifest lives on.
27
+ pins:
28
+ - { e1m: E1M_X_I2C0, macro: XEVK_I2C_BUS_SENSORS, doc: "On-board sensor + IO-expander + INA236 bus (ICM-42670, BMI323, BMP581, TCAL9538, INA236)." }
29
+ cores:
30
+ m33_sm:
31
+ app: ./src
32
+ # Zephyr peripheral subsystem exercised by this example. The
33
+ # loader translates the entry to CONFIG_I2C=y in alp.conf.
34
+ peripherals:
35
+ - i2c
36
+
37
+ diagnostics:
38
+ log_level: info
@@ -0,0 +1,11 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ #
3
+ # native_sim has no real I2C controller; pull in the emul I2C
4
+ # driver so the management bus enumerates at boot and the address
5
+ # scan can probe every 7-bit address (each NACKs because no target
6
+ # is registered -- so the scan reports 0 devices, which is still a
7
+ # PASS of the scan machinery). Auto-loaded by Zephyr when building
8
+ # for native_sim/native/64.
9
+
10
+ CONFIG_EMUL=y
11
+ CONFIG_I2C_EMUL=y
@@ -0,0 +1,29 @@
1
+ /*
2
+ * Copyright 2026 Alp Lab AB
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ *
5
+ * One emulated I2C bus exposed via the alp-i2c0 alias. No emul
6
+ * targets are attached, so every address in the scan NACKs -- but
7
+ * the open / probe-loop / close path runs end-to-end and the
8
+ * harness latches on the `[selftest] done` marker. The identity
9
+ * and power checks have no native_sim backend and report SKIP.
10
+ */
11
+
12
+ #include <zephyr/dt-bindings/i2c/i2c.h>
13
+
14
+ / {
15
+ aliases {
16
+ alp-i2c0 = &i2c0_emul;
17
+ };
18
+
19
+ soc {
20
+ i2c0_emul: i2c@100 {
21
+ compatible = "zephyr,i2c-emul-controller";
22
+ status = "okay";
23
+ reg = <0 0x100 4>;
24
+ #address-cells = <1>;
25
+ #size-cells = <0>;
26
+ clock-frequency = <I2C_BITRATE_STANDARD>;
27
+ };
28
+ };
29
+ };
@@ -0,0 +1,5 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ #
3
+ # Intentionally empty. Every CONFIG_* this app needs is derived
4
+ # from board.yaml by `tan build` and layered in via
5
+ # EXTRA_CONF_FILE (see README.md: `tan generate --target zephyr-conf`).
@@ -0,0 +1,266 @@
1
+ /*
2
+ * Copyright 2026 Alp Lab AB
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ *
5
+ * board-selftest -- power-on board bring-up / self-test.
6
+ *
7
+ * The app a customer runs FIRST on a freshly-assembled board,
8
+ * before chasing a peripheral that "doesn't work". It answers the
9
+ * four questions every bring-up starts with:
10
+ *
11
+ * 1. Is this the SoM I think it is? (on-module EEPROM identity)
12
+ * 2. Is the silicon alive + answering? (SoC secure-firmware ping)
13
+ * 3. Is the core rail/clock sane? (RUN operating-point profile)
14
+ * 4. What's actually on the I2C bus? (7-bit address scan)
15
+ *
16
+ * ...and prints a single pass/fail line so a field tech can read
17
+ * "3 PASS, 1 SKIP, 0 FAIL" off a serial console without a debugger.
18
+ *
19
+ * Portability: this uses ONLY portable <alp/...> APIs -- no chip
20
+ * driver, no vendor header -- so the SAME source builds and runs on
21
+ * every E1M family (Ring 1). Each check that a given backend can't
22
+ * service returns @ref ALP_ERR_NOSUPPORT, which the self-test
23
+ * reports as SKIP (not FAIL): "this backend has no probe for this",
24
+ * not "the hardware is broken". That distinction is the whole point
25
+ * of a self-test -- a missing capability and a fault must not look
26
+ * alike.
27
+ *
28
+ * What success looks like (real hardware, E1M-V2N101):
29
+ *
30
+ * [selftest] === board self-test ===
31
+ * [selftest] SoM identity: E1M-V2N101 rev r1 sn <factory-serial> -> PASS
32
+ * [selftest] SoC identity: renesas:rzv2n:n44 (secure-fw OK) -> PASS
33
+ * [selftest] power profile: RUN core 800 mV @ 400 MHz -> PASS
34
+ * [selftest] i2c scan BOARD_I2C_SENSORS: probing 0x08..0x77
35
+ * [selftest] found device @ 0x48
36
+ * [selftest] i2c scan BOARD_I2C_SENSORS: 1 device(s) -> PASS
37
+ * [selftest] result: 4 PASS, 0 SKIP, 0 FAIL
38
+ * [selftest] done
39
+ *
40
+ * On native_sim (CI lane): the SoC and power controllers have no
41
+ * backend, so checks 2-3 return ALP_ERR_NOSUPPORT and report SKIP.
42
+ * The emul I2C bus IS up (so check 1 talks to it) but no EEPROM
43
+ * target is registered, so alp_hw_info_read returns
44
+ * ALP_ERR_NOT_READY -- a genuine "identity manifest unreadable"
45
+ * fault, reported as FAIL (the check can't tell "no EEPROM here"
46
+ * from "broken EEPROM"; on real silicon a NAKing manifest IS a
47
+ * fault). The scan then walks the empty bus and PASSes with 0
48
+ * devices. The `[selftest] done` marker latches the harness
49
+ * regardless of the verdict.
50
+ */
51
+
52
+ #include <stdint.h>
53
+ #include <stdio.h>
54
+
55
+ #include "alp/hw_info.h"
56
+ #include "alp/peripheral.h"
57
+ #include "alp/power.h"
58
+
59
+ /* BOARD_I2C_SENSORS is a portable cross-EVK alias from <alp/board.h>:
60
+ * E1M EVK -> EVK_I2C_BUS_SENSORS -> ALP_E1M_I2C0
61
+ * E1M-X EVK -> XEVK_I2C_BUS_SENSORS -> ALP_E1M_X_I2C0
62
+ * Rebind it in board.yaml `pins:` to port to another board. */
63
+ #include "alp/board.h"
64
+
65
+ /* 7-bit I2C address scan window. 0x00..0x07 and 0x78..0x7F are
66
+ * reserved by the I2C spec (general-call, 10-bit prefixes, etc.);
67
+ * probing them is meaningless, so a scan walks 0x08..0x77 -- the
68
+ * same window i2cdetect uses by default. */
69
+ #define I2C_SCAN_FIRST_ADDR 0x08u
70
+ #define I2C_SCAN_LAST_ADDR 0x77u
71
+
72
+ /* Per-check verdict. SKIP is deliberately distinct from FAIL: a
73
+ * backend that has no probe for a capability (ALP_ERR_NOSUPPORT)
74
+ * has not FAILED the board -- it simply cannot answer. A field
75
+ * tech reading the report must not confuse the two. */
76
+ typedef enum {
77
+ CHECK_PASS = 0,
78
+ CHECK_SKIP = 1,
79
+ CHECK_FAIL = 2,
80
+ } check_result_t;
81
+
82
+ /* Running tally, printed as the last report line. */
83
+ typedef struct {
84
+ unsigned pass;
85
+ unsigned skip;
86
+ unsigned fail;
87
+ } tally_t;
88
+
89
+ /* Fold one check's verdict into the tally. */
90
+ static void tally_add(tally_t *t, check_result_t r)
91
+ {
92
+ switch (r) {
93
+ case CHECK_PASS:
94
+ t->pass++;
95
+ break;
96
+ case CHECK_SKIP:
97
+ t->skip++;
98
+ break;
99
+ default:
100
+ t->fail++;
101
+ break;
102
+ }
103
+ }
104
+
105
+ /* Map a status the identity/power checks return onto a verdict.
106
+ * NOSUPPORT means "no probe on this backend" -> SKIP; any other
107
+ * non-OK means the probe existed but the read went wrong -> FAIL. */
108
+ static check_result_t verdict_from_status(alp_status_t s)
109
+ {
110
+ if (s == ALP_OK) {
111
+ return CHECK_PASS;
112
+ }
113
+ if (s == ALP_ERR_NOSUPPORT) {
114
+ return CHECK_SKIP;
115
+ }
116
+ return CHECK_FAIL;
117
+ }
118
+
119
+ /* Check 1 -- SoM identity from the on-module EEPROM manifest.
120
+ * A blank EEPROM (NOT_PROVISIONED), a NAKing/absent one (NOT_READY),
121
+ * or a corrupt one (IO) is a real fault on hardware, reported as
122
+ * FAIL. Only NOSUPPORT -- no EEPROM bus configured on this build at
123
+ * all -- is a SKIP. On native_sim the emul bus is up but carries no
124
+ * EEPROM target, so this returns NOT_READY and FAILs; that is
125
+ * honest (native_sim genuinely has no identity manifest), and the
126
+ * done-marker still latches. */
127
+ static check_result_t check_som_identity(void)
128
+ {
129
+ alp_hw_info_t info;
130
+ alp_status_t s = alp_hw_info_read(&info);
131
+ if (s == ALP_OK) {
132
+ printf("[selftest] SoM identity: %s rev %s sn %s -> PASS\n",
133
+ info.som_sku,
134
+ info.som_hw_rev,
135
+ info.som_serial);
136
+ return CHECK_PASS;
137
+ }
138
+ /* NOT_PROVISIONED / IO / NOT_READY are genuine board faults;
139
+ * NOSUPPORT is "no EEPROM bus on this build" (e.g. native_sim). */
140
+ printf("[selftest] SoM identity: unreadable (%s) -> %s\n",
141
+ alp_status_name(s),
142
+ s == ALP_ERR_NOSUPPORT ? "SKIP" : "FAIL");
143
+ return verdict_from_status(s);
144
+ }
145
+
146
+ /* Check 2 -- SoC liveness + identity. The ping proves the secure /
147
+ * system-controller firmware answers before we trust any identity
148
+ * read; soc_ref is always populated (it's a build-time constant), so
149
+ * we print it even when the runtime query can't reach the
150
+ * controller. */
151
+ static check_result_t check_soc_identity(void)
152
+ {
153
+ alp_status_t ping = alp_soc_secure_fw_ping();
154
+
155
+ alp_soc_info_t soc;
156
+ alp_status_t s = alp_soc_info_read(&soc);
157
+ if (s == ALP_OK) {
158
+ printf("[selftest] SoC identity: %s (secure-fw %s) -> PASS\n",
159
+ soc.soc_ref,
160
+ soc.secure_fw_version);
161
+ return CHECK_PASS;
162
+ }
163
+ /* soc_ref is filled even on NOSUPPORT, so name the silicon
164
+ * regardless -- it's the single most useful line for "did I
165
+ * flash the firmware for the right chip?". */
166
+ printf("[selftest] SoC identity: %s (ping %s, read %s) -> %s\n",
167
+ soc.soc_ref,
168
+ alp_status_name(ping),
169
+ alp_status_name(s),
170
+ s == ALP_ERR_NOSUPPORT ? "SKIP" : "FAIL");
171
+ return verdict_from_status(s);
172
+ }
173
+
174
+ /* Check 3 -- read the RUN operating-point profile. This is a
175
+ * read-only mailbox round-trip on SoCs whose power tree lives behind
176
+ * a controller; it never changes the live operating point (that's
177
+ * alp_power_profile_set, which we deliberately do NOT call in a
178
+ * self-test). A zero field means "not reported", which is fine. */
179
+ static check_result_t check_power_profile(void)
180
+ {
181
+ alp_power_profile_t prof;
182
+ alp_status_t s = alp_power_profile_get(ALP_POWER_PROFILE_RUN, &prof);
183
+ if (s == ALP_OK) {
184
+ /* cpu_clk_hz is Hz; print MHz for readability. Integer
185
+ * division is fine -- a self-test wants "roughly 400 MHz",
186
+ * not sub-Hz precision. */
187
+ printf("[selftest] power profile: RUN core %u mV @ %u MHz -> PASS\n",
188
+ prof.rail_mv,
189
+ prof.cpu_clk_hz / 1000000u);
190
+ return CHECK_PASS;
191
+ }
192
+ printf("[selftest] power profile: unavailable (%s) -> %s\n",
193
+ alp_status_name(s),
194
+ s == ALP_ERR_NOSUPPORT ? "SKIP" : "FAIL");
195
+ return verdict_from_status(s);
196
+ }
197
+
198
+ /* Check 4 -- scan the management I2C bus for ACKing devices.
199
+ * A 1-byte read is the least-intrusive probe: a present device
200
+ * ACKs its address (ALP_OK), an empty address NACKs (ALP_ERR_IO).
201
+ * We don't interpret the byte -- only the ACK matters for presence.
202
+ *
203
+ * Verdict policy: the SCAN itself passing/failing is about whether
204
+ * the BUS works, not about how many devices answered. Zero devices
205
+ * on native_sim (no emul targets attached) is still a PASS of the
206
+ * scan machinery; a NULL bus handle (alias unset / no controller)
207
+ * is the SKIP/FAIL case. */
208
+ static check_result_t check_i2c_bus(void)
209
+ {
210
+ alp_i2c_t *bus = alp_i2c_open(&(alp_i2c_config_t){
211
+ .bus_id = BOARD_I2C_SENSORS,
212
+ .bitrate_hz = 100000, /* 100 kHz -- the safe baseline for a bus
213
+ whose device mix we don't yet know. */
214
+ });
215
+ if (bus == NULL) {
216
+ /* No alp-i2c0 alias / no controller on this build. */
217
+ alp_status_t s = alp_last_error();
218
+ printf("[selftest] i2c scan BOARD_I2C_SENSORS: open failed (%s) -> %s\n",
219
+ alp_status_name(s),
220
+ s == ALP_ERR_NOSUPPORT ? "SKIP" : "FAIL");
221
+ return s == ALP_ERR_NOSUPPORT ? CHECK_SKIP : CHECK_FAIL;
222
+ }
223
+
224
+ unsigned found = 0;
225
+ printf("[selftest] i2c scan BOARD_I2C_SENSORS: probing 0x%02x..0x%02x\n",
226
+ I2C_SCAN_FIRST_ADDR,
227
+ I2C_SCAN_LAST_ADDR);
228
+ for (uint8_t addr = I2C_SCAN_FIRST_ADDR; addr <= I2C_SCAN_LAST_ADDR; addr++) {
229
+ uint8_t byte = 0;
230
+ alp_status_t s = alp_i2c_read(bus, addr, &byte, sizeof(byte));
231
+ if (s == ALP_OK) {
232
+ printf("[selftest] found device @ 0x%02x\n", addr);
233
+ found++;
234
+ }
235
+ }
236
+
237
+ alp_i2c_close(bus);
238
+ printf("[selftest] i2c scan BOARD_I2C_SENSORS: %u device(s) -> PASS\n", found);
239
+ return CHECK_PASS;
240
+ }
241
+
242
+ int main(void)
243
+ {
244
+ /* Bring up the SDK runtime before anything else -- thin today,
245
+ * but future backends rely on it (see <alp/peripheral.h>). */
246
+ (void)alp_init();
247
+
248
+ printf("[selftest] === board self-test ===\n");
249
+
250
+ tally_t t = { 0 };
251
+ tally_add(&t, check_som_identity());
252
+ tally_add(&t, check_soc_identity());
253
+ tally_add(&t, check_power_profile());
254
+ tally_add(&t, check_i2c_bus());
255
+
256
+ /* One machine-readable summary line. A test harness or a field
257
+ * script greps this; a human reads the per-check lines above. */
258
+ printf("[selftest] result: %u PASS, %u SKIP, %u FAIL\n", t.pass, t.skip, t.fail);
259
+
260
+ /* The `done` marker latches the twister console harness
261
+ * regardless of the verdict -- a self-test that FAILS is still a
262
+ * successful RUN of the self-test. Real firmware might instead
263
+ * pull a GPIO or refuse to continue booting on a FAIL. */
264
+ printf("[selftest] done\n");
265
+ return 0;
266
+ }
@@ -0,0 +1,53 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ sample:
4
+ name: board-selftest
5
+ description: |
6
+ Board bring-up / self-test. Reads the SoM + SoC identity, reads
7
+ the RUN operating-point profile, and scans the on-module I2C
8
+ management bus, then prints a pass/fail report. Portable
9
+ <alp/*> APIs only -- no chip driver -- so the same source runs
10
+ on every E1M family. On native_sim the identity/power checks
11
+ have no backend and report SKIP; the emul I2C bus scans clean.
12
+
13
+ tests:
14
+ alp_sdk.example.board_selftest.e1m_x_evk:
15
+ extra_args: EXTRA_CONF_FILE=generated/alp.conf
16
+ platform_allow:
17
+ - native_sim
18
+ - native_sim/native/64
19
+ integration_platforms:
20
+ - native_sim/native/64
21
+ extra_configs:
22
+ - 'CONFIG_COMPILER_OPT="-DALP_BOARD_E1M_X_EVK"'
23
+ tags:
24
+ - alp-sdk
25
+ - example
26
+ - bringup
27
+ - selftest
28
+ - v2n
29
+ harness: console
30
+ harness_config:
31
+ type: one_line
32
+ regex:
33
+ - "\\[selftest\\] done"
34
+ alp_sdk.example.board_selftest.e1m_evk:
35
+ extra_args: EXTRA_CONF_FILE=generated/alp.conf
36
+ platform_allow:
37
+ - native_sim
38
+ - native_sim/native/64
39
+ integration_platforms:
40
+ - native_sim/native/64
41
+ extra_configs:
42
+ - 'CONFIG_COMPILER_OPT="-DALP_BOARD_E1M_EVK"'
43
+ tags:
44
+ - alp-sdk
45
+ - example
46
+ - bringup
47
+ - selftest
48
+ - aen
49
+ harness: console
50
+ harness_config:
51
+ type: one_line
52
+ regex:
53
+ - "\\[selftest\\] done"
@@ -0,0 +1,10 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ cmake_minimum_required(VERSION 3.20.0)
3
+
4
+ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5
+ project(cold_chain_monitor LANGUAGES C)
6
+
7
+ target_sources(app PRIVATE
8
+ src/main.c
9
+ src/cold_chain.c
10
+ )
@@ -0,0 +1,75 @@
1
+ # cold-chain-monitor
2
+
3
+ > **`[UNTESTED]` on hardware -- v0.9 paper-correct.** The `cold_chain` core
4
+ > is host-unit-tested on `native_sim/native/64`; the full app runs end-to-end on
5
+ > native_sim with synthetic environment data covering the states. HiL with a
6
+ > real BME280 + a trained model is bench-gated.
7
+
8
+ A pharma/food **cold-chain integrity monitor**: sample a BME280 T/RH/P sensor on
9
+ a slow logging cadence, compute the standards-backed metrics (temperature
10
+ excursion time, Mean Kinetic Temperature, dewpoint), classify the integrity
11
+ state, and emit an AI anomaly score. The *environmental* edge-AI vertical.
12
+
13
+ ## Honest scope
14
+
15
+ A reference cold-chain logger. MKT, dewpoint, and excursion-time are the real,
16
+ recognized metrics; thresholds are configurable per product. **NOT** a certified
17
+ GxP / 21-CFR-Part-11 data logger -- no validated audit trail, no calibration
18
+ traceability, no tamper-proof storage.
19
+
20
+ ## Standards-backed metrics
21
+
22
+ - **MKT** (Mean Kinetic Temperature, ICH Q1A / USP <1079>): the single
23
+ temperature delivering the same cumulative thermal stress as the fluctuating
24
+ profile. `MKT >= arithmetic mean`, so a brief hot spike counts for more than
25
+ its duration -- which is the whole point.
26
+ - **Dewpoint** (Magnus): condensation / mould risk when ambient T nears it.
27
+
28
+ ## Pipeline
29
+
30
+ ```
31
+ BME280 (I2C) --window--> cold_chain (mean/min/max, MKT, dewpoint, excursion)
32
+ -> cc_classify (OK / TEMP_EXCURSION / MKT_EXCEEDED / CONDENSATION_RISK)
33
+ -> <alp/inference.h> anomaly score (deterministic fallback) -> CC record
34
+ ```
35
+
36
+ ## Output
37
+
38
+ ```
39
+ # CC,t_s,state,temp_c,rh_pct,dewpoint_c,mkt_c,excursion_min
40
+ CC,256.0,OK,5.0,50.0,-4.6,5.0,0.0
41
+ CC,768.0,CONDENSATION_RISK,5.0,95.0,4.3,5.0,0.0
42
+ ```
43
+
44
+ ## Build
45
+
46
+ ```
47
+ # writes ./generated/alp.conf, which west reads below (#866)
48
+ tan generate --target zephyr-conf --core m55_hp --sdk-root "$ALP_SDK_ROOT" --output generated/alp.conf
49
+ west build -b alp_e1m_aen801_m55_hp/ae822fa0e5597ls0/rtss_hp . -- -DEXTRA_CONF_FILE=generated/alp.conf
50
+ west flash
51
+ ```
52
+
53
+ For the DEEPX DX-M1 path, re-scaffold rather than edit: `tan init --template
54
+ edge-ai-starter --som E1M-V2M101`. Flipping `som.sku` alone leaves `preset:`,
55
+ `cores:` and `pins:` pinned to this module (`e1m-evk`, which does not host
56
+ the `renesas-rzv2n-deepx` family) and `tan validate` refuses it.
57
+
58
+ ## Model
59
+
60
+ <!-- The ../cold-chain-monitor/ detour is deliberate: the scaffold
61
+ rewriter's _RELATIVE_LINK_RE only matches `../`-prefixed links, and
62
+ models/ is a child of this dir, not a sibling -- don't "fix" this. -->
63
+
64
+ No model is shipped (stub + deterministic classifier/fallback). See
65
+ [`models/README.md`](https://github.com/alplabai/alp-sdk/blob/v0.17.0/examples/ai/cold-chain-monitor/models/README.md) for the
66
+ autoencoder training recipe.
67
+
68
+ ## Tests
69
+
70
+ In the alp-sdk tree, unit tests live in
71
+ [`tests/unit/cold_chain`](https://github.com/alplabai/alp-sdk/tree/v0.17.0/tests/unit/cold_chain) and run with:
72
+
73
+ ```
74
+ twister -p native_sim/native/64 -T tests/unit/cold_chain
75
+ ```
@@ -0,0 +1,38 @@
1
+ # board.yaml -- cold-chain integrity monitor.
2
+ #
3
+ # A low-power M55 node reads the on-board BME280 temperature/humidity/pressure
4
+ # sensor on a slow logging cadence, computes the cold-chain metrics (MKT,
5
+ # dewpoint, excursion time), and classifies the integrity state. The V2N
6
+ # DEEPX path is a separate scaffold (--som E1M-V2M101), not a som.sku flip
7
+ # here -- see this project's README.
8
+
9
+ libraries:
10
+ - name: tflite-micro
11
+ cores: [m55_hp]
12
+
13
+ som:
14
+ sku: E1M-AEN801
15
+
16
+ preset: e1m-evk
17
+ supported_boards:
18
+ - e1m-evk
19
+ - e1m-x-evk
20
+
21
+ pins:
22
+ - { e1m: E1M_I2C0, macro: EVK_I2C_BUS_SENSORS, doc: "BME280 environment sensor bus" }
23
+
24
+ cores:
25
+ a32_cluster:
26
+ os: "off"
27
+ m55_hp:
28
+ app: ./src
29
+ inference:
30
+ default_arena_kib: 64
31
+ peripherals:
32
+ - i2c # BME280 link.
33
+
34
+ chips:
35
+ - bme280 # temperature / humidity / pressure.
36
+
37
+ diagnostics:
38
+ log_level: info
@@ -0,0 +1,8 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ CONFIG_MAIN_STACK_SIZE=16384
3
+
4
+ CONFIG_LOG=y
5
+ CONFIG_LOG_PRINTK=y
6
+ CONFIG_CBPRINTF_FP_SUPPORT=y
7
+
8
+ CONFIG_ALP_SDK_INFERENCE_BACKEND_TFLM=y