Ниже — набор практических шагов и приёмов, которые обычно помогают локализовать и исправить зависание на этапе «Starting kernel…» при загрузке RK3568 из U‑Boot. Пишите по шагам, пробуйте и возвращайтесь с результатами — дам дальнейшие рекомендации.
1) Убедитесь, что вы действительно прыгаете в правильный образ (Image / тип команды)
- Для aarch64 в U‑Boot обычно нужно загружать несжатый linux Image и использовать команду booti:
- Пример:
setenv fdt_addr_r 0x46000000
setenv kernel_addr_r 0x42000000
booti ${kernel_addr_r} - ${fdt_addr_r}
- Если у вас zImage / Image.gz — используйте соответствующую команду (bootz), но для arm64 стандартом является Image+booti. Ошибочный тип загрузки может привести к немедленному зависанию.
2) Проверьте, что DTB правильный и передан корректно
- В U‑Boot: fdt addr ${fdt_addr_r} ; fdt check || echo "DTB corrupted"
- Убедитесь, что DTB соответствует конкретной плате/Inmys SOM. Неправильный DTB может привести к тому, что контроллеры питания/клоки/порты будут настроены неверно и ядро «ушло в тихий WFI».
- Попробуйте загрузить тот же DTB/ядро, который поставляет продавец платы (если есть) — это быстрый тест на совместимость.
3) Уточните консоль (console) — самая частая причина «нет вывода»
- U‑Boot печатает «Starting kernel…», но ядро может писать в другой UART. Проверьте bootargs: printenv bootargs
- Приведите корректный console=... в bootargs, например:
- setenv bootargs 'console=ttyS2,115200 root=/dev/ram0 rw rootwait loglevel=8'
- Для ранних сообщений (до драйверов) используйте earlycon:
- Найдите физ. адрес UART в DTB (узел uart@...) и добавьте, например:
earlycon=pl011,mmio,0xff180000
- Или: earlycon=uart8250,mmio,0xff180000
- Если не знаете адреса UART — откройте DTS/DTB и найдите node uart@xxxxxx (reg).
4) Включите в ядре низкоуровневую отладку (если ещё не включили)
- CONFIG_EARLY_PRINTK / CONFIG_DEBUG_LL — при включении дают вывод до initramfs и большинства драйверов.
- Убедитесь, что драйвер UART, соответствующий раннему консоли, встроен в ядро (не модулем).
5) Попробуйте простую initramfs / root=/dev/ram0
- Сформируйте initramfs с /init, который сразу делает printk и sleep, чтобы понять, успешно ли ядро проходит init:
- Используйте rdinit=/init или root=/dev/ram0
- Таким образом можно проверить, что проблема — в инициализации rootfs или в самом ядре на более ранней стадии.
6) Логирование/повышение уровня логов
- Добавьте в bootargs: loglevel=8 initcall_debug printk.time=1 panic=10
- initcall_debug помогает увидеть, если зависание происходит в ранних initcalls.
7) Нет вывода, но ядро запущено — альтернативные каналы
- Netconsole: если network stack и драйвер инициализируются достаточно рано, можно настроить netconsole=... в bootargs и ловить printk в сети. Это может помочь, когда UART не работает.
- Если нет вывода совсем — JTAG / аппаратный отладчик (J‑Link, OpenOCD). С помощью JTAG можно посмотреть, где «застрял» CPU (адрес PC), стек, регистры.
8) Проверка специфики Rockchip (питание/BL31/ATF)
- RK SoC обычно зависит от BL31 (ARM Trusted Firmware) и от правильных параметров в DTB (power domains, regulators). Если вы меняли BL31/ATF/firmware, убедитесь, что:
- СBL31 корректен и совместим с вашим U‑Boot/ядром.
- Не нарушено управление питанием/клоками.
- Если BL31 некорректен, U‑Boot мог запуститься, но ядро потом вызывает операции с power domains и «зависает».
9) Проверка образа/адресов загрузки
- Убедитесь, что kernel_addr_r и fdt_addr_r не пересекаются и загружаются в правильные места.
- В U‑Boot: md ${kernel_addr_r} 8 ; md ${fdt_addr_r} 20 — проверить содержание.
10) Диагностика «без вывода» — как быстро проверить, запустилось ли ядро
- Попробуйте загрузить простой тестовый образ, например upstream kernel build с minimal defconfig для rk3568 или vendor image, который точно работает на плате — это позволит отделить проблему ядра от конфигурации.
- Если upstream тоже «виснет», вероятность аппаратного/firmware/DTB вопроса выше.
11) Конкретные примеры команд в U‑Boot
- Пример последовательности:
- setenv kernel_addr_r 0x42000000
- setenv fdt_addr_r 0x46000000
- setenv bootargs 'console=ttyS2,115200 earlycon=pl011,mmio,0xff180000 root=/dev/ram0 rw rootwait loglevel=8 initcall_debug'
- booti ${kernel_addr_r} - ${fdt_addr_r}
12) Если всё ещё виснет — что собрать и прислать мне
- Вывод serial порта вплоть до «Starting kernel…»
- Содержимое bootargs и используемые адреса (kernel_addr_r, fdt_addr_r)
- Версия U‑Boot, команда загрузки (booti/bootz/bootm), тип образа (Image/zImage/fit)
- Фрагмент DTS (uart node, chosen/stdout-path)
- Конфигурация ядра (или минимум: включены ли CONFIG_EARLY_PRINTK/DEBUG_LL)
- Информация о BL31/ATF (версия/файлы) и схема загрузки вашей платы
Короткое итоговое руководство действий сейчас (порядок, который рекомендую выполнить немедленно):
1. Проверить и явным образом задать правильный console= и earlycon= в bootargs. Перезагрузить и смотреть serial.
2. Убедиться, что вы используете booti + Image + корректный DTB.
3. Пересобрать ядро с CONFIG_EARLY_PRINTK/CONFIG_DEBUG_LL и сделать earlycon совпадающим с адресом UART из DTS.
4. Если по serial по‑прежнему нет вывода — попробовать netconsole или JTAG.
Если пришлёте вывод serial (до и после «Starting kernel…»), ваш bootargs и строки U‑Boot (каким образом загружаете образы), помогу локализовать дальше и предложу, какие параметры ещё менять.