Skip to content

Commit 5d2ba98

Browse files
committed
test(hw): exercise real DMA capture on ADRV9009 ZC706 overlay
The previous test skipped Phase 1 when only the sdtgen `ad_ip_jesd204_tpl_adc` IIO names were present, deferring buffered RX as "merged-DTB IIO-naming work outside overlay-lifecycle scope". With the builder DMA-capture fix in place that workaround is no longer needed; this test now drives a real refill on the merged DTB and gates on noise-floor std. * Pick the RX TPL by reg address rather than by name. Our merged DTB names both the RX TPL (@44a00000) and the OBS TPL (@44a08000) `ad_ip_jesd204_tpl_adc` (sdtgen unit-name), so a plain `find_device` returns whichever probed first — typically OBS via `ad_adc.c`. Talise's `radio_on` only streams framer-A, so a refill on OBS returns all zeros even though the OBS DMA fires its IRQ. Match `of_node` containing `44a00000` first; fall back to the higher-numbered duplicate (cf_axi_adc binds RX after `ad_adc` binds OBS) when libiio doesn't expose `of_node`. * Guard the opportunistic Phase 2 (pyadi-iio FFT) against the partial-init state. pyadi-iio looks up the buffered ADC by the production name `axi-adrv9009-rx-hpc`; on the merged DTB that name is missing, so `adi.adrv9009(uri=...)` returns successfully but with `_rxadc = None`, and the next `dev.rx_*` access crashes with `AttributeError`. Detect the None _rxadc and skip cleanly; Phase 1 already validated the data path. * On Phase 1 failure, dump full `/proc/interrupts` and recent `dmesg` so the next investigation can disambiguate DMA-not-firing from JESD-not-streaming without a re-run.
1 parent 2009b0b commit 5d2ba98

1 file changed

Lines changed: 82 additions & 45 deletions

File tree

test/hw/xsa/test_adrv9009_zc706_overlay.py

Lines changed: 82 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,17 @@
1212
so U-Boot's ``tftp devicetree.dtb`` finds it; the kernel is
1313
``uImage`` (legacy U-Boot image, wrapped from the built ``zImage``
1414
by :func:`~test.hw.hw_helpers._wrap_zimage_as_uimage`).
15-
2. **DMA path** — two adaptations vs the AD9081 variant:
16-
17-
* The default post-boot Talise state on ZC706 + ADRV9009 leaves
18-
buffered RX inert. The DMA test pushes a canonical
19-
iio-oscilloscope ``DC245p76`` Talise profile via
20-
``adrv9009-phy.profile_config`` first; that re-inits the radio
21-
to ``radio_on`` without changing the JESD lane rate.
22-
* The ADRV9009 ZC706 reference HDL has no internal DAC→ADC
23-
loopback (unlike AD9081's ``ad_ip_jesd204_tpl_*`` cores), so a
24-
TX DDS tone may not appear in the RX capture without an
25-
external SMA-to-SMA cable on the daughter card. The FFT stage
26-
asserts SNR > 10 dB on a non-DC peak only when one is clearly
27-
present and otherwise logs the noise-only result and passes.
15+
2. **DMA path** — the default post-boot Talise state on ZC706 +
16+
ADRV9009 leaves buffered RX inert. The DMA test pushes a
17+
canonical iio-oscilloscope ``DC245p76`` Talise profile via
18+
``adrv9009-phy.profile_config`` first; that re-inits the radio
19+
to ``radio_on`` without changing the JESD lane rate. The
20+
ADRV9009 ZC706 reference HDL has no internal DAC→ADC loopback
21+
(unlike AD9081's ``ad_ip_jesd204_tpl_*`` cores), so a TX DDS tone
22+
may not appear in the RX capture without an external SMA-to-SMA
23+
cable on the daughter card. The FFT stage asserts SNR > 10 dB
24+
on a non-DC peak only when one is clearly present and otherwise
25+
logs the noise-only result and passes.
2826
2927
LG_ENV: ``test/hw/env/nemo.yaml``.
3028
"""
@@ -442,49 +440,88 @@ def test_dma_loopback(booted_board, tmp_path):
442440

443441
ctx, ip = open_iio_context(shell)
444442

445-
# Pre-check before touching any DMA buffer: only the production
446-
# Kuiper DTB names (``axi-adrv9009-rx-hpc`` / ``-obs-hpc``) back
447-
# a refillable AXI-DMA buffer. Our merged sdtgen DTB labels the
448-
# JESD framing core ``ad_ip_jesd204_tpl_adc`` instead, which is
449-
# the JESD framing test endpoint, not the buffered ADC frontend
450-
# — refilling its buffer hangs even after Talise re-init +
451-
# ``ensm_mode=radio_on``. Aligning the merged-DTB IIO names
452-
# with Kuiper is a separate merged-DTB IIO-naming change,
453-
# outside overlay-lifecycle scope. Skip the buffered-RX phase
454-
# cleanly when the right names are absent so we don't leave a
455-
# stalled libiio buffer that segfaults the rest of the suite.
456-
rx_dev_names = {d.name for d in ctx.devices if d.name}
457-
has_buffered_rx = bool(
458-
rx_dev_names & {"axi-adrv9009-rx-hpc", "axi-adrv9009-rx-obs-hpc"}
459-
)
460-
if not has_buffered_rx:
461-
del ctx
462-
pytest.skip(
463-
"merged-DTB exposes only ad_ip_jesd204_tpl_adc, not the"
464-
" axi-adrv9009-rx-hpc Kuiper name backed by AXI-DMA;"
465-
" buffered RX requires merged-DTB IIO-naming work"
466-
" outside overlay-lifecycle scope"
467-
)
468-
469443
# Phase 1: bare data-path smoke check.
470-
assert_rx_capture_valid(
471-
ctx,
472-
(
473-
"axi-adrv9009-rx-hpc",
474-
"axi-adrv9009-rx-obs-hpc",
475-
),
476-
n_samples=2**12,
477-
context="adrv9009 zc706 overlay",
444+
#
445+
# Both the RX TPL (``...@44a00000``) and the OBS TPL
446+
# (``...@44a08000``) probe to libiio with the same of_node
447+
# name ``ad_ip_jesd204_tpl_adc`` — their unit-names are
448+
# identical in the sdtgen-built DTB. ``find_device`` returns
449+
# whichever probed first (typically OBS via ``ad_adc.c``,
450+
# before cf_axi_adc binds the RX TPL). Talise's ``radio_on``
451+
# streams framer-A (RX); framer-B (OBS) stays gated, so a
452+
# refill on the OBS device returns all zeros even though the
453+
# OBS DMA fires its done IRQ. Prefer the RX TPL by reg
454+
# address so we exercise the path ``radio_on`` actually
455+
# enables.
456+
rx_tpl_dev = None
457+
for d in ctx.devices:
458+
if d.name != "ad_ip_jesd204_tpl_adc":
459+
continue
460+
try:
461+
of_node = d.attrs["of_node"].value if "of_node" in d.attrs else ""
462+
except Exception: # noqa: BLE001 — attr read may raise on some builds
463+
of_node = ""
464+
if "44a00000" in of_node:
465+
rx_tpl_dev = d
466+
break
467+
if rx_tpl_dev is None:
468+
# ``of_node`` isn't always exposed as an IIO attr; fall back
469+
# to the higher-numbered duplicate. cf_axi_adc binds the RX
470+
# TPL after ``ad_adc`` binds OBS, so the RX iio:device has
471+
# the larger numeric id.
472+
candidates = [d for d in ctx.devices if d.name == "ad_ip_jesd204_tpl_adc"]
473+
if candidates:
474+
rx_tpl_dev = max(candidates, key=lambda d: int(d.id.rsplit(":device", 1)[1]))
475+
476+
target_names: tuple[str, ...] = (
477+
"axi-adrv9009-rx-hpc",
478+
"axi-adrv9009-rx-obs-hpc",
479+
"ad_ip_jesd204_tpl_adc",
478480
)
481+
if rx_tpl_dev is not None:
482+
target_names = (rx_tpl_dev.id,)
483+
484+
try:
485+
assert_rx_capture_valid(
486+
ctx,
487+
target_names,
488+
n_samples=2**12,
489+
context="adrv9009 zc706 overlay",
490+
)
491+
except AssertionError:
492+
# On-target diagnostics: IRQ counts disambiguate
493+
# DMA-not-firing from JESD-not-streaming for the next
494+
# round of debugging.
495+
print("=== /proc/interrupts ===")
496+
print(shell_out(shell, "cat /proc/interrupts"))
497+
print("=== dmesg tail ===")
498+
print(shell_out(shell, "dmesg | tail -n 60"))
499+
raise
479500

480501
# Phase 2: opportunistic spectrum check via pyadi-iio.
502+
#
503+
# ``pyadi-iio`` looks up the buffered ADC by the production
504+
# name ``axi-adrv9009-rx-hpc``. Our merged DTB names the same
505+
# node ``ad_ip_jesd204_tpl_adc`` (sdtgen unit-name), so the
506+
# ``adi.adrv9009`` constructor returns an object with
507+
# ``_rxadc = None`` instead of raising — every subsequent
508+
# ``dev.rx_*`` access then crashes with ``AttributeError``.
509+
# Detect that state up front and skip; Phase 1 already
510+
# validated the data path.
481511
import adi
482512

483513
try:
484514
dev = adi.adrv9009(uri=f"ip:{ip}")
485515
except Exception as exc: # noqa: BLE001 — connect failure → skip phase 2
486516
print(f"adi.adrv9009 unavailable; skipping FFT phase: {exc}")
487517
return
518+
if getattr(dev, "_rxadc", None) is None:
519+
print(
520+
"adi.adrv9009 missing 'axi-adrv9009-rx-hpc' IIO name "
521+
"(merged DTB exposes 'ad_ip_jesd204_tpl_adc' instead) — "
522+
"skipping FFT phase; Phase 1 already validated the data path."
523+
)
524+
return
488525

489526
dev.rx_enabled_channels = [0]
490527
dev.rx_buffer_size = RX_BUFFER_SIZE

0 commit comments

Comments
 (0)