1

Я создал образ для платы Freescale iMX6 EVK (на базе ARM), используя Buildroot. Он нормально загружался с SD-карты, и я хотел поэкспериментировать с настраиваемыми командами загрузки в U-Boot. Я хочу сделать загрузочную последовательность максимально быстрой и быстрой, поэтому я упростил некоторые проверки и тесты, выполняемые U-Boot (например, удалил проверку для сценария загрузки и загрузки по сети).

Вот моя переменная bootcmd U-Boot env (отформатированная для легкого чтения):

bootcmd=
echo Booting from SD...;
mmc dev ${mmcdev};
if mmc rescan; then
  setenv mmcroot /dev/mmcblk1p2 rootwait ro;
  setenv bootargs console=${console},${baudrate} root=${mmcroot};
  fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image};
  setenv fdt_file imx6ull-14x14-evk.dtb;
  fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file};
  bootz ${loadaddr} - ${fdt_addr};
else 
  echo Boot FAILED: Couldnt find kernel or dtb;
fi

когда я включаю плату, после нажатия любой клавиши, чтобы остановить автозагрузку, я получаю это:

Hit any key to stop autoboot:  0 
Booting from SD...
switch to partitions #0, OK
mmc1 is current device
reading zImage
4652504 bytes read in 369 ms (12 MiB/s)
reading imx6ull-14x14-evk.dtb
33755 bytes read in 30 ms (1.1 MiB/s)
Kernel image @ 0x80800000 [ 0x000000 - 0x46fdd8 ]
## Flattened Device Tree blob at 83000000
   Booting using the fdt blob at 0x83000000
   Using Device Tree in place at 83000000, end 8300b3da

Starting kernel ...

Затем он зависает на этапе «Starting kernel ...».

ОДНАКО, если я прерву U-Boot нажатием Enter, то (из приглашения U-Boot) запустите одну из следующих команд:

boot

или же

run bootcmd

Он показывает те же сообщения, что и выше, но затем ядро запускается в порядке.

Я сравнил результаты в обоих случаях, и они идентичны до "Стартовое ядро". Я также добавил строку в bootcmd для вывода переменных env (printenv) и подтвердил, что переменные также идентичны в обоих случаях. Вот последние ботарги (напечатанные с помощью echo ${bootargs}) - они также одинаковы в обоих случаях:

console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait ro 

Я думал, что команда boot только что выполнила bootcmd, и что процесс автоматической загрузки сделал то же самое, если не был прерван.

Так почему же это работает, если я прерываю его и запускаю boot вручную?

==== РЕДАКТИРОВАТЬ ====

После комментариев от опилок я провел еще несколько экспериментов, чтобы прояснить проблему.

1/ Добавлен 'earlyprintk' в сборку ядра (опции взлома ядра).

Это привело к тому, что при успешной загрузке было напечатано следующее:

Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0

При неудачной загрузке он по-прежнему останавливается на «Запуск ядра ...» (никакой дополнительной информации от earlyprintk).

2/ Дальнейший взлом bootcmd для выяснения проблемы.

Вот переменная env "bootcmd" по умолчанию, созданная новой сборкой (Примечание: обычно это все в одной строке, то есть «bootcmd = ....»; отформатировано здесь для ясности):

run findfdt;
mmc dev ${mmcdev};
mmc dev ${mmcdev};
if mmc rescan; then 
 if run loadbootscript; then
  run bootscript;
 else 
  if run loadimage; then
   run mmcboot;
  else
   run netboot;
  fi;
 fi;
else 
 run netboot;
fi

Это работает (то есть автоматическая загрузка после задержки загрузки).

Вот моя минимальная модификация:

run findfdt;
mmc dev ${mmcdev};
mmc dev ${mmcdev};
mmc rescan;
if run loadbootscript; then
  run bootscript;
else 
  if run loadimage; then
   run mmcboot;
  else
   run netboot;
  fi;
fi;

Все, что я сделал, это удалил внешнюю структуру if (если mmc повторно сканирует; затем ...). Это все еще называет "mmc rescan", который преуспевает.

Обратите внимание, что это сохраняется, поместив вышеуказанное в одну строку ('xxxx') и используя:

setenv bootcmd 'xxxxx'
saveenv

Это приводит к зависанию платы на «Starting kernel ...», но если я прерву автоматическую загрузку, введите приглашение u-boot, а затем используйте "boot", она загрузится нормально.

Я могу вернуться к исходному bootcmd, и он работает правильно (с автоматической загрузкой все в порядке), поэтому я думаю, что метод изменения переменной - это нормально.

Однажды я увидел одну странную вещь, когда изменил ее на свою версию:

Starting kernel ...
resetting ...

[Board Rebooted itself!]

U-Boot 2016.03 (Nov 16 2017 - 07:08:36 +1300)

[Auto-boot]

Starting kernel ...    
[Hang.]

С тех пор все вернулось к зависанию, если я не прерву загрузку и не введу команду "boot".

Ошибка в U-Boot? переменные среды u-boot как-то повреждены?

Nb: Сейчас это не главная проблема, но я думаю, что мы могли бы сэкономить несколько мс, избавившись от бессмысленного поиска загрузочного скрипта, которого, как я знаю, там нет, и в будущем у нас может быть причина настроить загрузку по какой-то другой причине, и я хотел бы знать, что это можно сделать предсказуемо!

1 ответ1

0

После дополнительных экспериментов я обнаружил, что следующие РАБОТЫ:

bootcmd=
setenv fdt_file imx6ull-14x14-evk.dtb; 
setenv bootargs console=${console},${baudrate} root=${mmcroot}; 
mmc dev ${mmcdev};
mmc rescan;
fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}; 
fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}; 
bootz ${loadaddr} - ${fdt_addr}

...Но это НЕДОСТАТКИ:

bootcmd=
setenv fdt_file imx6ull-14x14-evk.dtb; 
setenv bootargs console=${console},${baudrate} root=${mmcroot}; 
mmc dev ${mmcdev};
if true; then 
 mmc rescan; 
 fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}; 
 fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}; 
 bootz ${loadaddr} - ${fdt_addr}; 
else 
 echo Boot FAILED: Couldnt find kernel or dtb;
fi

(Отформатировано на несколько строк для ясности). Под "сбоями" я подразумеваю, что при включении питания он ожидает истечения времени автозагрузки, загружает ядро и dtb, затем висит на «Starting Kernel ...» и должен быть выключен или сброшен. Однако, если я нажимаю клавишу для прерывания автоматической загрузки, а затем набираю "boot" или "run bootcmd", он загружается нормально (хотя он запускает точно такой же сценарий).

Так что по какой-то причине использование оператора if в скрипте bootcmd (даже тривиального) нарушает его, хотя я не знаю почему.

Это не очень хороший ответ, но, по крайней мере, я получил его на работу. Оригинальный проект имел оператор if, проверяющий результат "mmc rescan", но я думаю, что если это не удастся, он все равно остановится с некоторой ошибкой.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .