Skip to content

Add hi3516av300 + hi3516dv300 (cv500-family) to flash agent#68

Merged
widgetii merged 1 commit intomasterfrom
agent-av300-alias
May 5, 2026
Merged

Add hi3516av300 + hi3516dv300 (cv500-family) to flash agent#68
widgetii merged 1 commit intomasterfrom
agent-av300-alias

Conversation

@widgetii
Copy link
Copy Markdown
Member

@widgetii widgetii commented May 5, 2026

Summary

Third agent platform after ev300 (V4) and cv300 (V3): the cv500-family generation (V5) — Cortex-A7 with the same memory map shared by cv500, av300, and dv300.

Most of the wiring already existed. The Cortex-A7 startup path with MMU + I/D cache from #67 covers cv500-family. PR #65 already taught `hisilicon_standard.py` the cv500-family bootrom quirks (12-byte 0xFF run zeroing, gzip SPL boundary, non-fatal SPL TAIL when prestep_data is set). Two real fixes were needed to make av300 actually run.

Fixes

1. Wrong UART base in agent/Makefile cv500 entry

The cv500 block had `UART_BASE = 0x12100000` copy-pasted from the V3/hi3518ev200 layout. qemu-hisilicon's `hi3516cv500_soc` (which models the whole cv500 family, av300 included) puts UART0 at `0x120A0000`. QEMU surfaced it instantly: agent ran silently because writes went to unmapped I/O. Fix: `0x120A0000`.

2. SPL boundary detected from the wrong buffer

`_send_spl()` in the agent-flash flow takes both `firmware` (the agent binary) and `spl_override` (OpenIPC u-boot used as the SPL stage), but `_detect_spl_size` was scanning `firmware`. The agent has no compressed payload, so the scan fell through to `profile_max = 0x6000` — overshooting the real SPL code (ends at `0x5000` on av300) by 0x1000 B. Those extra bytes include the 12-byte 0xFF padding at `0x52E4` that PR #65 identified as the cv500-family bootrom RX-hang trigger. Result: SPL DATA chunk #21 stalls with no ACK, full 32-retry exhaustion.

Fix: detect the SPL boundary from `spl_override` when present. Plus defense-in-depth: apply `_zero_long_ff_runs` to `spl_data` so any ≥12-byte 0xFF run that does slip through (e.g. a non-OpenIPC SPL build with FF padding earlier in the binary) doesn't trip the same bug.

3. Aliasing in `chip_to_agent`

Match the existing `gk7205v300 → gk7205v200` pattern: one binary, multiple chip names route to it. Add `hi3516av300 → hi3516cv500` and `hi3516dv300 → hi3516cv500` to `get_agent_binary()`. No new Makefile entry needed.

4. Cosmetic profile name fix

Both `hi3516av300.json` and `hi3516dv300.json` had `"name": "hi3516cv500"` (copy-paste artifact — the profile loader keys off filename so this is harmless, but inconsistent).

Verification

QEMU smoke test: `qemu-system-arm -M hi3516cv500` runs the agent cleanly, READY/DEFIB packet stream, no faults.

Real hi3516av300 board (`/dev/uart-hi3516av300_imx415`, MikroTik `ether8`):
```
jedec=c22019 (Macronix MX25L256, 32 MiB), ram=0x80000000, caps=0x7f, version=2
256 KiB @ 921600: 3.04 s = 84.3 KB/s
1 MiB sustained @ 921600: 11.74 s = 87.2 KB/s
flash bytes match installed u-boot byte-for-byte
```

Cross-platform throughput summary (1 MiB read, 921600 baud):

CPU Generation KB/s
ev300 Cortex-A7 V4 87.1
cv300 ARM926 V3 89.0
av300 Cortex-A7 V5 (cv500-family) 87.2

All three within ~2 KB/s — UART baud is the bottleneck.

```
make -C agent test HOST_CC=gcc: 5406/5406
pytest tests/ -x --ignore=tests/fuzz: 402 passed, 2 skipped
ruff check src/ tests/: All checks passed
mypy src/defib/ --ignore-missing-imports: no issues found in 55 source files
```

dv300 has no test board attached — it inherits the same binary as a silent alias. av300 hardware proves the same codepath cv500/dv300 will take.

Test plan

  • QEMU `-M hi3516cv500` boots agent cleanly (caught the wrong UART base)
  • Real av300 hardware: agent upload, info, flash read at 921600 baud, content verified
  • All test suites green (host C, pytest, ruff, mypy)

🤖 Generated with Claude Code

Third agent platform after ev300 (V4) and cv300 (V3): the cv500-family
generation (V5) — Cortex-A7 with the same memory map shared by cv500,
av300, and dv300.  Almost all the wiring already existed: the agent's
Cortex-A7 startup path with MMU+I/D cache (#67) covers cv500-family,
and `hisilicon_standard.py` already has every cv500-family bootrom
quirk handled (PR #65: 12-byte 0xFF run zeroing, gzip SPL boundary,
non-fatal SPL TAIL when prestep_data is set).  Two real fixes were
needed to make av300 actually run:

## Wrong UART base in cv500 Makefile entry

The cv500 SoC block had `UART_BASE = 0x12100000`, copy-pasted from the
V3/3518ev200 layout.  qemu-hisilicon's `hi3516cv500_soc` (which models
the whole cv500 family, av300 included) puts UART0 at `0x120A0000`.
QEMU smoke test surfaced it: `qemu-system-arm -M hi3516cv500` ran the
agent silently — no instruction faults but no UART output either,
because writes were going to unmapped I/O.  Fixing UART_BASE to
0x120A0000 produces the same READY/DEFIB packet stream as cv300/ev300
in QEMU.

## SPL boundary detected from the wrong buffer

`_send_spl()` in agent flash mode receives both `firmware` (the agent
binary) and `spl_override` (the OpenIPC u-boot used as the SPL stage).
It detects the SPL/u-boot boundary via gzip/LZMA signature scanning,
but was scanning `firmware` — the agent has no compressed payload, so
the scan fell through to `profile_max = 0x6000`.  That overshoots the
real SPL code (which ends at 0x5000 on av300) by 0x1000 bytes — and
those bytes include the 12-byte 0xFF padding at offset 0x52E4 that PR
#65 identified as the cv500-family bootrom RX hang trigger.  Result:
SPL DATA chunk #21 stalls forever, no ACK, full retry exhaustion.

Fix: detect the SPL boundary from `spl_override` when present.  Plus
defense-in-depth: apply `_zero_long_ff_runs` to `spl_data` so any
≥12-byte 0xFF run that does slip through (e.g. a non-OpenIPC SPL
build with FF padding earlier in the binary) doesn't trip the same
bug.

## Aliasing pattern

Following the existing `gk7205v300 → gk7205v200` shape: one agent
binary serves the whole family, multiple chip names route to it.  Add
`hi3516av300 → hi3516cv500` and `hi3516dv300 → hi3516cv500` to
`get_agent_binary()`'s chip_to_agent in `src/defib/agent/client.py`.
No new Makefile entry needed.

Also fix `"name": "hi3516cv500"` copy-paste artifact in the av300 and
dv300 profile JSONs (cosmetic — loader keys off filename — but the
inconsistency reads wrong).

## Verification

QEMU `qemu-system-arm -M hi3516cv500`: agent boots cleanly, READY/DEFIB
packet stream, no faults.

Real hi3516av300 board (`/dev/uart-hi3516av300_imx415`, MikroTik
`ether8`):
  jedec=c22019 (Macronix MX25L256, 32 MiB), ram=0x80000000, caps=0x7f
  256 KiB @ 921600: 3.04 s = 84.3 KB/s
  1 MiB sustained @ 921600: 11.74 s = 87.2 KB/s
  flash content matches installed u-boot byte-for-byte

Cross-platform throughput summary at 921600 baud (1 MiB sustained):
  ev300 (Cortex-A7, V4): 87.1 KB/s
  cv300 (ARM926, V3):    89.0 KB/s
  av300 (Cortex-A7, V5): 87.2 KB/s

All three within ~2 KB/s of each other — UART baud is the bottleneck.

make test HOST_CC=gcc: 5406/5406.  pytest: 402 passed.  ruff & mypy
clean.

dv300 has no test board attached so it inherits the same binary as a
silent alias; the test board confirms the av300 path which is the same
codepath cv500/dv300 will take.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@widgetii widgetii merged commit 310d21b into master May 5, 2026
13 checks passed
@widgetii widgetii deleted the agent-av300-alias branch May 5, 2026 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant