Skip to main content

aen-*-regcheck — on-silicon driver smoke tests

A suite of minimal register-level bench examples that each bind one E8 block, exercise it through the portable Zephyr class API where one exists, and confirm the expected behaviour on real silicon — cross-checked with a J-Link mem32 read. They prove the driver binds and programs registers: the foundation the higher-level examples build on.

Source: examples/aen/.

:::info These are bench tools, not teaching examples Every regcheck says it plainly in its own source: "BENCH-VALIDATION app — not a customer teaching example." None of them carries a board.yaml, so none is part of the 95-example catalog or the portable-example contract. They are standalone Zephyr apps built directly against a board target — see Build below.

For app-building, start from the portable examples instead: hello-world, i2c-master, spi-master. :::

The two-witness method

Every regcheck is designed for a scopeless bench — no oscilloscope, and the app UART is not routed to USB. So each one confirms its result two independent ways:

  1. In firmware — drive the API, print the values plus the registers read back, and emit exactly one RESULT PASS: / RESULT FAIL: line. Several also latch raw register words into file-scope globals, so the evidence survives over SWD even if a later step faults.
  2. By hand — the operator re-reads the same absolute addresses over J-Link mem32.

That second witness is the point: a driver that only prints the right thing gets caught.

Where the console is the RAM buffer rather than a UART, the operator reads the ram_console_buf symbol over J-Link mem8 and ASCII-decodes it.

Functional checks

These drive a real transaction and assert what came back.

ExampleBlockCheck
aen-crc-regcheckhardware CRC (alif,crc)CRC32/IEEE over a fixed 16-byte buffer vs a host-precomputed 0x684FC31C; CRC_OUT re-read over J-Link
aen-dma-regcheckARM PL330 DMA1000-byte M2M memcpy verified byte-for-byte (RESULT PASS)
aen-hwsem-regcheckHWSEM (alif,hwsem)take → count nonzero → give → count 0 (AMP mutual-exclusion latch)
aen-cmp-regcheckHSCMP (alif,cmp)high-speed comparator + internal DAC6 reference path alive
aen-lptimer-regcheckLPTIMER (alif,lptimer)always-on DOWN-counter decreases between two reads
aen-rtc-regcheckLPRTC (snps,dw-apb-rtc)always-on UP-counter advances (counter-only — not a calendar RTC)
aen-counter-utimer-regcheckUTIMER counter (alif,utimer-counter)free-running 32-bit counter advances across two counter_get_value() reads; the operator re-reads the UTIMER CNTR register over mem32
aen-counter-alarm-regcheckUTIMER COMPARE-A alarma relative alarm armed via the portable counter_set_channel_alarm() actually fires, the one-shot clears, and a re-arm fires again
aen-adc-regcheckADC (alif,adc)adc_channel_setup + adc_read single-shot; the START/SINGLE_SHOT bits reading back idle afterwards is the register evidence the conversion ran
aen-dac-regcheckDAC (alif,dac)dac_channel_setup + dac_write_value mid-scale; DAC_IN holds the code and the EN bit stays set (the DAC has no completion teardown and no IRQ)
aen-spi-regcheckSPI (alif,dwc-ssi-spi)spi_transceive() in internal loopback (the DWC_ssi SRL bit ties TX shift-register to RX — a real data check with no external wire), plus a CTRLR0/SSIENR/BAUDR/SR readback
aen-i2c2-eeprom-regcheckSoC I²C2 (snps,designware-i2c)scan 0x08..0x77, confirm the 24C128 answers at 0x50, then a combined write-then-read (repeated-START) of 16 bytes. Content is not checked — a blank EEPROM reads all-0xff and still PASSes; this proves the bus + addressing + read path

:::note What aen-crc-regcheck is really settling The canonical CRC-32 reflects input and output and one's-complements the result. The Alif engine drives reflection and inversion from separate CRC_CONTROL bits, and the order the silicon applies them is the one open question this regcheck exists to answer on the bench. A mismatch is a documented bench-confirm item, not a code defect — the source's RESULT FAIL branch says so and tells the operator not to guess the order without the silicon answer. :::

Binding / staging checks

These are BIND checks, not behaviour checks. They prove the devicetree node exists, binds to the expected compatible at the expected register base, and that phandle chains resolve — pure DT predicates, independent of device_is_ready. They deliberately do not move data.

ExampleBlockCheck
aen-camera-regcheckcamera capture stackalif,cam (CPI) / snps,designware-csi / snps,designware-dphy / onnn,arx3a0 all bind at their expected reg bases; instantiated video devices are exercised through the portable Zephyr v4.4 video API
aen-dsi-regcheckC2-MIPI-DSI display chaintes,cdc-2.1 (CDC200 pixel pump) → snps,designware-dsi (DSI host) → snps,designware-dphy bind; the DSI host's cdc-if and phy-if phandles resolve, so the chain is wired. Not a pixels-on-glass check — for live output use aen-dsi-display
aen-can-regcheckCAN-FD (cast,can)can0 binds to cast,can, the alp_can0 alias resolves to that same node (the portable backend's contract), and the CAN-FD enable plumbing is wired
aen-isp-regcheckISP-Pico (vsi,isp-pico)the isp node binds at its expected reg base with its two IRQs. Bind-only by necessity — see below

:::warning aen-isp-regcheck does not enable the ISP driver The check deliberately leaves CONFIG_VIDEO_ISP_VSI off. The ISP driver links the Alif libisp wrapper (a Vivante BLOB), and the vendored 2025 wrapper is older than the 2026 driver and API-incompatible — the translation unit does not even compile against it, let alone link. So the regcheck validates the DT staging that is deliverable build-green, and nothing more. :::

The D-PHY is worth noting: it is the same block in both the camera and display chains — CSI-2 RX for one, TX for the other.

NPU presence probes

ExampleBlockCheck
aen-npu-ethosu-regcheckArm Ethos-U85 (arm,ethos-u, global)The ID/CONFIG/STATUS block is present, powered, and clocked; the variant is identified from two independent ID fields
aen-npu-ethosu55-regcheckArm Ethos-U55 (128-MAC, HE-core-local)Same probe on the core-private U55. Its source records the silicon reading: ID 0x10104201 (arch 1.1.0) with CONFIG.product == 0 — validated from the HE core

Neither runs an inference. That needs the Ethos-U core driver library plus a Vela-compiled model and command stream — the documented follow-up, delivered by aen-npu-inference.

The U85 probe reads the ID register directly off the DT reg base rather than through ethosu_get_hw_info(), and that's deliberate: the arm,ethos-u node is status = "okay", so Zephyr's Ethos-U driver auto-instantiates at POST_KERNEL and calls ethosu_init(), which soft-resets the NPU and spins waiting for it to come ready. If the NPU clock or power is not up, that init can hang before main() ever runs. Reading the raw base keeps the probe robust — and if init does hang, a J-Link mem32 read of the same ID address still tells the operator whether the block is clocked. That dual path is the whole design.

The calendar RTC

aen-rtc-regcheck covers the LPRTC as a bare counter. The portable calendar surface on top of it — alp_rtc_set_time() / alp_rtc_get_time() — is the separate aen-rtc-calendar shim, documented with the other bench tools on the AEN bench + bring-up tools page.

Build

Regchecks are standalone Zephyr apps — there is no board.yaml and no alp_project.py flow. Build them straight against the board target:

export ZEPHYR_BASE=<zephyr-base>
west build -p always -b alp_e1m_aen801_m55_he/ae822fa0e5597ls0/rtss_he \
examples/aen/aen-crc-regcheck -d build/aen-crc-regcheck -- \
"-DEXTRA_ZEPHYR_MODULES=<alp-sdk>;<hal_alif>"

Each app's boards/ overlay auto-applies for the matching board target (Zephyr's per-board overlay convention). Typically it okays the block under test and retargets zephyr,flash to ITCM for the RAM-run.

Bench run

Human-operated; the SDK does not do this in CI.

  1. Build → build/<app>/zephyr/zephyr.bin.
  2. J-Link (generic Cortex-M55): loadbin the image to ITCM, set PC, run.
  3. Read the RESULT line — from the UART console, or from the ram_console_buf symbol over SWD (mem8, ASCII-decode) on a serial-less bench.
  4. Confirm against ground truth: mem32 the block's key register per the app's readback plan.

Expected output

[aen-dma-regcheck] PL330 M2M copy 1000 bytes
[aen-dma-regcheck] memcmp OK
[aen-dma-regcheck] RESULT PASS

See also

Questions about this page? Discuss in Community Forum