В данном руководстве рассматриваются вопросы установки и настройки загрузчика U-Boot и ОС Linux (на примере ArchLinux ARM) на плату Orange Pi One (процессор (SoC) AllWinner H3).
Редакция январь, 2019 г.
Для сборки загрузчика, ядра и ПО Linux необходима установка набора инструментов (toolchain).
Рекомендуется использовать последнюю версию linaro toolchain, на данный момент
https://releases.linaro.org/components/toolchain/binaries/7.4-2019.02/arm-linux-gnueabihf/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabihf.tar.xz
Распаковываем архив, например, в каталог /opt/
.
Далее можно поставить символьную ссылку, чтобы корневой путь toolchain был удобным:
ln -s gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabihf /opt/gcc-linaro
Примечание: данная сборка имеет множество повторяющихся файлов. Данный скрипт освободит 137 Мбайт. Запускать из каталога gcc-linaro.
cd bin rm arm-linux-gnueabihf-c++ ln -s arm-linux-gnueabihf-g++ arm-linux-gnueabihf-c++ rm arm-linux-gnueabihf-gcc ln -s arm-linux-gnueabihf-gcc-6.3.1 arm-linux-gnueabihf-gcc rm arm-linux-gnueabihf-ld ln -s arm-linux-gnueabihf-ld.bfd arm-linux-gnueabihf-ld cd .. cd arm-linux-gnueabihf rm -r lib ln -s libc/lib lib rm bin/* for t in ar as ld ld.bfd ld.gold nm objcopy objdump ranlib readelf strip do ln -s ../../bin/arm-linux-gnueabihf-$t bin/$t done rm libc/usr/libexec/getconf/* for t in POSIX_V6_ILP32_OFF32 POSIX_V6_ILP32_OFFBIG POSIX_V7_ILP32_OFF32 POSIX_V7_ILP32_OFFBIG XBS5_ILP32_OFF32 XBS5_ILP32_OFFBIG do ln -s ../../bin/getconf libc/usr/libexec/getconf/$t done cd .. cd share/man/man1 rm arm-linux-gnueabihf-g++.1 ln -s arm-linux-gnueabihf-gcc.1 arm-linux-gnueabihf-g++.1
Затем настраиваем окружение, в котором далее будет выполняться сборка загрузчика U-Boot и ядра:
export ARCH=arm export CROSS_COMPILE=arm-linux-gnueabihf- export PATH=/opt/gcc-linaro/bin:$PATH
После этого в командах make
уже не нужно указывать архитектуру и тип кросс-компиляции.
Для сборки образа загрузчика также могут понадобиться пакеты bison, flex, python-devel.
Предлагается разметка SD-карты на основе GPT с отдельными разделами для ядра, rootfs, программ и данных пользователя. Учитывая требования SoC, начало таблицы разделов GPT необходимо перенести далее 1024 сектора. В данном руководстве рассматривается вариант разметки с началом таблицы разделов на секторе 2048. Запись MBR и заголовок GPT находятся стандартно в секторах 0-1.
No | Первый сектор | Последний сектор | Всего секторов | Первый байт | Послед. байт | Размер | Назначение |
---|---|---|---|---|---|---|---|
1 | 0 | 0 | 1 | 0 | 511 | 512 б | MBR |
2 | 1 | 1 | 1 | 512 | 1023 | 512 б | GPT header |
3 | 2 | 15 | 14 | 1024 | 8191 | 7 кб | свободно |
4 | 16 | 79 | 64 | 8192 | 40959 | 32 кб | U-Boot SPL |
5 | 80 | 1167 | 1088 | 40960 | 598015 | 544 кб | U-Boot |
6 | 1168 | 1423 | 256 | 598016 | 729087 | 128 кб | U-Boot Environment |
7 | 1424 | 2047 | 624 | 729088 | 1048575 | 312 кб | свободно |
8 | 2048 | 2079 | 32 | 1048576 | 1064959 | 16 кб | GPT partition table |
Области 5 и 6 желательно обнулять перед установкой U-Boot.
Границы областей 5 и 6 определяются настройками U-Boot (команда make menuconfig
):
Environment → Environment Offset
(значение 0x88000) и Environment → Environment Size
(значение 0x20000).
Для установки и настройки GPT рекомендуется утилита gdisk
версии 1.0.3 или более поздней из пакета gptfdisk.
Особенностью установки является задание расположения самой таблицы разделов с сектора 2048:
x
(режим эксперта)j
(установить начало таблицы).Ниже приведен пример разметки SD-карты (номинальная ёмкость 8 Гбайт). Последний раздел DATA может иметь любой приемлемый размер.
Number | Start (sector) | End (sector) | Size | Label | FS, Mode | Назначение |
1 | 4096 | 69631 | 32.0 MiB | BOOT1 | ext2, ro | ядро |
2 | 69632 | 135167 | 32.0 MiB | BOOT2 | ext2, ro | ядро (альтернативный) |
3 | 135168 | 4329471 | 2.0 GiB | ROOTFS1 | ext2, rw/ro | root fs |
4 | 4329472 | 8523775 | 2.0 GiB | ROOTFS2 | ext2, rw/ro | root fs (альтернативный) |
5 | 8523776 | 9572351 | 512.0 MiB | HOME | ext4, rw | /home |
6 | 9572352 | 10620927 | 512.0 MiB | USER | ext2, rw/ro | программы пользователя |
7 | 10620928 | 14815231 | 2.0 GiB | DATA | ext4, rw | данные /var |
Для разделов 1,2,3,4 и 6 создать файловую систему EXT2:
mkfs.ext2 -L BOOT1 /dev/sde1 mkfs.ext2 -L BOOT2 /dev/sde2 mkfs.ext2 -L ROOTFS1 /dev/sde3 mkfs.ext2 -L ROOTFS2 /dev/sde4 mkfs.ext2 -L USER /dev/sde6
Для разделов 5 и 7 создать файловую систему EXT4:
mkfs.ext4 -L HOME /dev/sde5 mkfs.ext4 -L DATA /dev/sde7
Во всех примерах предполагается, что SD-карта в хост-системе видна как /dev/sde
.
Также для удобства дальнейшего использования указаны метки разделов.
Скачать исходный код загрузчика с ftp://ftp.denx.de/pub/u-boot/. В данном примере использована версия 2019-01.
Загружаем базовую конфигурацию для данной платы:
make orangepi_one_defconfig
Выполняем тонкую настройку U-Boot:
make menuconfig
В меню выбрать Environment —> Environment in an MMC device
.
Отменить File systems —> Enable FAT filesystem write support
,
а также поддержку записи для всех остальных файловых систем.
Сохранить конфигурацию (файл .config
).
Собираем загрузчик:
make -j4 all
После успешной сборки в корневом каталоге исходников будет сам загрузчик u-boot-sunxi-with-spl.bin
.
Устанавливаем SPL и загрузчик на SD-карту $DEV
, но перед этим обнуляем область под U-Boot и его данные:
DEV=/dev/sde dd if=/dev/zero of=$DEV seek=80 count=1344 dd if=u-boot/u-boot-sunxi-with-spl.bin of=$DEV seek=16 sync
Вставляем SD-карту в плату Orange Pi One и через UART смотрим вывод загрузчика. Прерываем процесс автозагрузки ОС нажатие любой клавиши в терминале при получении сообщения
Hit any key to stop autoboot:
При первой загрузке может вылезти сообщение
*** Warning - bad CRC, using default environment
— это нормально для первой загрузки.
Далее в командной строке выполняем команды дальнейшей настройки автозагрузки:
setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p3 rootwait rw panic=2 setenv bootcmd 'load mmc 0:1 ${kernel_addr_r} /zImage; load mmc 0:1 ${fdt_addr_r} /dtbs/${fdtfile}; bootz ${kernel_addr_r} - ${fdt_addr_r}' saveenv reset
Установка и настройка U-Boot теперь завершена. Ядро будет стартовать с первого раздела, а rootfs будет находиться на третьем разделе mmc0
.
U-Boot SPL 2019.01 (Jan 31 2019 - 14:37:05 +0300) DRAM: 512 MiB Trying to boot from MMC1 U-Boot 2019.01 (Jan 31 2019 - 14:37:05 +0300) Allwinner Technology CPU: Allwinner H3 (SUN8I 1680) Model: Xunlong Orange Pi One DRAM: 512 MiB MMC: SUNXI SD/MMC: 0 Loading Environment from MMC... OK In: serial Out: serial Err: serial Net: phy interface0 eth0: ethernet@1c30000 starting USB... USB0: USB EHCI 1.00 USB1: USB OHCI 1.0 USB2: USB EHCI 1.00 USB3: USB OHCI 1.0 scanning bus 0 for devices... 1 USB Device(s) found scanning bus 2 for devices... 1 USB Device(s) found scanning usb for storage devices... 0 Storage Device(s) found Hit any key to stop autoboot: 0
Если что-то не заработало, то начинаем поэтапно разбираться.
Пример пошагового запуска приведен ниже. Значения всех используемых переменных можно вывести через команду printenv varname
или echo ${varname}
.
=> load mmc 0:3 ${kernel_addr_r} /boot/zImage 4067176 bytes read in 189 ms (20.5 MiB/s) => echo ${fdt_addr_r} 0x43000000 => echo ${fdtfile} sun8i-h3-orangepi-one.dtb => load mmc 0:3 ${fdt_addr_r} /boot/dtbs/${fdtfile} 20112 bytes read in 11 ms (1.7 MiB/s)
wget http://archlinuxarm.org/os/ArchLinuxARM-armv7-latest.tar.gz
Now mount the SD Card ext4 partition and extract the official image inside: (The following commands may require root privileges!)
mkdir ArchARM mount /dev/sdX1 ArchARM bsdtar -zxvf ArchLinuxARM-armv7-latest.tar.gz -C ArchARM sync
You should now have a folder called linux with the kernel in it and another one called ArchARM mounted on the SD card partition 1. (Rename the kernel folder accordingly)
Используем Mainline версию ядра с GIT-репозитория sunxi-next:
git clone git://github.com/linux-sunxi/linux-sunxi.git -b sunxi-next --depth=20
Для сборки самой последней версии (на данный момент 5.0.0) параметр –depth достаточно установить в 1. Если необходимо переключиться, например, на версию 4.20.0, то скачивать надо минимум с –depth=20. Для перехода на иную версию, делаем checkout, например, для версии 4.20.0:
git checkout 8fe28cb58bcb235034b64cbbb7550a8a43fd88be
Далее все действия выполняются в корневом каталоге исходного кода linux-sunxi
.
В выбранной версии ядра (4.20.0) не заработал framebuffer. Опытным путем установлено следующее решение проблемы:
arch/arm/boot/dts/sunxi-h3-h5.dtsi
секцию chosen
, в которой описаны устройства framebuffer-hdmi
и framebuffer-tve
.simplefb_hdmi
в файл arch/arm/boot/dts/sun8i-h3.dtsi
. Для этого наложить патч, который добавляет framebuffer в device tree для H3 (http://orangepi.pp.ua/index.php/topic,406.15.html?PHPSESSID=32008a926e97c20dd94bbaa03a46789d).Патч, адаптированный для linux-sunxi-next 4.20.0 можно сразу взять здесь: sun8i-h3-simplefb.patch.gz. Далее:
patch -p1 < sun8i-h3-simplefb.patch
Включаем встроенные в SoC UART1 и UART2 при необходимости (аналогично с UART3). Для этого в файле
arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
в секциях настройки &uart1
и &uart2
исправляем status
с disabled
на okay
:
&uart1 { pinctrl-names = "default"; pinctrl-0 = <&uart1_pins>; status = "okay"; }; &uart2 { pinctrl-names = "default"; pinctrl-0 = <&uart2_pins>; status = "okay"; };
После загрузки системы данные порты будут видны как /dev/ttyS1
и /dev/ttyS2
соответственно.
Порт UART0 /dev/ttyS0
- консоль управления, выводы которой (GND,TX,RX) выведены на плате отдельно около разъема RJ-45. Расположение выводов UART1 и UART2 см. на схеме ниже.
Описание конкретных выводов для портов указано в файле arch/arm/boot/dts/sunxi-h3-h5.dtsi
, который должен помочь на случай необходимости использования RTS/CTS.
Выбираем базовый конфигурационный файл для сборки ядра:
make sunxi_defconfig
Для более тонкой настройки запускаем конфигурацию через меню:
make menuconfig
Отключаем поддержку initramfs:
General setup
—> Initial RAM filesystem and RAM disk (initramfs/initrd) support
убираем.Выбираем поддержку framebuffer:
Device Drivers
—> Graphics support
—> Frame buffer Devices
, отмечаем Support for frame buffer devices
,Simple framebuffer support
.Device Drivers
—> Graphics support
—> Console display driver support
, отмечаем Framebuffer Console support
.
Включаем поддержку DE2 CCU clock driver (опция CONFIG_SUN8I_DE2_CCU
):
Device Drivers
—> Common Clock Framework
—> Support for the Allwinner SoCs DE2 CCU
.Отключаем поддержку других SoC:
System type
—> Allwinner SoCs
—> оставить только Allwinner sun8i Family SoCs support
.Device Drivers
—> Graphics support
—> убрать DRM Support for Allwinner A10 Display Engine
.
Включаем поддержку USB-периферии в меню Device Drivers
—> USB support
:
[*] OTG support <M> USB Modem (CDC ACM) support <*> USB Mass Storage support <*> USB Serial Converter support ---> [*] USB Serial Console device support [*] USB Generic Serial Driver <M> USB Serial Simple Driver <M> USB Belkin and Peracom Single Port Serial Driver <M> USB Winchiphead CH341 Single Port Serial Driver <M> USB CP210x family of UART Bridge Controllers <M> USB FTDI Single Port Serial Driver <M> USB Prolific 2303 Single Port Serial Driver <M> USB driver for GSM and CDMA modems
Далее для включения драйвера framebuffer в аргументах ядра (см. параметр U-Boot bootcmd
) нужно будет указать console=tty1
.
И, наконец, можно установить строку, добавляемую в версию ядра
- General setup
—> Local version
.
Начать строку лучше со знака «-».
Чтобы в конце не добавлялся «+», нужно создать в корневом каталоге сборки пустой файл .scmversion
:
touch .scmversion
Собственно компиляция:
make -j4 zImage dtbs modules make INSTALL_MOD_PATH=output modules_install make INSTALL_MOD_PATH=output firmware_install make INSTALL_MOD_PATH=output headers_install INSTALL_HDR_PATH=output/usr
Замечание:
make INSTALL_MOD_PATH=output firmware_install
скорее всего не понадобится.Как было сказано выше, ядро устанавливаем в отдельный раздел (BOOT1):
BOOTDIR=/run/media/user/BOOT1 ROOTDIR=/run/media/user/ROOTFS1 #Cleaning up rm -r $BOOTDIR/zImage rm $BOOTDIR/dtbs/* #Copying cp -R linux/arch/arm/boot/zImage $BOOTDIR/ cp -R linux/arch/arm/boot/dts/sun8i-h3*.dtb $BOOTDIR/dtbs/ cp -R linux/output/lib/ $ROOTDIR/usr/ cp -R linux/output/usr/ $ROOTDIR/
CPU Core frequency adjusting in U-Boot
Run make menuconfig:
Boot Images —> CPU Clock frequency
Default should be 1080 (Mhz); I lowered it to 816 Mhz
Voltage Regulator SY8113B patch
The following enables the On-Board Voltage regulator which can switch the Core voltage between 1.1V and 1.3V (Should NEVER exceed 1.5V)
Patch here: https://patchwork.kernel.org/patch/9198383/ download and save as patch.diff in linux/arch/arm/boot/dts. Then run:
patch < patch.diff
Check that our SY8113B is working by checking the 1V2C voltage point on the PCB (near the main processor). It should read 1.1V for frequencies ⇐ 816 Mhz
Be aware that as of right now no CPU scaling is implemented in the mainline kernel, so the U-boot clock speed is used instead.
GPIO C Library
This works: https://github.com/zhaolei/WiringOP | gpio readall to list GPIO Layout. | No PWM support
My Kernel Config (archlinuxarm-linux-v7 based): Download
Thanks to tekdoc.
Удаление ядра ArchLinux и прошивок. После удаления нужно заново скопировать на SD-карту ядро zImage и файлы /boot/dtbs/*.
pacman -R linux-armv7 linux-firmware mkinitcpio mkinitcpio-busybox
Удаление оставшихся файлов:
rm -R /usr/lib/firmware/
Удаление ненужных локалей:
pacman -S localepurge
Закомментировать в /etc/locale.nopurge NEEDSCONFIGFIRST, затем:
localepurge
Установить пакет sunxi-tools
.
Включение и выключение светодиода «Status» (от рута):
sunxi-pio -m PA15=1 sunxi-pio -m PA15=0