Skip to content

ci: publish a DDR3 u-boot for hi3518ev200 boards that have DDR3 - #9

Merged
openipc-ai merged 2 commits into
masterfrom
ddr3-variant
Aug 27, 2026
Merged

ci: publish a DDR3 u-boot for hi3518ev200 boards that have DDR3#9
openipc-ai merged 2 commits into
masterfrom
ddr3-variant

Conversation

@openipc-ai

@openipc-ai openipc-ai commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Closes #8. Field case: OpenIPC/firmware#2299.

Symptom

A hi3518ev200 camera that flashes cleanly and then boots nothing. The
bootloader partition verifies byte-for-byte after writing, the vendor
bootloader written back the same way boots fine, and a UART recovery
upload ACKs every chunk and then produces only 0x20 bootmode markers
where the jump should be. It reads as a bad flash or a bad upload. It is
neither.

Cause

reg_info_hi3518ev200.bin sets DMC_CFG_DDRMODE (0x20111050) to
0x15. From drivers/ddr/ddr_ddrc_v500.h:

#define DDR_DMC_CFG_DDRMODE     0x50
#define DMC_CFG_DRAM_TYPE_MASK  0x7 /* [2:0]101:DDR2, 110:DDR3, 111:DDR4 */

0x15 is DDR2. On a board populated with DDR3 there is no working
memory at all, so the SPL runs out of SRAM, misprograms the controller
and faults on the first DRAM access — before anything can print.

table 0x20111050 type
reg_info_hi3518ev200.bin 0x00000015 DDR2
reg_info_hi3518ev201.bin 0x00000015 DDR2
reg_info_hi3516cv200.bin 0x00000016 DDR3

hi3516cv200 is the same DDRC v500 and the same PHY S40, and it already
ships a validated DDR3 table. hi3518ev200 just has no build that uses
one.

Evidence from the affected board

  • Nanya NT5CC128M16IP-DI, a 2 Gbit DDR3L part, read off the package.

  • Its running vendor bootloader: md.l 0x20111050 100000016.

  • The 4 KB register block extracted from that vendor bootloader is
    byte-for-byte identical to reg_info_hi3516cv200.bin (3584 bytes
    of table, remainder zero padding). The table this PR selects is
    literally the one the board's own vendor firmware uses.

  • Splicing it into the published u-boot-hi3518ev200-recovery.bin at
    offset 64 and uploading over UART boots to a prompt:

    USB:   scanning bus for devices... 1 USB Device(s) found
    Hit any key to stop autoboot:  1 ... 0
    OpenIPC # 
    

Change

mini-boot.bin is assembled as 64 B vectors + a 4096 B register table +
code + LZMA payload, with no checksum over the table region. The table is
dd'd in with bs=4096 conv=sync, so swapping it is size-neutral
regardless of which table file is used — a DDR3 variant needs no code
change and no config change.

The build matrix splits its one field into three: name (published
artifact), config (u-boot board config), reg (register table).
reg_info_hi3516cv200.bin is referenced rather than copied to a second
filename so the two builds cannot drift apart silently.

New artifacts: u-boot-hi3518ev200-ddr3-universal.bin and
u-boot-hi3518ev200-ddr3-recovery.bin. The hi3518ev200 and
hi3516cv200 jobs build from exactly the config and table they built
from before, so no DDR2 board changes behaviour.

Verification of the CI artifacts

Every artifact from this run, checked against the table it should carry
and the DRAM type that table encodes:

artifact                                  size  table@64 matches       DDRMODE   type
u-boot-hi3518ev200-universal            133443  True  reg_info_hi3518ev200.bin 0x00000015 DDR2
u-boot-hi3518ev200-recovery             127299  True  reg_info_hi3518ev200.bin 0x00000015 DDR2
u-boot-hi3518ev200-ddr3-universal       133435  True  reg_info_hi3516cv200.bin 0x00000016 DDR3
u-boot-hi3518ev200-ddr3-recovery        127291  True  reg_info_hi3516cv200.bin 0x00000016 DDR3
u-boot-hi3516cv200-universal            133407  True  reg_info_hi3516cv200.bin 0x00000016 DDR3
u-boot-hi3516cv200-recovery             127263  True  reg_info_hi3516cv200.bin 0x00000016 DDR3

vendor block == cv200 table region shipped in the ddr3 build: True

On the sizes not matching: they differ by 8 bytes between the
hi3518ev200 and hi3518ev200-ddr3 jobs, and this is not the table. The
build is not reproducible — Makefile:488 generates
U_BOOT_DATE/U_BOOT_TIME from date on every build, so the LZMA
payload changes length slightly run to run and the linked addresses ahead
of it shift with it. The same effect shows up between this run's
u-boot-hi3518ev200-universal.bin and the currently published one: same
133443 bytes, 18164 differing bytes inside the payload, identical source.
Worth fixing on its own, but it is pre-existing and orthogonal to this
change.

Test plan

  • actionlint clean (two SC2046 warnings, both pre-existing on master).
  • Build matrix names, QEMU smoke matrix and the publish loop cross-checked as in sync.
  • Every CI artifact verified to carry the intended table (table above).
  • The spliced binary boots on the affected hardware (log above).
  • CI: three build jobs and three QEMU smoke jobs green.

Known limitation, not addressed here

hi3518ev200.h sets CFG_DDR_SIZE to 64 MB, and detect_memory()
probes with get_ram_size(base, CFG_DDR_SIZE) — so it cannot report
more than 64 MB, and totalmem is what load_hisilicon uses to size
MMZ. The board in #2299 has 128 MB (its vendor kernel maps to
0x88000000), so it will boot correctly but see half its RAM. That is a
separate change with its own blast radius on existing DDR2 boards, and I
would rather land the fix that turns a brick into a booting camera
first.

hi3518ev200's register table programs the memory controller for DDR2:
DMC_CFG_DDRMODE (0x20111050) is 0x15, and DMC_CFG_DRAM_TYPE_MASK in
drivers/ddr/ddr_ddrc_v500.h reads [2:0] as 101=DDR2, 110=DDR3, 111=DDR4.
Boards of this SoC built with DDR3 therefore have no working memory: the
SPL runs from SRAM, programs the controller for the wrong device, and
dies the moment it touches DRAM. From the outside the camera looks
bricked -- flashing succeeds, nothing boots, and a UART recovery upload
ACKs every chunk and then goes silent on the jump.

OpenIPC/firmware#2299 is one such board. Its Nanya NT5CC128M16IP-DI is a
2 Gbit DDR3L part, its running vendor bootloader reports
"md.l 0x20111050 1 -> 00000016", and the 4 KB register block lifted out
of that bootloader is byte-for-byte reg_info_hi3516cv200.bin. Splicing
that table into u-boot-hi3518ev200-recovery.bin at offset 64 and
uploading it over UART boots to a U-Boot prompt on the reporter's
hardware.

So the DDR3 table for this silicon already exists in the tree and is
already validated -- hi3518ev200 simply has no build that uses it. The
mini-boot link step dd's the table in at a fixed offset with no checksum
over it, so the variant is a table swap and nothing else: same config,
same sources, same image size.

The matrix therefore separates what was one field into three: `name` is
the published artifact, `config` the u-boot board config, and `reg` the
table. reg_info_hi3516cv200.bin is referenced rather than copied to a
second filename, so the two builds cannot drift apart silently.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Publish DDR3 U-Boot images for hi3518ev200 boards

🐞 Bug fix ✨ Enhancement ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Publishes DDR3 universal and recovery images for affected hi3518ev200 boards.
• Reuses the validated hi3516cv200 DDR3 table without changing existing DDR2 artifacts.
• Extends QEMU smoke tests and release publishing to cover the new variant.
Diagram

graph TD
  M["Build Matrix"] --> C["Board Config"] --> B["Image Build"] --> A["Named Artifacts"] --> Q{"QEMU Pass"} --> P["Firmware Release"]
  M --> R["DDR Table"] --> B
Loading
High-Level Assessment

The matrix-based table selection is the best approach: it preserves the existing hi3518ev200 configuration and DDR2 outputs while reusing the vendor-validated DDR3 table. Copying the register table or creating a duplicate board configuration would add drift risk without changing the resulting image behavior.

Files changed (1) +31 / -16

Other (1) +31 / -16
build.ymlAdd a tested and published hi3518ev200 DDR3 build variant +31/-16

Add a tested and published hi3518ev200 DDR3 build variant

• Splits matrix entries into artifact name, board configuration, and DDR register table so hi3518ev200 can be built with the validated hi3516cv200 DDR3 table. Propagates the new artifact name through size checks, SRAM validation, uploads, QEMU smoke tests, and release publishing while preserving existing DDR2 artifact names.

.github/workflows/build.yml

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (1) 📜 Skill insights (0)

Grey Divider


Action required

1. DDR3 selection remains undocumented 📎 Requirement gap ⚙ Maintainability
Description
The PR publishes a new hi3518ev200-ddr3 artifact but adds no installation guidance for checking
0x20111050 or choosing DDR2 versus DDR3 images. Users can therefore flash the wrong DRAM variant
and leave the device unable to boot.
Code

.github/workflows/build.yml[27]

+          - { name: hi3518ev200-ddr3, config: hi3518ev200, reg: reg_info_hi3516cv200.bin }
Evidence
PR Compliance ID 4 requires installation documentation with the pre-flight command, value
interpretation, and variant mapping. The changed workflow introduces the hi3518ev200-ddr3 artifact
and contains only CI-oriented comments; repository searches found no user documentation containing
md.l 0x20111050 1 or any hi3518ev200-ddr3 reference outside this workflow.

Document the DRAM-type pre-flight check and variant selection
.github/workflows/build.yml[15-27]
README[24-31]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The newly published `hi3518ev200-ddr3` variant lacks user-facing installation guidance for determining the board's DRAM type and selecting the matching image.

## Issue Context
Document running `md.l 0x20111050 1` from a working HiSilicon U-Boot, explain that a final hexadecimal digit of `5` means DDR2 and `6` means DDR3, and map those results to the standard and `-ddr3` artifacts respectively.

## Fix Focus Areas
- README[24-31]
- .github/workflows/build.yml[15-27]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources

Grey Divider

Tip of the day
💡 Did you know, you can ask Qodo to dismiss a finding you disagree with, with your reason on record

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

# is shared rather than copied.
include:
- { name: hi3518ev200, config: hi3518ev200, reg: reg_info_hi3518ev200.bin }
- { name: hi3518ev200-ddr3, config: hi3518ev200, reg: reg_info_hi3516cv200.bin }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Ddr3 selection remains undocumented 📎 Requirement gap ⚙ Maintainability

The PR publishes a new hi3518ev200-ddr3 artifact but adds no installation guidance for checking
0x20111050 or choosing DDR2 versus DDR3 images. Users can therefore flash the wrong DRAM variant
and leave the device unable to boot.
Agent Prompt
## Issue description
The newly published `hi3518ev200-ddr3` variant lacks user-facing installation guidance for determining the board's DRAM type and selecting the matching image.

## Issue Context
Document running `md.l 0x20111050 1` from a working HiSilicon U-Boot, explain that a final hexadecimal digit of `5` means DDR2 and `6` means DDR3, and map those results to the standard and `-ddr3` artifacts respectively.

## Fix Focus Areas
- README[24-31]
- .github/workflows/build.yml[15-27]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Publishing a -ddr3 variant creates a hazard that did not exist while
there was only one image: a DDR2 board flashed with the DDR3 image fails
in exactly the same way the DDR3 boards have been failing, and the
failure looks like a bad flash rather than a wrong choice.

So document the pre-flight check next to the download table. `md.l
0x20111050 1` from any working HiSilicon U-Boot -- the vendor's own
bootloader will do -- reads DMC_CFG_DDRMODE, whose last hex digit is the
DRAM type per DMC_CFG_DRAM_TYPE_MASK in drivers/ddr/ddr_ddrc_v500.h: 5
is DDR2, 6 is DDR3.

The repository's front page was upstream U-Boot's stock README, which
says nothing about which of these artifacts to use or what the -recovery
images are for.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@openipc-ai

Copy link
Copy Markdown
Contributor Author

Addressing the Qodo review.

Requirement gap — "DDR3 selection remains undocumented": valid, fixed in 42a5e77.

The concern is right and it is the one real hazard this PR introduces:
before it there was a single hi3518ev200 image and nothing to choose
wrongly, and after it a DDR2 board flashed with the DDR3 image fails in
exactly the way the DDR3 boards have been failing — silently, looking
like a bad flash.

The suggested location was not right, though: README in this repo is
upstream U-Boot's stock 145 KB file, and the cited lines 24-31 are the
GPL header. Added README.md instead, which also gives the repository a
front page that says what these artifacts are — it previously showed the
stock U-Boot README, which does not mention them at all. It carries the
download table, the md.l 0x20111050 1 pre-flight check with the
5=DDR2 / 6=DDR3 mapping traced to DMC_CFG_DRAM_TYPE_MASK, and a note
that -recovery images are for UART upload and must not be flashed.

Two things I did not take from the suggestion, both because I could not
stand behind them:

  • I drafted a "read the DRAM package marking" fallback with vendor
    prefix patterns and cut it back to the one part actually confirmed on
    hardware (NT5CC128M16IP-DI) plus "look up the datasheet". Getting a
    prefix wrong in flashing instructions bricks someone's camera, and I
    had not verified those prefixes.
  • The README describes this repo as covering Hi3516CV200 and Hi3518EV200
    only. Hi3518EV201 has a config and a register table in tree but no
    entry in the build matrix and no published u-boot artifact, so listing
    it would have been wrong.

The wiki's en/install-hisi.md is where users actually go to flash, so
the same check belongs there too. Tracking in #8 rather than here.

@openipc-ai
openipc-ai merged commit 0548e22 into master Aug 27, 2026
7 checks passed
@openipc-ai
openipc-ai deleted the ddr3-variant branch August 27, 2026 10:43
@openipc-ai

Copy link
Copy Markdown
Contributor Author

Correction to my note above: I said the wiki side was tracked in #8, but Closes #8 in the PR body auto-closed that issue on merge, so that pointer went stale the moment this landed. The wiki change is OpenIPC/wiki#493.

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.

hi3518ev200 U-Boot is DDR2-only: cameras with DDR3 memory never boot and look bricked

1 participant