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,185 @@
1
+ /*
2
+ * Copyright 2026 Alp Lab AB
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ *
5
+ * mproc-mailbox -- M55-HP <-> M55-HE shared-memory mailbox
6
+ * roundtrip on AEN (Alif Ensemble dual-Cortex-M55 silicon).
7
+ *
8
+ * The pattern this example shows
9
+ * ==============================
10
+ *
11
+ * Two Cortex-M55 cores share a small region of non-cached
12
+ * SRAM + a hardware mailbox + a hardware semaphore. An app on
13
+ * the M55-HP (the "application" core) sends a payload to the
14
+ * M55-HE (the "high-efficiency" peer) and waits for a reply.
15
+ *
16
+ * 1. HP owns the application: Wi-Fi, MQTT, UI.
17
+ * 2. HE owns offloadable work: PDM/audio DSP, slow sensor
18
+ * polling, inference pre/post-processing.
19
+ * 3. Mailbox + shared memory are how HP hands work to HE and
20
+ * collects results.
21
+ *
22
+ * The SDK exposes this through <alp/mproc.h>. Same API on AEN
23
+ * (HP<->HE) and on V2N (Cortex-A55 <-> Cortex-M33); the
24
+ * backend dispatches to the silicon's hardware mailbox.
25
+ *
26
+ * What you'll see in this example
27
+ * ===============================
28
+ *
29
+ * [mproc] init mbox + shmem
30
+ * [mproc] sending payload "hello-from-HP" (13 bytes)
31
+ * [mproc] HE replied via mbox callback
32
+ * [mproc] HE replied "echo: hello-from-HP" (19 bytes)
33
+ * [mproc] done
34
+ *
35
+ * Under native_sim there's no peer core; the example exercises
36
+ * just the HP-side init + the framing-encode path + `done`.
37
+ * Real-silicon runs both halves.
38
+ *
39
+ * Peer firmware
40
+ * =============
41
+ *
42
+ * The HE-side application lives at
43
+ * `https://github.com/alplabai/alp-sdk/blob/v0.17.0/examples/multicore/mproc-mailbox/peer/main.c`. Both halves build
44
+ * standalone via `west build`, and `board.yaml` declaring both
45
+ * `m55_hp` and `m55_he` as real project cores means one `tan build`
46
+ * already produces both images through the orchestrator's existing
47
+ * multi-slice path -- no sysbuild involved.
48
+ */
49
+
50
+ #include <stdio.h>
51
+ #include <string.h>
52
+
53
+ #include "alp/mproc.h"
54
+ #include "alp/peripheral.h"
55
+
56
+ /* Region name resolved against the alp-shmemN DT aliases in the
57
+ * board overlay -- here, alp-shmem0 in boards/<board>.overlay or
58
+ * the orchestrator-emitted carve-out for AEN dual-core builds. */
59
+ #define SHMEM_REGION_NAME "alp_shmem0"
60
+ #define SHMEM_REGION_SIZE 512u
61
+ #define MBOX_CHANNEL 0u
62
+ #define REQUEST_OFFSET 0u
63
+ #define RESPONSE_OFFSET 256u /* gap from request so the two never overlap */
64
+ #define MAX_PAYLOAD 128u
65
+
66
+ static const char *PAYLOAD = "hello-from-HP";
67
+
68
+ static struct {
69
+ volatile bool got_reply;
70
+ volatile size_t reply_offset;
71
+ volatile size_t reply_len;
72
+ } g_state;
73
+
74
+ /* Mailbox inbound-message callback. Fires when the HE peer
75
+ * signals back with the (offset, length) tuple naming the
76
+ * staged echo response. Runs on the SDK's mbox thread; we
77
+ * just stash the values so main() can drain them. */
78
+ static void mbox_inbound(uint32_t channel, const void *data, size_t len, void *user)
79
+ {
80
+ (void)channel;
81
+ (void)user;
82
+ if (len < 8u) return;
83
+ const uint8_t *b = data;
84
+ g_state.reply_offset =
85
+ (size_t)b[0] | ((size_t)b[1] << 8) | ((size_t)b[2] << 16) | ((size_t)b[3] << 24);
86
+ g_state.reply_len =
87
+ (size_t)b[4] | ((size_t)b[5] << 8) | ((size_t)b[6] << 16) | ((size_t)b[7] << 24);
88
+ g_state.got_reply = true;
89
+ }
90
+
91
+ int main(void)
92
+ {
93
+ printf("[mproc] init mbox + shmem\n");
94
+
95
+ const alp_shmem_config_t shmem_cfg = {
96
+ .name = SHMEM_REGION_NAME,
97
+ .size = SHMEM_REGION_SIZE,
98
+ };
99
+ alp_shmem_t *shmem = alp_shmem_open(&shmem_cfg);
100
+
101
+ const alp_mbox_config_t mbox_cfg = {
102
+ .channel = MBOX_CHANNEL,
103
+ .peer = ALP_CORE_M55_HE,
104
+ };
105
+ alp_mbox_t *mbox = alp_mbox_open(&mbox_cfg);
106
+
107
+ if (shmem == NULL || mbox == NULL) {
108
+ printf("[mproc] open failed: last_err=%d\n", (int)alp_last_error());
109
+ goto done;
110
+ }
111
+
112
+ /* Get a pointer view of the shared region. Both cores see
113
+ * the same physical bytes; the region is non-cacheable,
114
+ * so no cache flush is needed. */
115
+ void *shmem_base = NULL;
116
+ size_t shmem_size = 0u;
117
+ if (alp_shmem_view(shmem, &shmem_base, &shmem_size) != ALP_OK) {
118
+ printf("[mproc] shmem view failed\n");
119
+ goto teardown;
120
+ }
121
+ if (shmem_size < RESPONSE_OFFSET + MAX_PAYLOAD) {
122
+ printf("[mproc] shmem too small (%zu)\n", shmem_size);
123
+ goto teardown;
124
+ }
125
+
126
+ /* Stage the payload at REQUEST_OFFSET in the shared region.
127
+ * memcpy is the right primitive here -- the SDK's shmem
128
+ * surface gives back a raw pointer + size and trusts the
129
+ * caller to write through it. */
130
+ const size_t payload_len = strlen(PAYLOAD);
131
+ memcpy((uint8_t *)shmem_base + REQUEST_OFFSET, PAYLOAD, payload_len);
132
+
133
+ /* Send the mailbox notification. Payload here is the
134
+ * `(offset, length)` tuple that points at the staged bytes
135
+ * in shmem; the peer reads the actual data through its own
136
+ * shmem view. */
137
+ uint8_t mbox_msg[8] = {
138
+ (uint8_t)REQUEST_OFFSET, 0, 0, 0, /* offset (LE u32) */
139
+ (uint8_t)payload_len, 0, 0, 0, /* length (LE u32) */
140
+ };
141
+ if (alp_mbox_send(mbox, mbox_msg, sizeof(mbox_msg), 100u) != ALP_OK) {
142
+ printf("[mproc] mbox send failed\n");
143
+ goto teardown;
144
+ }
145
+ printf("[mproc] sending payload \"%s\" (%u bytes)\n", PAYLOAD, (unsigned)payload_len);
146
+
147
+ /* Register the receive callback before waiting. On real
148
+ * silicon the peer sends back via the same mbox; the
149
+ * callback drains the (offset, length) tuple naming the
150
+ * echo response. */
151
+ if (alp_mbox_set_callback(mbox, mbox_inbound, NULL) != ALP_OK) {
152
+ printf("[mproc] set_callback failed\n");
153
+ goto teardown;
154
+ }
155
+
156
+ #ifdef CONFIG_BOARD_NATIVE_SIM
157
+ printf("[mproc] native_sim: no peer core; skipping reply wait\n");
158
+ #else
159
+ /* Poll for the reply. On HiL the mailbox-ISR-driven
160
+ * callback flips g_state.got_reply within ~1 ms of the
161
+ * peer's send. */
162
+ for (int i = 0; i < 100 && !g_state.got_reply; ++i) {
163
+ alp_delay_ms(10);
164
+ }
165
+ if (!g_state.got_reply) {
166
+ printf("[mproc] reply timeout (peer not running?)\n");
167
+ goto teardown;
168
+ }
169
+ printf("[mproc] HE replied via mbox callback\n");
170
+
171
+ if (g_state.reply_len > MAX_PAYLOAD) g_state.reply_len = MAX_PAYLOAD;
172
+ char reply_buf[MAX_PAYLOAD + 1];
173
+ memcpy(reply_buf, (uint8_t *)shmem_base + g_state.reply_offset, g_state.reply_len);
174
+ reply_buf[g_state.reply_len] = '\0';
175
+ printf("[mproc] HE replied \"%s\" (%u bytes)\n", reply_buf, (unsigned)g_state.reply_len);
176
+ #endif
177
+
178
+ teardown:
179
+ alp_mbox_close(mbox);
180
+ alp_shmem_close(shmem);
181
+
182
+ done:
183
+ printf("[mproc] done\n");
184
+ return 0;
185
+ }
@@ -0,0 +1,26 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ sample:
4
+ name: mproc-mailbox
5
+ description: |
6
+ AEN M55-HP side of a Cortex-M55 mailbox + shared-memory
7
+ roundtrip via <alp/mproc.h>. Under native_sim the example
8
+ exercises the HP-side init + alp_mbox_send framing path and
9
+ exits cleanly (no peer core to talk to). Real silicon
10
+ waits for the peer firmware to echo the payload back.
11
+ common:
12
+ tags: mproc shmem
13
+ harness: console
14
+ harness_config:
15
+ type: one_line
16
+ regex:
17
+ - "\\[mproc\\] done"
18
+ tests:
19
+ alp_sdk.examples.mproc_mailbox.native_sim:
20
+ platform_allow: native_sim/native/64
21
+ extra_args: EXTRA_CONF_FILE=generated/alp.conf CONFIG_ALP_SDK_MPROC=y # mproc surface is opt-in; the .aen sibling sets it too.
22
+ alp_sdk.examples.mproc_mailbox.aen:
23
+ platform_allow:
24
+ - ensemble_e8_dk/ae822fa0e5597ls0/rtss_he
25
+ extra_args: EXTRA_CONF_FILE=generated/alp.conf CONFIG_ALP_SDK_MPROC=y
26
+ build_only: true # real run needs the peer firmware (v0.4+).
@@ -0,0 +1,8 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ cmake_minimum_required(VERSION 3.20)
4
+
5
+ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6
+ project(i2c_master LANGUAGES C)
7
+
8
+ target_sources(app PRIVATE src/main.c)
@@ -0,0 +1,112 @@
1
+ # i2c-master
2
+
3
+ Discrete I2C master that reads a known device at a known
4
+ address. Pattern: open the bus, init the chip driver, loop
5
+ reading the sensor every second, close cleanly.
6
+
7
+ Contrasts with [`examples/peripheral-io/i2c-scanner`](https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/peripheral-io/i2c-scanner) -- the
8
+ scanner *probes* every 7-bit address for ACKs without knowing
9
+ what's behind them; this example *reads* a known sensor.
10
+
11
+ ## What this shows
12
+
13
+ * `alp_i2c_open()` -- open `BOARD_I2C_SENSORS` at 400 kHz Fast-mode.
14
+ The `<alp/board.h>` alias resolves to `ALP_E1M_I2C0` on the E1M
15
+ EVK and `ALP_E1M_X_I2C0` on the E1M-X EVK.
16
+ * `bmp581_init()` -- chip-driver probe (CHIP_ID check).
17
+ * `bmp581_set_sampling()` -- configure oversampling, ODR, and power mode.
18
+ * `bmp581_read_raw()` + `bmp581_compensate()` -- one pressure+temperature read per second.
19
+ * Error handling: NACK on probe -> graceful exit with diagnostic.
20
+ * `bmp581_deinit()` + `alp_i2c_close()` -- clean shutdown.
21
+
22
+ ## Hardware
23
+
24
+ The BMP581 barometer is the on-board sensor on `BOARD_I2C_SENSORS`
25
+ on both the E1M EVK (U14) and the E1M-X EVK, per
26
+ [`metadata/boards/e1m-evk.yaml`](https://github.com/alplabai/alp-sdk/blob/v0.17.0/metadata/boards/e1m-evk.yaml) and
27
+ [`metadata/boards/e1m-x-evk.yaml`](https://github.com/alplabai/alp-sdk/blob/v0.17.0/metadata/boards/e1m-x-evk.yaml)
28
+ `i2c_devices:`.
29
+
30
+ 7-bit address depends on the SDO strap:
31
+
32
+ | SDO strap | Address | On this bus |
33
+ |-----------|---------|---------------------------------------|
34
+ | VDDIO | 0x47 | E1M EVK U14 + E1M-X EVK (this default) |
35
+ | GND | 0x46 | (not populated on these EVKs) |
36
+
37
+ Both supported EVKs strap SDO to VDDIO, so `BMP581_ADDR_7BIT`
38
+ works unchanged across them (see
39
+ [`metadata/boards/e1m-evk.yaml`](https://github.com/alplabai/alp-sdk/blob/v0.17.0/metadata/boards/e1m-evk.yaml),
40
+ BMP581 datasheet BST-BMP581-DS004 s5.6, or
41
+ [`include/alp/chips/bmp581.h`](https://github.com/alplabai/alp-sdk/blob/v0.17.0/include/alp/chips/bmp581.h)).
42
+
43
+ > **#1269:** this example used to target the TMP112 temperature sensor,
44
+ > but TMP112 lives on **BRD_I2C**, not on `BOARD_I2C_SENSORS` -- opening
45
+ > `BOARD_I2C_SENSORS` and probing for TMP112 NACKs on real hardware.
46
+ > BRD_I2C is a separate controller instance regardless (on the E1M-AEN
47
+ > family it is SoC I2C0, function C -- #1848), so simply repointing the bus_id
48
+ > would still not reach a TMP112 there. See
49
+ > [`examples/v2n/v2n-temp-sensor`](https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/v2n/v2n-temp-sensor) for the
50
+ > V2N-only BRD_I2C/TMP112 pattern instead.
51
+
52
+ ## Build
53
+
54
+ ```bash
55
+ # Standalone, native_sim (emul I2C; bmp581_init NACKs cleanly):
56
+ # writes ./generated/alp.conf, which west reads below (#866)
57
+ tan generate --target zephyr-conf --core m55_hp --sdk-root "$ALP_SDK_ROOT" --output generated/alp.conf
58
+ west build -b native_sim/native/64 . \
59
+ -- -DEXTRA_CONF_FILE=generated/alp.conf -DEXTRA_ZEPHYR_MODULES=$ALP_SDK_ROOT
60
+ west build -t run
61
+
62
+ # On real silicon, point -b at the SoM's Zephyr board target.
63
+ # Example for E1M-AEN801:
64
+ west build -b alp_e1m_aen801_m55_hp/ae822fa0e5597ls0/rtss_hp . -- -DEXTRA_CONF_FILE=generated/alp.conf
65
+ west flash
66
+ ```
67
+
68
+ ## Expected output
69
+
70
+ Real hardware (BMP581 populated, room temperature, sea-level-ish pressure):
71
+
72
+ ```
73
+ [i2c-master] open BOARD_I2C_SENSORS @ 400 kHz
74
+ [i2c-master] bmp581_init @ 0x47 -> 0 (OK)
75
+ [i2c-master] sample 0: 96234 Pa, 23.625 degC
76
+ [i2c-master] sample 1: 96231 Pa, 23.687 degC
77
+ [i2c-master] sample 2: 96233 Pa, 23.625 degC
78
+ [i2c-master] sample 3: 96230 Pa, 23.687 degC
79
+ [i2c-master] sample 4: 96232 Pa, 23.750 degC
80
+ [i2c-master] done
81
+ ```
82
+
83
+ native_sim (emul I2C, no BMP581 registered):
84
+
85
+ ```
86
+ [i2c-master] open BOARD_I2C_SENSORS @ 400 kHz
87
+ [i2c-master] bmp581_init @ 0x47 -> -5 (populated? right address?)
88
+ [i2c-master] done
89
+ ```
90
+
91
+ ## Troubleshooting
92
+
93
+ * **`bmp581_init -> -5`** (ALP_ERR_IO / NACK). Either the chip
94
+ isn't populated on your board, the address is wrong (see
95
+ table above), or the bus is held low (missing pull-ups, stuck
96
+ slave). Run [`examples/peripheral-io/i2c-scanner`](https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/peripheral-io/i2c-scanner) to confirm what
97
+ ACKs.
98
+ * **`alp_i2c_open failed`** (NULL return). The `alp-i2c0` DT
99
+ alias isn't set -- check your board overlay or, for
100
+ native_sim, that `CONFIG_EMUL=y CONFIG_I2C_EMUL=y` and the
101
+ overlay we ship are picked up.
102
+ * **Garbled readings.** Wrong baud (bitrate) for the bus
103
+ capacitance. Drop from 400 kHz to 100 kHz to confirm.
104
+
105
+ ## Reference
106
+
107
+ - [`<alp/peripheral.h>`](https://github.com/alplabai/alp-sdk/blob/v0.17.0/include/alp/peripheral.h) I2C surface.
108
+ - [`<alp/chips/bmp581.h>`](https://github.com/alplabai/alp-sdk/blob/v0.17.0/include/alp/chips/bmp581.h) -- driver API.
109
+ - [`examples/peripheral-io/i2c-scanner/`](https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/peripheral-io/i2c-scanner) -- discovery companion.
110
+ - [`examples/peripheral-io/i2c-slave/`](https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/peripheral-io/i2c-slave) -- slave-mode companion, built on the `alp_i2c_target_*` surface.
111
+ - [`examples/v2n/v2n-temp-sensor/`](https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/v2n/v2n-temp-sensor) -- TMP112-on-BRD_I2C companion, V2N-only.
112
+ - BMP581 datasheet (BST-BMP581-DS004, rev 1.13).
@@ -0,0 +1,57 @@
1
+ # board.yaml -- per-app project configuration for the
2
+ # i2c-master example.
3
+ #
4
+ # Reads the BMP581 barometer on BOARD_I2C_SENSORS via the chip-
5
+ # driver header. Discrete master that talks to a known device at
6
+ # a known address -- contrasts with https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/peripheral-io/i2c-scanner which
7
+ # probes every 7-bit address for ACKs.
8
+ #
9
+ # Customer workflow: `tan init --from-example peripheral-io/i2c-master`, change `som.sku` to
10
+ # your MPN, edit the `preset:` (or use an inline board) if you're on a non-EVK board,
11
+ # and `tan build`, which plans alp.conf from this file; twister and a bare
12
+ # west build read the pre-generated generated/alp.conf instead
13
+ # (`tan generate --target zephyr-conf`, see README.md).
14
+ som:
15
+ sku: E1M-AEN801
16
+
17
+ preset: e1m-evk
18
+ supported_boards:
19
+ - e1m-evk
20
+ - e1m-x-evk
21
+
22
+ # E1M pads this app uses (subset of the EVK preset's `e1m_routes:`).
23
+ pins:
24
+ - { e1m: E1M_I2C0, macro: EVK_I2C_BUS_SENSORS, doc: "Shared sensor + IO-expander + INA236 bus" }
25
+ cores:
26
+ m55_hp:
27
+ app: ./src
28
+ # Zephyr peripheral subsystem exercised by this example. The
29
+ # loader translates the entry to CONFIG_I2C=y in alp.conf.
30
+ peripherals:
31
+ - i2c
32
+
33
+ # BMP581 is populated on every member of the AEN, V2N, V2N-M1
34
+ # families per alp-sdk's metadata/chips/bmp581.yaml (not part of
35
+ # this scaffolded project) -- so this example is Ring 2
36
+ # (chip-bound, multi-family) per
37
+ # alp-sdk's scripts/check_example_portability.py classification
38
+ # (also not part of this scaffolded project).
39
+ #
40
+ # NOTE (#1269): TMP112 was here previously, but TMP112 lives on
41
+ # BRD_I2C, not on BOARD_I2C_SENSORS -- see alp-sdk's
42
+ # metadata/boards/e1m-evk.yaml i2c_devices: and
43
+ # metadata/boards/e1m-x-evk.yaml i2c_devices: (not part of this
44
+ # scaffolded project), neither of which lists a TMP112 on the sensor
45
+ # bus this example opens. BRD_I2C
46
+ # is a SEPARATE controller instance from BOARD_I2C_SENSORS regardless
47
+ # (on the E1M-AEN family, BRD_I2C is SoC I2C0, function C -- #1848), so
48
+ # repointing the bus_id would still not reach a TMP112 there. BMP581 is
49
+ # the part that is actually on BOARD_I2C_SENSORS on both supported
50
+ # boards, at the same address (0x47) on each -- see
51
+ # https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/v2n/v2n-temp-sensor for the V2N-only BRD_I2C/TMP112 pattern
52
+ # instead.
53
+ chips:
54
+ - bmp581
55
+
56
+ diagnostics:
57
+ log_level: info
@@ -0,0 +1,10 @@
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 bus enumerates at boot and bmp581_init can probe
5
+ # (which returns NACK because no BMP581 is registered -- exactly
6
+ # the path the example's error-handling branch exercises).
7
+ # Auto-loaded by Zephyr when building for native_sim/native/64.
8
+
9
+ CONFIG_EMUL=y
10
+ CONFIG_I2C_EMUL=y
@@ -0,0 +1,28 @@
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 bmp581_init returns NACK -- but the
7
+ * open / probe / close path runs end-to-end and the harness
8
+ * latches on the `[i2c-master] done` marker.
9
+ */
10
+
11
+ #include <zephyr/dt-bindings/i2c/i2c.h>
12
+
13
+ / {
14
+ aliases {
15
+ alp-i2c0 = &i2c0_emul;
16
+ };
17
+
18
+ soc {
19
+ i2c0_emul: i2c@100 {
20
+ compatible = "zephyr,i2c-emul-controller";
21
+ status = "okay";
22
+ reg = <0 0x100 4>;
23
+ #address-cells = <1>;
24
+ #size-cells = <0>;
25
+ clock-frequency = <I2C_BITRATE_FAST>;
26
+ };
27
+ };
28
+ };
@@ -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,186 @@
1
+ /*
2
+ * Copyright 2026 Alp Lab AB
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ *
5
+ * i2c-master -- discrete I2C master that reads a known device at
6
+ * a known address.
7
+ *
8
+ * Pattern: open the bus, init the chip driver, loop reading the
9
+ * register every second, close cleanly. Contrasts with
10
+ * https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/peripheral-io/i2c-scanner which probes every 7-bit address for ACKs
11
+ * without knowing what's behind them.
12
+ *
13
+ * Hardware: the BMP581 barometer sits on BOARD_I2C_SENSORS on every
14
+ * E1M and E1M-X EVK, strapped to 7-bit address 0x47 (SDO -> VDDIO)
15
+ * on both -- see alp-sdk's metadata/boards/e1m-evk.yaml and
16
+ * metadata/boards/e1m-x-evk.yaml (not part of this scaffolded
17
+ * project) `i2c_devices:`. On a brand-new
18
+ * bring-up you may want to build and run the alp-sdk repo's
19
+ * https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/peripheral-io/i2c-scanner example first to confirm which
20
+ * address ACKs -- it isn't part of this scaffolded project.
21
+ *
22
+ * (#1269: this example used to target the TMP112 temperature
23
+ * sensor, but TMP112 lives on BRD_I2C, not on BOARD_I2C_SENSORS --
24
+ * opening BOARD_I2C_SENSORS and probing for TMP112 NACKs on real
25
+ * hardware. BRD_I2C is a separate controller instance regardless
26
+ * (on the E1M-AEN family it is SoC I2C0, function C -- #1848), so
27
+ * simply repointing the bus_id would still not reach a TMP112 there; see
28
+ * https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/v2n/v2n-temp-sensor for the V2N-only BRD_I2C/TMP112
29
+ * pattern.)
30
+ *
31
+ * What success looks like (real hardware):
32
+ *
33
+ * [i2c-master] open BOARD_I2C_SENSORS @ 400 kHz
34
+ * [i2c-master] bmp581_init @ 0x47 -> 0 (OK)
35
+ * [i2c-master] sample 0: 96234 Pa, 23.625 degC
36
+ * [i2c-master] sample 1: 96231 Pa, 23.687 degC
37
+ * ...
38
+ * [i2c-master] done
39
+ *
40
+ * On native_sim (CI lane) the alp-i2c0 alias maps to the emul I2C
41
+ * driver -- no BMP581 is registered as a target, so bmp581_init
42
+ * gets NACKed and the example exits with the diagnostic. Either
43
+ * way the [i2c-master] done marker latches the harness.
44
+ */
45
+
46
+ #include <stdio.h>
47
+
48
+ #include "alp/peripheral.h"
49
+ #include "alp/chips/bmp581.h"
50
+
51
+ /* BOARD_I2C_SENSORS is a portable cross-EVK alias from <alp/board.h>:
52
+ * E1M EVK -> EVK_I2C_BUS_SENSORS -> ALP_E1M_I2C0
53
+ * E1M-X EVK -> XEVK_I2C_BUS_SENSORS -> ALP_E1M_X_I2C0
54
+ * Rebind it in board.yaml `pins:` to port to another board. */
55
+ #include "alp/board.h"
56
+
57
+ /* BMP581 7-bit I2C address with SDO -> VDDIO -- the on-board strap
58
+ * on both the E1M EVK (U14) and E1M-X EVK (see alp-sdk's
59
+ * metadata/boards/e1m-evk.yaml / e1m-x-evk.yaml, not part of
60
+ * this scaffolded project, `i2c_devices:`).
61
+ * SDO -> GND gives 0x46 instead; see the BMP581 datasheet
62
+ * BST-BMP581-DS004 s5.6 or alp-sdk's include/alp/chips/bmp581.h
63
+ * (not part of this scaffolded project) if your board straps
64
+ * differently. */
65
+ #define BMP581_ADDR_7BIT BMP581_I2C_ADDR_HIGH /* 0x47 */
66
+
67
+ /* Number of samples to take before exiting. Capped so the
68
+ * native_sim build doesn't stall the twister harness; real
69
+ * firmware would loop forever. */
70
+ #define SAMPLE_COUNT 5u
71
+
72
+ /* Wait between samples. 50 Hz ODR (below) means a fresh reading
73
+ * every 20 ms; waiting a full second gives a comfortable margin
74
+ * and prints once per watch-tick which is easy on the eyes. */
75
+ #define SAMPLE_PERIOD_MS 1000u
76
+
77
+ int main(void)
78
+ {
79
+ /* Bring up the SDK runtime before anything else -- thin today,
80
+ * but future backends rely on it (see <alp/peripheral.h>). */
81
+ (void)alp_init();
82
+
83
+ printf("[i2c-master] open BOARD_I2C_SENSORS @ 400 kHz\n");
84
+
85
+ /* Open the bus at 400 kHz (I2C Fast-mode). BMP581 supports up
86
+ * to 1 MHz (Fast-mode Plus) per its datasheet, so 400 kHz is
87
+ * comfortably inside spec; the SDK rounds DOWN to the
88
+ * controller's closest achievable rate. 100 kHz is the safe
89
+ * baseline for unknown devices. */
90
+ alp_i2c_t *bus = alp_i2c_open(&(alp_i2c_config_t){
91
+ .bus_id = BOARD_I2C_SENSORS, /* E1M EVK: ALP_E1M_I2C0; E1M-X EVK: ALP_E1M_X_I2C0 */
92
+ .bitrate_hz = 400000,
93
+ });
94
+ if (bus == NULL) {
95
+ /* No alp-i2c0 alias on this build -> NULL handle.
96
+ *
97
+ * Common causes:
98
+ * * Board overlay forgot to set the alias.
99
+ * * SoM has no I2C0 routed (rare -- it's part of the
100
+ * portable E1M baseline).
101
+ * * On native_sim without the emul overlay we ship,
102
+ * the alias is unset. */
103
+ printf("[i2c-master] open failed: alp_last_error=%d\n", (int)alp_last_error());
104
+ printf("[i2c-master] done\n");
105
+ return 0;
106
+ }
107
+
108
+ /* Initialise the BMP581 driver. This reads CHIP_ID and verifies
109
+ * it matches BMP581_CHIP_ID -- catches the "wrong address" case
110
+ * (NACK on probe) up-front. If init fails the example exits
111
+ * cleanly -- maybe the chip isn't populated, maybe the address
112
+ * is wrong, maybe the bus is held low by another device.
113
+ * https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/peripheral-io/i2c-scanner can confirm which devices ACK. */
114
+ bmp581_t sensor;
115
+ alp_status_t s = bmp581_init(&sensor, bus, BMP581_ADDR_7BIT);
116
+ if (s != ALP_OK) {
117
+ /* Most-frequent failure modes:
118
+ * * ALP_ERR_IO -- bus error or NACK. No BMP581 here,
119
+ * wrong address, or pull-ups missing
120
+ * (the bus floats high without them).
121
+ * * ALP_ERR_INVAL -- bad argument (NULL ctx or NULL bus).
122
+ *
123
+ * Use the alp-sdk repo's https://github.com/alplabai/alp-sdk/tree/v0.17.0/examples/peripheral-io/i2c-scanner
124
+ * example to enumerate what IS on this bus before chasing a
125
+ * BMP581 that may not be populated. */
126
+ printf("[i2c-master] bmp581_init @ 0x%02x -> %d "
127
+ "(populated? right address?)\n",
128
+ BMP581_ADDR_7BIT,
129
+ (int)s);
130
+ alp_i2c_close(bus);
131
+ printf("[i2c-master] done\n");
132
+ return 0;
133
+ }
134
+ printf("[i2c-master] bmp581_init @ 0x%02x -> %d (OK)\n", BMP581_ADDR_7BIT, (int)s);
135
+
136
+ /* Configure oversampling + ODR + power mode in one call. x8
137
+ * oversampling at 50 Hz normal mode is a reasonable general-
138
+ * purpose default; reach for higher OSR when you want lower
139
+ * noise at the cost of more power/latency. */
140
+ s = bmp581_set_sampling(
141
+ &sensor, BMP581_OSR_X8, BMP581_OSR_X8, BMP581_ODR_50_HZ, BMP581_MODE_NORMAL);
142
+ if (s != ALP_OK) {
143
+ printf("[i2c-master] bmp581_set_sampling -> %d\n", (int)s);
144
+ /* Non-fatal: the chip stays at whatever mode init left it in. */
145
+ }
146
+
147
+ /* Sample loop: read SAMPLE_COUNT pressure+temperature pairs, one
148
+ * per second. Real-life firmware would publish each reading
149
+ * over MQTT, push to a ring buffer for trend analysis, or
150
+ * compare against an alert threshold and pull a GPIO. */
151
+ for (uint32_t i = 0; i < SAMPLE_COUNT; i++) {
152
+ bmp581_raw_t raw = { 0 };
153
+ bmp581_compensated_t comp = { 0 };
154
+ s = bmp581_read_raw(&sensor, &raw);
155
+ if (s == ALP_OK) {
156
+ s = bmp581_compensate(&raw, &comp);
157
+ }
158
+ if (s == ALP_OK) {
159
+ /* Format integer + fractional parts so we avoid float
160
+ * printf on M-class targets. temperature_c1000 is
161
+ * signed -- the fractional part takes the absolute
162
+ * value so e.g. -1750 milli-C prints as "-1.750 degC"
163
+ * (not "-1.-750 degC"). */
164
+ int whole = comp.temperature_c1000 / 1000;
165
+ int frac =
166
+ (comp.temperature_c1000 < 0 ? -comp.temperature_c1000 : comp.temperature_c1000) %
167
+ 1000;
168
+ printf(
169
+ "[i2c-master] sample %u: %d Pa, %d.%03d degC\n", i, comp.pressure_pa, whole, frac);
170
+ } else {
171
+ /* Read/compensate errors during steady-state are rare --
172
+ * usually a transient bus glitch (EMI, ground bounce).
173
+ * Log and continue rather than aborting; the next
174
+ * sample will likely succeed. */
175
+ printf("[i2c-master] sample %u: read -> %d\n", i, (int)s);
176
+ }
177
+ alp_delay_ms(SAMPLE_PERIOD_MS);
178
+ }
179
+
180
+ /* Clean shutdown -- deinit the chip driver, then close the bus
181
+ * handle (which releases the slot back to the pool). */
182
+ bmp581_deinit(&sensor);
183
+ alp_i2c_close(bus);
184
+ printf("[i2c-master] done\n");
185
+ return 0;
186
+ }
@@ -0,0 +1,52 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ sample:
4
+ name: i2c-master
5
+ description: |
6
+ Per-peripheral example for I2C master. Reads the on-board
7
+ BMP581 barometer at a known 7-bit address via
8
+ BOARD_I2C_SENSORS. Builds on both EVKs: E1M EVK uses E1M_I2C0;
9
+ E1M-X EVK uses E1M_X_I2C0. Contrasts with
10
+ examples/peripheral-io/i2c-scanner (discovery vs known-address read).
11
+
12
+ tests:
13
+ alp_sdk.example.i2c_master.e1m_x_evk:
14
+ extra_args: EXTRA_CONF_FILE=generated/alp.conf
15
+ platform_allow:
16
+ - native_sim
17
+ - native_sim/native/64
18
+ integration_platforms:
19
+ - native_sim/native/64
20
+ extra_configs:
21
+ - 'CONFIG_COMPILER_OPT="-DALP_BOARD_E1M_X_EVK"'
22
+ tags:
23
+ - alp-sdk
24
+ - example
25
+ - i2c
26
+ - sensors
27
+ - v2n
28
+ harness: console
29
+ harness_config:
30
+ type: one_line
31
+ regex:
32
+ - "\\[i2c-master\\] done"
33
+ alp_sdk.example.i2c_master.e1m_evk:
34
+ extra_args: EXTRA_CONF_FILE=generated/alp.conf
35
+ platform_allow:
36
+ - native_sim
37
+ - native_sim/native/64
38
+ integration_platforms:
39
+ - native_sim/native/64
40
+ extra_configs:
41
+ - 'CONFIG_COMPILER_OPT="-DALP_BOARD_E1M_EVK"'
42
+ tags:
43
+ - alp-sdk
44
+ - example
45
+ - i2c
46
+ - sensors
47
+ - aen
48
+ harness: console
49
+ harness_config:
50
+ type: one_line
51
+ regex:
52
+ - "\\[i2c-master\\] done"