X96Q LPDDR3 v1.3 — кастомный U-Boot

Кастомная сборка U-Boot для X96Q TV Box LPDDR3 v1.3 (Allwinner H616/H313, 1 GiB LPDDR3, AXP313A, eMMC boot).

Проверено: UART 115200, загрузка Armbian с eMMC, DRAM: 1 GiB.

Структура репозитория

x96q-uboot/
├── README.md
├── build.sh                    # сборка (macOS + Homebrew)
├── patches/
│   ├── jernejsk-emmc.patch     # фикс eMMC на H616
│   ├── easter-egg.patch        # баннер в SPL + Kconfig
│   └── fdtfile-armbian.patch   # совместимость DTB с Armbian
├── overlays/
│   ├── configs/x96_q_lpddr3_v1.3_defconfig
│   └── dts/sun50i-h313-x96q-lpddr3-v1.3.dts
├── output/
│   └── u-boot-custom.bin       # артефакт сборки (gitignore)
└── scripts/
    ├── flash-emmc.sh           # образ + U-Boot на eMMC
    └── flash-uboot-only.sh     # только U-Boot поверх существующего образа

Что было сломано и как чинили

1. Неправильный defconfig (DDR3 вместо LPDDR3)

Симптом: DRAM: not supported в UART.

Причина: generic x96q_defconfig настроен на DDR3, а плата — LPDDR3 v1.3 с другими таймингами и AXP313.

Фикс: defconfig x96_q_lpddr3_v1.3_defconfig из Armbian/NickAlilovic + DTS sun50i-h313-x96q-lpddr3-v1.3.dts.

2. eMMC read error в SPL

Симптом: SPL не читает eMMC, BootROM зацикливается или грузит битый bootloader.

Причина: на H616 контроллеру MMC нужен hardware reset карты и FIFO threshold (патч Jernej Skrabec, upstream U-Boot).

Фикс: patches/jernejsk-emmc.patch — backport на v2025.01.

3. Несовпадение имени DTB (главный баг загрузки)

Симптом:

The file allwinner/sun50i-h313-x96q-lpddr3-v1.3.dtb was not found
ERROR: Did not find a cmdline Flattened Device Tree

Причина: U-Boot из SPL выставляет fdtfile по имени своего device tree (…-lpddr3-v1.3.dtb). Armbian в /boot/dtb/allwinner/ кладёт только sun50i-h313-x96q-lpddr3.dtb (без суффикса v1.3). Ядро и initrd грузятся, DTB — нет.

Фикс (три уровня):

  1. Патч U-Boot fdtfile-armbian.patch — в misc_init_r() подменяет fdtfile на Armbian-имя.
  2. flash-emmc.sh — после прошивки пишет fdtfile=sun50i-h313-x96q-lpddr3.dtb в armbianEnv.txt и создаёт symlink …-v1.3.dtb.
  3. Вручную на работающей системе — то же в /boot/armbianEnv.txt.

U-Boot DT (v1.3) и kernel DT (lpddr3) — разные файлы с разным назначением. SPL использует свой DTS для DRAM/PMIC; ядро — DTB из образа Armbian.

4. dd: Operation not permitted на boot0/boot1

Симптом: запись в user area проходит, в mmcblk2boot0 — отказ.

Причина: boot-разделы eMMC по умолчанию read-only (force_ro=1).

Фикс: перед dd:

echo 0 > /sys/block/mmcblk2boot0/force_ro
echo 0 > /sys/block/mmcblk2boot1/force_ro

Скрипт flash-emmc.sh делает это автоматически.

5. Card did not respond to voltage select! : -110 на mmc0

Симптом: при фолбэке boot.scr пытается mmc0 и падает.

Причина: в U-Boot mmc0 — SD-слот, при определённых условиях voltage select не проходит; это не блокер, если DTB найден на правильном mmc (SD = mmc1 в нашем случае).

Карта MMC

Где Устройство Назначение
Linux mmcblk0 SD-карта
Linux mmcblk2 eMMC (user area)
Linux mmcblk2boot0/1 eMMC boot partitions (по 2 MiB)
U-Boot shell mmc dev 1 eMMC
U-Boot shell mmc dev 2 то же eMMC (другой индекс)
U-Boot autoboot mmc1 откуда грузится boot.scr (SD при вставленной карте)

SPL/U-Boot пишется в три места:

  • user area @ 8 KiB (dd seek=8) — legacy sunxi offset
  • boot0 — основная boot-область eMMC
  • boot1 — зеркало (резерв)

Сборка

Требования (macOS)

brew install aarch64-elf-gcc gnu-sed openssl@3 swig python3

Команда

./build.sh

Скрипт:

  1. Клонирует U-Boot v2025.01 и ARM TF-A в .build/
  2. Накатывает патчи из patches/
  3. Копирует defconfig и DTS из overlays/
  4. Собирает BL31 + U-Boot
  5. Кладёт бинарник в output/u-boot-custom.bin (~822 KiB)

Проверка артефакта

strings output/u-boot-custom.bin | grep -E 'binary build|2025.01|lpddr3'

Ожидаемо:

  • *** binary build ***
  • U-Boot SPL 2025.01-dirty
  • sun50i-h313-x96q-lpddr3.dtb (fdtfile для Armbian)

Прошивка eMMC

Полная (образ Armbian + U-Boot)

На приставке (под root, лучше загрузившись с SD):

# скопировать на приставку:
#   output/u-boot-custom.bin
#   scripts/flash-emmc.sh
#   Armbian_*.img.xz

cd /home/binary   # или куда положили файлы
sudo ./flash-emmc.sh
# или явно:
sudo ./flash-emmc.sh Armbian_community_26.2.0-trunk.904_X96q_trixie_current_6.18.29_minimal.img.xz

Скрипт:

  1. xz -dc образ | dd of=/dev/mmcblk2 — запись образа локально (не через SSH pipe)
  2. U-Boot → user @ 8 KiB
  3. Разблокировка boot0/boot1
  4. U-Boot → boot0 + boot1
  5. Правка armbianEnv.txt + symlink DTB

После прошивки: вынуть SD, перезагрузка.

Только U-Boot (образ уже на eMMC)

sudo ./flash-uboot-only.sh /path/to/u-boot-custom.bin

Ожидаемый UART при успешной загрузке

*** binary build ***
U-Boot 2025.01-dirty (...) binary build
CPU:   Allwinner H616 (SUN50I)
Model: hechuang,x96-q LPDDR3 v1.3
DRAM:  1 GiB
...
U-boot loaded from eMMC
Load fdt: /boot/dtb/allwinner/sun50i-h313-x96q-lpddr3.dtb

Патчи

Патч Зачем
jernejsk-emmc.patch reset eMMC + FIFO threshold на H616
easter-egg.patch CONFIG_X96Q_BINARY_BUILD — маркер в SPL, идентификация сборки
fdtfile-armbian.patch fdtfile → имя DTB из Armbian, иначе boot.scr не находит дерево

Восстановление (FEL)

Если eMMC bootloader битый и SD не помогает:

  1. Зажать кнопку FEL, подключить USB (1f3a:efe8)
  2. FEL + sunxi-tools: wipe boot0/boot1/SPL или прошить свежий u-boot-custom.bin

Подробности — в родительском репозитории FEL (fel-recover.sh, fel-wipe-emmc.sh).

Версии

Компонент Версия
U-Boot base v2025.01
ARM TF-A BL31 sun50i_h616
Defconfig Armbian x96_q_lpddr3_v1.3
Плата X96Q LPDDR3 v1.3 (не путать с DDR3 и не-LPDDR3 ревизиями)

Лицензия

Патчи и overlay — поверх GPL-2.0+ U-Boot. DTS: GPL-2.0+ OR MIT (см. заголовок файла).

S
Description
пропатченый U-Boot для x96q
Readme 35 KiB
Languages
Shell 85.5%
Roff 14.5%