Установка Linux на калькулятор. Часть II

в 9:10, , рубрики: diy или сделай сам, ruvds_статьи, Блог компании RUVDS.com, гик-устройства, калькулятор, Компьютерное железо, портирование linux, Разработка под Linux

Установка Linux на калькулятор. Часть II - 1

Как вы помните, в прошлой статье мне удалось стартануть linux на калькуляторе. Однако, работать на нём было невозможно, и я считаю это незачётом. Тогда я понял, что кроличья нора достаточно глубока и придётся полностью пересобирать всю систему, разбираясь с кодом. В итоге, я кратко прошёлся по всем этапам, которые описывал автор проекта. И результат полностью того стоит. Итак, поехали!

Аппаратные доработки: подключаем UART

Я написал обо всех моих бедах создателю этого linux, заодно попросив прислать мне бекап его прошивки (хотя его лучше, не заливать). И спросил, как же мне подключить UART к моему калькулятору? На что он мне прислал следующую картинку, и сказал: ищи это на другой стороне платы.

Установка Linux на калькулятор. Часть II - 2

В результате, мне предстоял сложный квест — отклеить плату от дисплея, не расколов дисплей и не сломав плату. Пихая туда все возможные металлические предметы, очень аккуратно, в течении часа мне удалось её отделить. Самое сложное было не оборвать тончайшие шлейфы.

Установка Linux на калькулятор. Часть II - 3

Отделяем плату.

Наконец-то, нашему вниманию представляется просто невероятный зоопарк тестовых падов, выводы JTAG и, по моему, SPI, интерфейс SD. Но, самое главное, наш отладочный UART.

Установка Linux на калькулятор. Часть II - 4

Скорее всего там использована логика 1,8 В, но у меня не было такого адаптера, и я решил рискнуть и использовать адаптер с логикой 3,3 В (вам же настоятельно рекомендую использовать 1,8). Попытка, заставить мой адаптер работать на напряжении 1,8 вольта, не увенчалась успехом. Таким образом, я вывел сигналы на гребёнку, в т.ч. опорные 1,8 вольта (но они не пригодились).

Установка Linux на калькулятор. Часть II - 5

Можно приклеивать плату обратно и продолжать работать.

Давайте сразу посмотрим, почему же у нас не запускается система, при загрузке в ОЗУ? Хотя вроде всё работает. Во-первых, давайте глянем скрипт запуска. Содержимое файла run_linux_in_ram.uu:

uuu_version 1.2.135

# This script allows you to run the Linux OS in the RAM without altering the NAND Flash

SDP: boot -f boot/u-boot-dtb.imx -nojump
SDP: write -f firmware/zImage -addr 0x80800000
SDP: write -f firmware/imx6ull-14x14-prime.dtb -addr 0x83000000
SDP: write -f firmware/rootfs.cpio.uboot -addr 0x86800000
SDP: jump -f boot/u-boot-dtb.imx -ivt
SDP: done

Загружаем в память загрузчик u-boot, ядро, dts (точнее, скомпилированный бинарник dtb), initramfs и передаём управление загрузчику, после чего с успехом завершаем приложение uuu.
По логам всё идёт отлично, до момента окончательной загрузки ядра, а там начинается вот такая петрушка.

clk: Not disabling unused clocks
ALSA device list:
  No soundcards found.
Freeing unused kernel memory: 1024K
can't open /dev/null: No such file or directory
...
can't open /dev/null: No such file or directory
Starting syslogd: OK
Starting klogd: OK
Starting network: OK
Starting Xorg: OK
can't open /dev/ttymxc0: No such file or directory
....
can't open /dev/ttymxc0: No such file or directory
imx-sdma 20ec000.sdma: external firmware not found, using ROM firmware
input: Goodix Capacitive TouchScreen as /devices/soc0/soc/2100000.aips-bus/21a4000.i2c/i2c-1/1-0014/input/input3

И так до посинения. Всё банально, /dev/ не создана. И проблема эта открылась позже, при конфигурировании rootfs. Шикарно, мы теперь имеем отличный инструмент отладки. Начнём всё собирать!

Сборка софта

Если вы дойдёте самостоятельно до этого этапа, то надеюсь у вас есть какой-никакой опыт сборки ядра, rootfs, конфигурирования через make menuconfig. Так как описывать весь необходимый список установочных пакетов мне уже лениво (надо установить как минимум кросскомпилятор arm-linux-gnueabihf-, ncurses и многое другое, у меня просто уже всё давно стоит). Будем считать, что вы всё умеете, я лишь заострю ваше внимание на некоторые моменты. Для начала процитирую, то как рекомендуется делать сборку на официальном сайте проекта, а потом я внесу некоторые комментарии.

4. Сборка из исходника

Этот процесс протестирован под Ubuntu 18.04 LTS. Рекомендуется делать сборку под Linux.

4.1 u-boot

Как правило, пересобирать u-boot вам не нужно, и нижеприведенные инструкции даются в качестве справочного материала.
Чтобы собрать u-boot из исходника:

git clone git://github.com/zephray/uboot.git
cd uboot
git checkout imx_v2018.03_4.14.98_2.0.0_ga
make mx6ull_prime_defconfig
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make

В результате получится бинарный файл u-boot-dtb.imx.

4.2 Ядро

Для включения/отключения конкретных модулей драйверов/ядра потребуется пересобрать все ядро.

4.2.1 Компиляция с помощью Buildroot

buildroot соберет ядро автоматически. Конфигурацию же можно изменить с помощью make linux-menuconfig.

4.2.2 Сборка ядра вручную

git clone git://github.com/zephray/linux.git
cd linux
git checkout imx_4.14.98_2.0.0_ga
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make hp_prime_defconfig
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make

В итоге будут собраны файлы arch/arm/boot/dts/imx6ull-14x14-prime.dts и arch/arm/boot/zImage.

4.3 Корневая файловая система (rootfs)

На данный момент hp-prime-linux использует для построения корневой файловой системы buildroot. Пакетного менеджера пока что нет, и если вам нужно добавить или удалить пакет, то потребуется пересобрать rootfs.

git clone git://git.buildroot.net/buildroot
cd buildroot
git checkout 2019.02.4 
make BR2_EXTERNAL=~/Prinux/buildroot prime_defconfig
make

Для установки модулей ядра в rootfs, перейдите в директорию ядра и выполните следующие команды:

INSTALL_MOD_PATH=~/buildroot/output/target ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make modules_install

После этого повторно сгенерируйте образы с помощью buildroot.

Для начала, я решил проверить, что, как минимум, всё это собирается из исходников, поэтому решил потренироваться на самом простом — сборке u-boot. Это важно, так как бывает такой момент, что автор написал инструкцию по сборке и прошивке, а забыл закоммитить последние изменения, и в результате его инструкция оказывается бесполезным мусором.

U-boot собирается совершенно 1 в 1 по инструкции, без каких либо тонкостей. В корневой папке после компиляции, мы получим кучу файлов, но нас интересует файл u-boot-dtb.imx.

Скопируем его в нашу флеш-утилиту (предварительно создав там папку my):

cp u-boot-dtb.imx /home/dlinyj/tmp/calc/flash_utility/my

И создадим там новый загрузочный скрипт, на котором всё и будем обкатывать:

uuu_version 1.2.135

SDP: boot -f my/u-boot-dtb.imx -nojump
SDP: jump -f my/u-boot-dtb.imx -ivt
SDP: done

Проверяем на калькуляторе (всё как обычно, запускаем скрипт, потом вставляем USB. И в результате должны получить такой результат.

Установка Linux на калькулятор. Часть II - 6

Это полный успех, значит код рабочий и мы можем продолжать. Если вы дойдёте до сборки, то настоятельно рекомендую поглядеть git log и git diff между коммитами, чтобы оценить масштабы проделанной работы. Это восхищает и мотивирует!

Со сборкой ядра у меня тоже практически не возникло никаких проблем, разве что пришлось поставить дополнительный пакет lzop, чтобы ядро корректно сжалось. Протестировать можно точно так же (не забыв добавить загрузку dtb-файла, иначе ядро не стартанёт).

Самым сложным оказалась сборка rootfs, как оказалось, дефолтный конфиг мне не подойдёт для сборки. Для начала. делаем всё точно, как написано в инструкции:

git clone git://git.buildroot.net/buildroot
cd buildroot
git checkout 2019.02.4 

А вот теперь начинается самое интересное, хождение по битым ссылкам :). В релизах, кроме flash_utility.tar.gz есть ещё файл Source code, который, совершенно неочевидным образом содержит в себе необходимые конфиги для сборки rootfs! Скачиваем файл prinux-0.1.zip и распаковываем его в удобное для нас место. Либо клонируем репозиторий. У меня это вышел путь /home/dlinyj/tmp/calc/prinux.

Там внутри есть папка buildroot — это и есть внешние конфигурационные файлы для сборки buildroot! И вот этот путь, именно до этой папки указываем в следующей команде:

make BR2_EXTERNAL= /home/dlinyj/tmp/calc/prinux prime_defconfig

Допереть до этого самостоятельно было невозможно, покуда я не прошерстил вообще все репозитории, файлы и не прочитал как же собирается buildroot (к своему стыду, впервые собираю его вот так, с нуля).

Этой конфигурации мало, в целом можно конечно собрать, и даже попробовать запустить, но initramfs он будет слишком здоровым (там стоят Иксы), больше 25 МБ, и он не запустится. А для прошивки на nand мы будем получать ту же самую проблему, как и в тесте загрузки в память: не будут созданы файл-устройства.

Первое, я отредактировал файл /home/dlinyj/tmp/calc/prinux/buildroot/configs/prime_defconfig и привёл его к виду:

BR2_arm=y
BR2_cortex_a7=y
BR2_ARM_FPU_NEON_VFPV4=y
BR2_OPTIMIZE_3=y
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TARGET_GENERIC_HOSTNAME="prinux"
BR2_TARGET_GENERIC_ISSUE="Welcome to Prinux"
BR2_INIT_SYSTEMD=y
BR2_TARGET_GENERIC_GETTY_PORT="ttymxc0"
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_PRINUX_PATH)/board/prime/overlay/"
BR2_ROOTFS_POST_IMAGE_SCRIPT="$(BR2_EXTERNAL_PRINUX_PATH)/board/prime/post_build.sh"
BR2_TARGET_ROOTFS_TAR_BZIP2=y
BR2_PACKAGE_HOST_UBOOT_TOOLS=y

Выкинув совершенно лишние на данный момент пакеты иксов (мне бы стартануть систему, а потом всё остальное).

Далее выполняю:

make BR2_EXTERNAL= /home/dlinyj/tmp/calc/prinux prime_defconfig
make menuconfig

В опции Filesystem images включаю:

[*] cpio the root filesystem (for use as an initial RAM filesystem)
[*]   Create U-Boot image of the root filesystem 

Прохожусь по всем пакетам и отрубаю вообще всё, чтобы не было лишнего.

В разделе System configuration ставлю:

Init system (BusyBox)  
/dev management (Static using device table)

Тем самым ещё более уменьшая образ, и наконец у нас будет корректно работать менеджер устройств!
Выходим и сохраняем. И собираем:

make

После успешной компиляции, топаем обратно в папку с собранным ядром и нам необходимо теперь установить модули ядра в нашу rootfs, для этого выполняем:

INSTALL_MOD_PATH=/home/dlinyj/tmp/calc/buildroot/output/target ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make modules_install

И возвращаемся в buildroot и вновь выполняем make. В результате мы получим собранные пакеты в папке /home/dlinyj/tmp/calc/buildroot/output/images:

  • rootfs.cpio.uboot — это готовый initramfs
  • rootfs.tar.bz2 — образ готовый для прошивки на nand.

Стартуем!

Переписываю готовые образы rootfs в папку my и не забываем переписать туда же свежесобранное ядро из папки /home/dlinyj/tmp/calc/linux/arch/arm/boot, файл zImage. Далее беру за основу скрипт прошивки на nand-флеш и привожу его к виду:

Скрипт для прошивки на nand-flash

uuu_version 1.2.135

# This script allows you to flash the Linux OS into NAND Flash.

# Boot into flash environment
SDP: boot -f boot/u-boot-dtb.imx -nojump
SDP: write -f boot/zImage -addr 0x80800000
SDP: write -f boot/imx6ull-14x14-prime.dtb -addr 0x83000000
SDP: write -f boot/fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.gz.u-boot -addr 0x86800000
SDP: jump -f boot/u-boot-dtb.imx -ivt

# Flash kernel
FBK: ucmd flash_erase /dev/mtd1 0 0
FBK: ucp my/zImage t:/tmp
FBK: ucmd nandwrite -p /dev/mtd1 /tmp/zImage

# Flash device tree blob
FBK: ucmd flash_erase /dev/mtd2 0 0
FBK: ucp firmware/imx6ull-14x14-prime.dtb t:/tmp
FBK: ucmd nandwrite -p /dev/mtd2 /tmp/imx6ull-14x14-prime.dtb

# Flash rootfs
FBK: ucmd flash_erase /dev/mtd4 0 0
FBK: ucmd ubiformat /dev/mtd4
FBK: ucmd ubiattach /dev/ubi_ctrl -m 4
FBK: ucmd ubimkvol /dev/ubi0 -Nrootfs -m
FBK: ucmd mkdir -p /mnt/mtd
FBK: ucmd mount -t ubifs ubi0:rootfs /mnt/mtd
FBK: acmd export EXTRACT_UNSAFE_SYMLINKS=1; tar -jx -C /mnt/mtd
FBK: ucp my/rootfs.tar.bz2 t:-
FBK: sync
FBK: ucmd umount /mnt/mtd

# Done
FBK: done

Обращаю внимание, что у нас используется специальный образ rootfs для прошивки nand-флеш. Я выкинул прошивку u-boot (так и не понял в чём проблема, и пока не смог победить). device tree blob загружается из другой папки, но никто не мешает его собранный так же переписать либо из u-boot, либо из папки с ядром.

Запускаем этот скрипт, и у нас успешно прошивается nand-флеш. Поскольку загрузчик у нас не прошит, при подаче питания linux не стартанёт. Поэтому вновь правим (или пишем новый скрипт) для загрузки u-boot:

uuu_version 1.2.135

SDP: boot -f my/u-boot-dtb.imx -nojump
SDP: jump -f my/u-boot-dtb.imx -ivt
SDP: done

Запускаем этот скрипт, и шалость удалась!

К сожалению, мне удалось успешно загрузиться на nand только один раз, потом я решил поправить один файл и у меня уже сыпалось всё с паникой ядра. Чуть ниже расскажу о проблемах.

А как на счёт логина с клавиатуры калькулятора и работы экрана?

А, вы хотите нормальной работы калькулятора, прям как настоящего компьютера? Независимо от большого ПК, не работая через консоль? Да?

Да ладно. Их есть у меня, пожалуйста. Для этого, согласно той же инструкции надо поправить один файл. Цитирую:

5.3.1 Активация консоли VT

В данном релизе она активна по умолчанию.

vi ~/buildroot/output/target/etc/inittab

Введите следующее:

tty0::respawn:/sbin/getty -L tty0 0 vt100 # VT

Хочу обратить внимание, что в оригинальной статье ошибка (забыт нолик), в этой цитате я исправил данную команду. Вписываем эту строку, и перекомпилируем снова rootfs.

Далее пишем загрузочный скрипт, для загрузки нашей сборки initramfs:

uuu_version 1.2.135

# This script allows you to run the Linux OS in the RAM without altering the NAND Flash

SDP: boot -f my/u-boot-dtb.imx -nojump
SDP: write -f my/zImage -addr 0x80800000
SDP: write -f firmware/imx6ull-14x14-prime.dtb -addr 0x83000000
SDP: write -f my/rootfs.cpio.uboot -addr 0x86800000
SDP: jump -f my/u-boot-dtb.imx -ivt
SDP: done

Запускаем его, и вот вам демонстрация работы экрана и клавиатуры, ну чем не компьютер.

После чего я немного разошёлся, и накидал ещё в /root несколько графических файлов, и вывел их с помощью программы fbi (вы их видели в заходниках статей).

Итого

Установка Linux на калькулятор. Часть II - 7

Фух, была проделана громадная работа, растянувшаяся на две недели, но оно того по настоящему стоило!

Если, вы вдруг имеете подобный калькулятор, то вполне можете повторить запуск линукс (как минимум в ОЗУ), с помощью обновленной утилиты, которую можете скачать вот тут.
flash_utility.tar.gz.

К сожалению, с nand-флеш мне не удалось подружиться. После редактирования файлика, и дальнейшей перезагрузки, я получил вот такое сообщение.

Установка Linux на калькулятор. Часть II - 8

Я так и не понял почему так получается, как я не бился, второй раз загрузиться на nand-флеш мне не удалось. Скорее всего, это связанно с тем, что я затёр вспомогательные области nand-флеша, и где-то rootfs и u-boot попадает на эти битые сектора, которые я варварским образом перемаркировал в нормальные. Уже буквально в ночи, перед выходом данной статьи решил собрать initramfs с утилитами mtd и nand и посмотреть, что же происходит. А происходит весьма любопытная петрушка. При загрузке ядро у меня выдаёт.

gpmi-nand 1806000.gpmi-nand: mode:4 ,failed in set feature.
Bad block table found at page 262080, version 0x01
Bad block table found at page 262016, version 0x01
nand_read_bbt: bad block at 0x000000000000
nand_read_bbt: bad block at 0x000000020000
nand_read_bbt: bad block at 0x000000040000
nand_read_bbt: bad block at 0x000000060000
nand_read_bbt: bad block at 0x0000012c0000
nand_read_bbt: bad block at 0x000004e20000
nand_read_bbt: bad block at 0x000005280000
nand_read_bbt: bad block at 0x0000094c0000
nand_read_bbt: bad block at 0x000017b20000
5 cmdlinepart partitions found on MTD device gpmi-nand
Creating 5 MTD partitions on "gpmi-nand":
0x000000000000-0x000000400000 : "boot"
0x000000400000-0x000000c00000 : "kernel"
0x000000c00000-0x000000d00000 : "dtb"
0x000000d00000-0x000000e00000 : "misc"
0x000000e00000-0x000020000000 : "rootfs"
gpmi-nand 1806000.gpmi-nand: driver registered.

Но при этом в системе пятый раздел, на котором собственно и находится rootfs после загрузки отсутствует. Ошибок в логе загрузки нет:

# mtdinfo 
Count of MTD devices:           5
libmtd: error!: cannot open "/dev/mtd4"
        error 2 (No such file or directory)
Present MTD devices:            mtd0, mtd1, mtd2, mtd3, mtd4
Sysfs interface supported:      yes
# ls -la /dev/mtd*
crw-r-----    1 root     root       90,   0 Feb 16  2021 /dev/mtd0
crw-r-----    1 root     root       90,   2 Feb 16  2021 /dev/mtd1
crw-r-----    1 root     root       90,   4 Feb 16  2021 /dev/mtd2
crw-r-----    1 root     root       90,   6 Feb 16  2021 /dev/mtd3
brw-r-----    1 root     root       31,   0 Feb 16  2021 /dev/mtdblock0
brw-r-----    1 root     root       31,   1 Feb 16  2021 /dev/mtdblock1
brw-r-----    1 root     root       31,   2 Feb 16  2021 /dev/mtdblock2
brw-r-----    1 root     root       31,   3 Feb 16  2021 /dev/mtdblock3

Странная, пока непонятная мистика, куда подевался раздел.
Точно так же, мне не удалось прошить u-boot на nand. При прошивке командой:

kobs-ng init -x -v --chip_0_device_path=/dev/mtd0 /tmp/u-boot-dtb.imx

Происходит следующая ошибка:

WOpen:/tmp
WOpen:/tmp/u-boot-dtb.imx
run shell cmd: kobs-ng init -x -v --chip_0_device_path=/dev/mtd0 /tmp/u-boot-dtb.imx
unable to create a temporary file

Это всё, что удалось поймать по UART. Я уже и в исходниках kobs-ng поковырялся, но всё бестолку. Пока непонятно как разрешить этот вопрос.

Вопросы к сообществу

  • Кто-нибудь сталкивался с проблемой перепрошивки с помощью утилиты kobs-ng?

Благодарности

  • Выражаю огромную благодарность создателю данного проекта ZephRay, без него бы этой статьи бы не было. Это невероятный и очень крутой труд.
  • Выражаю благодарность Bright_Translate за помощь с переводом инструкции по установке.
  • Главная благодарность моей жене, которая помогала мне в составлении и оформлении данной статьи. А так же терпела мои ночные бдения за этим устройством.

Ссылки

  1. Основной проект.
  2. Файлы для сборки rootfs и скрипты прошивальщика.
  3. Обновлённая мной рабочая прошивка для калькулятора.

Автор: Сергей

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js