Как записать вторичный загрузчик в SPI NOR Flash
Примечания.
1. В приведенной ниже пошаговой инструкции часть пунктов (команд, помеченных звездочкой)
носят проверочный характер и демонстрируют возможности в использование команд, поэтому
являются необязательными и могут быть при желании пропущены.
2. На плате OpiZero2 необходимо соединить дюпон-перемычкой "мама-мама" контакты 9 и 13
на 26-контактном раземе платы. Эта перемычка (GND на GPIO PC5). Эта перемычка нужна только
для работы SPI, но её можно не убирать (особенно, если плата в корпусе), т.к. на обычную
работу с SD-картой она не влияет.
3. Для нормального доступа к TFTP-серверу из сети необходимо на ПК отключить в брандмауэре (в антивирусе)
контроль сетевых соединений или установить разрешающее правило для этого tftp-сервера.
Последовательность действий
1. Скопировать (любым способом) файл загрузчика u-boot-sunxi-with-spl.bin
в корневую папку TFTP-сервера (например, E:/tftp) с переименованием в spispl.bin.
Для этого можно просто использовать файл spispl.bin из zip-архива spispl.zip.
2. Записать на SD-карту с помощью утилиты Win32DiskImager (или аналогичной) файл
spispl.img, извлеченный из архива spispl.zip.
Примечание. В принципе, то же самое можно сделать под Linux командой dd,
записав на карту файл spispl.bin со смещением 8192. Но наша инструкция ориентирована на ПК с Windows.
А продвинутым пользователям Linux эту инструкцию и читать не нужно.
3. Запустить MobaXTerm и открыть окно терминала, подключенного к UART OpiZero2
4. Вставить эту записанную SD-карту в устройство и включить питание, удерживая клавишу 'Пробел'
на клавиатуре ПК. Загрузится U-Boot с SD-карты, лог загрузки которого выглядит так:
U-Boot SPL 2022.10-00409-g2afa989fbe-dirty (Oct 14 2022 - 15:04:08 +0500)
DRAM: 1024 MiB
Trying to boot from MMC1
NOTICE: BL31: v2.5(debug):v2.5
NOTICE: BL31: Built : 11:31:59, Oct 7 2022
NOTICE: BL31: Detected Allwinner H616 SoC (1823)
NOTICE: BL31: Found U-Boot DTB at 0x4a09c900, model: OrangePi Zero2
INFO: ARM GICv2 driver initialized
INFO: Configuring SPC Controller
INFO: PMIC: Probing AXP305 on RSB
INFO: PMIC: aldo1 voltage: 3.300V
INFO: PMIC: aldo2 voltage: 3.300V
INFO: PMIC: aldo3 voltage: 3.300V
INFO: PMIC: bldo1 voltage: 1.800V
INFO: PMIC: dcdcd voltage: 1.500V
INFO: PMIC: dcdce voltage: 3.300V
INFO: Changed devicetree to reserve BL31 memory.
INFO: BL31: Platform setup done
INFO: BL31: Initializing runtime services
INFO: BL31: cortex_a53: CPU workaround for 855873 was applied
INFO: BL31: cortex_a53: CPU workaround for 1530924 was applied
INFO: PSCI: Suspend is unavailable
INFO: BL31: Preparing for EL3 exit to normal world
INFO: Entry point address = 0x4a000000
INFO: SPSR = 0x3c9
U-Boot 2022.10-00409-g2afa989fbe-dirty (Oct 14 2022 - 15:04:08 +0500) Allwinner Technology
CPU: Allwinner H616 (SUN50I)
Model: OrangePi Zero2
DRAM: 1 GiB
Core: 56 devices, 19 uclasses, devicetree: separate
WDT: Not starting watchdog@30090a0
MMC: mmc@4020000: 0
Loading Environment from FAT... Unable to use mmc 0:0...
In: serial@5000000
Out: serial@5000000
Err: serial@5000000
Net: eth0: ethernet@5020000
starting USB...
Bus usb@5101000: probe failed, error -38
Bus usb@5101400: USB OHCI 1.0
Bus usb@5200000: probe failed, error -38
Bus usb@5200400: USB OHCI 1.0
scanning bus usb@5101400 for devices... 1 USB Device(s) found
scanning bus usb@5200400 for devices... 1 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
Hit any key to stop autoboot: 0
=>
5. Запустить на ПК TFTP-сервер и запомнить его IP-адрес
(например, 192.168.0.105 - это IP сетевой карты компьютера)
6. Установить в U-Boot переменную serverip командой
env set serverip
=> env set serverip 192.168.0.105
=> env print serverip
ipaddr=192.168.0.105
7. Установить в U-Boot переменную ipaddr командой env set ipaddr
Примечание. 192.168.0.122 - это статический IP-адрес платы из ARP-таблицы роутера,
привязанный к МАС-адресу Ethernet платы
=> env set ipaddr 192.168.0.122
=> env print ipaddr
ipaddr=192.168.0.122
8. Загрузить файл загрузчика в память командой tftpboot
=> tftpboot 0x45000000 spl.bin
Using ethernet@5020000 device
TFTP from server 192.168.0.105; our IP address is 192.168.0.122
Filename 'spl.bin'.
Load address: 0x45000000
Loading: #################################################
2.9 MiB/s
done
Bytes transferred = 754349 (b82ad hex)
=>
9. * Проверить размер загруженного файла командой env print filesize
=> env print filesize
filesize=b82ad
=>
10. * Прочитать содержимое памяти (для проверки) командой md
=> md 0x45000000
45000000: ea000016 4e4f4765 3054422e 9e2dbf8d ....eGON.BT0..-.
45000010: 0000a000 024c5053 00000000 00000000 ....SPL.........
45000020: 0000002c 00000000 00000000 356e7573 ,...........sun5
45000030: 682d6930 2d363136 6e61726f 69706567 0i-h616-orangepi
45000040: 72657a2d 0000326f 00000000 00000000 -zero2..........
45000050: 00000000 00000000 00000000 00000000 ................
45000060: ea00001f 14000041 00000000 00000000 ....A...........
45000070: 00000000 00000000 00000000 00000000 ................
45000080: 00000000 00000000 00000000 00000000 ................
45000090: 00000000 00000000 00000000 00000000 ................
450000a0: 00000000 00000000 00000000 00000000 ................
450000b0: 00000000 00000000 00000000 00000000 ................
450000c0: 00000000 00000000 00000000 00000000 ................
450000d0: 00000000 00000000 00000000 00000000 ................
450000e0: 00000000 e28f0058 e59f1054 e0800001 ....X...T.......
450000f0: e580d000 e580e004 e10fe000 e580e008 ................
=>
11. Инициализировать SPI командой sf probe
=> sf probe
SF: Detected mx25l1606e with page size 256 Bytes, erase size 4 KiB, total 2 MiB
=>
12. Очистить SPI командой sf erase (первая половина памяти)
=> sf erase 0 +0xf0000
SF: 983040 bytes @ 0x0 Erased: OK
=>
13. Записать в SPI $filesize байт со смещением 0 байт
командой sf write
=> sf write 0x45000000 0
device 0 offset 0x0, size 0xb82ad
SF: 754349 bytes @ 0x0 Written: OK
=>
14. * Прочитать SPI в другую область памяти командой sf read
=> sf read 0x46000000 0
device 0 offset 0x0, size 0xb82ad
SF: 754349 bytes @ 0x0 Read: OK
=>
15. * Показать дамп памяти командой md
=> md 0x46000000
46000000: ea000016 4e4f4765 3054422e 9e2dbf8d ....eGON.BT0..-.
46000010: 0000a000 024c5053 00000000 00000000 ....SPL.........
46000020: 0000002c 00000000 00000000 356e7573 ,...........sun5
46000030: 682d6930 2d363136 6e61726f 69706567 0i-h616-orangepi
46000040: 72657a2d 0000326f 00000000 00000000 -zero2..........
46000050: 00000000 00000000 00000000 00000000 ................
46000060: ea00001f 14000041 00000000 00000000 ....A...........
46000070: 00000000 00000000 00000000 00000000 ................
46000080: 00000000 00000000 00000000 00000000 ................
46000090: 00000000 00000000 00000000 00000000 ................
460000a0: 00000000 00000000 00000000 00000000 ................
460000b0: 00000000 00000000 00000000 00000000 ................
460000c0: 00000000 00000000 00000000 00000000 ................
460000d0: 00000000 00000000 00000000 00000000 ................
460000e0: 00000000 e28f0058 e59f1054 e0800001 ....X...T.......
460000f0: e580d000 e580e004 e10fe000 e580e008 ................
=>
Примечание. Наличие подписи eGON.BT0 в массиве данных,
начиная с 5-го байта, свидетельствует о том, что это -
начало вторичного загрузчика Boot0 (он же SPL). т.е. загрузчик записан в SPI
правильно (с высокой вероятностью).
Краткий список команд для записи загрузчика:
(который можно целиком запустить в оболочке U-Boot простым копи-паст)
env set serverip 192.168.0.105
env set ipaddr 192.168.0.122
tftpboot 0x45000000 spl.bin
sf probe
sf erase 0 +0xf0000
sf write 0x45000000 0
Таким образом, в результате выполненных выше команд вторичный загрузчик SPL успешно записан
в энергонезависимую память SPI Flash на плате OrangePi Zero2. Теперь можно, отключив питание,
вынуть SD-карту с загрузчиком, при этом устройство останется с хранящимся в нём загрузчиком.
После включения платы без SD-карты на терминале будет отображаться процесс загрузки, который
завершится переходом в оболочку (командный интерфейс) U-Boot. Оболочка откроется немедленно
при зажатой клавише 'Пробел' или чуть поже после попыток U-Boot найти и загрузить ядро системы.
Лог загрузки из SPI выглядит аналогично логу загрузки с SD-карты.
U-Boot SPL 2022.10-00409-g2afa989fbe-dirty (Oct 14 2022 - 15:04:08 +0500)
DRAM: 1024 MiB
Trying to boot from sunxi SPI
NOTICE: BL31: v2.5(debug):v2.5
NOTICE: BL31: Built : 11:31:59, Oct 7 2022
NOTICE: BL31: Detected Allwinner H616 SoC (1823)
NOTICE: BL31: Found U-Boot DTB at 0x4a09c900, model: OrangePi Zero2
INFO: ARM GICv2 driver initialized
INFO: Configuring SPC Controller
INFO: PMIC: Probing AXP305 on RSB
INFO: PMIC: aldo1 voltage: 3.300V
INFO: PMIC: aldo2 voltage: 3.300V
INFO: PMIC: aldo3 voltage: 3.300V
INFO: PMIC: bldo1 voltage: 1.800V
INFO: PMIC: dcdcd voltage: 1.500V
INFO: PMIC: dcdce voltage: 3.300V
INFO: Changed devicetree to reserve BL31 memory.
INFO: BL31: Platform setup done
INFO: BL31: Initializing runtime services
INFO: BL31: cortex_a53: CPU workaround for 855873 was applied
INFO: BL31: cortex_a53: CPU workaround for 1530924 was applied
INFO: PSCI: Suspend is unavailable
INFO: BL31: Preparing for EL3 exit to normal world
INFO: Entry point address = 0x4a000000
INFO: SPSR = 0x3c9
U-Boot 2022.10-00409-g2afa989fbe-dirty (Oct 14 2022 - 15:04:08 +0500) Allwinner Technology
CPU: Allwinner H616 (SUN50I)
Model: OrangePi Zero2
DRAM: 1 GiB
Core: 56 devices, 19 uclasses, devicetree: separate
WDT: Not starting watchdog@30090a0
MMC: mmc@4020000: 0
Loading Environment from SPIFlash... SF: Detected mx25l1606e with page size 256 Bytes, erase size 4 KiB, total
*** Warning - bad CRC, using default environment
Loading Environment from FAT... MMC: no card present
** Bad device specification mmc 0 **
In: serial@5000000
Out: serial@5000000
Err: serial@5000000
Net: eth0: ethernet@5020000
starting USB...
Bus usb@5101000: probe failed, error -38
Bus usb@5101400: USB OHCI 1.0
Bus usb@5200000: probe failed, error -38
Bus usb@5200400: USB OHCI 1.0
scanning bus usb@5101400 for devices... 1 USB Device(s) found
scanning bus usb@5200400 for devices... 1 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
Hit any key to stop autoboot: 0
=>