Привет!
У нас часто спрашивают есть ли в Embox поддержка Raspberry Pi. Да, есть. Описание как запустить теперь тут. В этой статье я хочу чуть подробней об этом рассказать.
У нас давно была куплена плата Raspberry Pi Model B rev 2.0 (это которая первая Rpi 1) и даже были сделаны первые шаги в портировании: UART, контроллер прерываний, таймер и даже framebuffer в каком-то виде были реализованы. Но данные о том как это запустить, были утеряны, поэтому пришлось вспоминать/разбираться заново.
Во-первых, запустили на эмуляторе QEMU. В обычном QEMU есть поддержка машины raspi2, но нет raspi. Но когда был процесс портации, добавлялась как раз поддержка raspi. У нас сохранилась версия в нашем репозитории, правда пришлось набросать коммитов, чтобы она компилировалась под современное окружение, но в итоге у нас появилась версия эмулятора QEMU в которой имеется поддержка rpi1 — машина "-M raspi" ( посмотреть как запускать можно у нас на wiki). В итоге Embox запустили там и нарисовали градиент в видеопамять.
Встал вопрос о запуске на железе. Как загружаться было сначала непонятно, поэтому решили попробовать стандартный Raspbian. С официального сайта скачивается 2020-02-13-raspbian-buster-lite.img. Вся загрузка происходит с microSD-карты, поэтому подготавливаем ее — копируем полученный образ
dd bs=4M if=2020-02-13-raspbian-buster-lite.img of=/dev/sdb conv=fsync
, где “/dev/sdb” — это SD-карта.
Если теперь посмотреть в lsblk, то будет что-то такое:
sdb 8:16 1 14,6G 0 disk
├─sdb1 8:17 1 256M 0 part
└─sdb2 8:18 1 14,3G 0 part
Давайте примонтируем sdb1 и посмотрим, что там лежит:
$ sudo mount /dev/sdb1 /mnt
$ ls /mnt/
bcm2708-rpi-b.dtb bcm2710-rpi-3-b.dtb COPYING.linux fixup_db.dat start_db.elf
bcm2708-rpi-b-plus.dtb bcm2710-rpi-3-b-plus.dtb fixup4cd.dat fixup_x.dat start.elf
bcm2708-rpi-cm.dtb bcm2710-rpi-cm3.dtb fixup4.dat issue.txt start_x.elf
bcm2708-rpi-zero.dtb bcm2711-rpi-4-b.dtb fixup4db.dat kernel.img
bcm2708-rpi-zero-w.dtb bootcode.bin fixup4x.dat LICENCE.broadcom
bcm2709-rpi-2-b.dtb cmdline.txt fixup_cd.dat overlays
bcm2710-rpi-2-b.dtb config.txt fixup.dat start_cd.elf
Как видно, есть целый набор *.dtb на все случаи жизни — для разных версий Raspberry. Так же видим загрузчик — bootcode.bin, и kernel.img — это Линукс.
Подключили монитор через HDMI к плате, загрузились, увидели Raspbian, все хорошо. Далее нужно скопировать наш бинарник с Embox в kernel.img, чтобы загрузчик его подгрузил. Собираем Embox:
make confload-arm/rpi1-model-b
make
Копируем полученный бинарник:
cp build/base/bin/embox.bin /mnt/kernel.img
Вставляем SD-карту обратно в Rpi и включаем питание — на мониторе квадрат, который должен был быть нарисован Embox-ом, не появился. Ну хорошо, попробуем подключиться по последовательному порту и отладить наш бинарник. Для этого используем RDC1-USB-UART адаптер. Подключаем его к плате следующим образом:
RDC1 Rapi
GND <---> GND
5V <---> 5V
RX <---> TXD0/GPIO14
TX <---> RXD0/GPIO15
Вот здесь можно посмотреть распиновку на картинке, чтобы было прощe. Теперь получается, что питание на USB-адаптер приходит от USB-хаба PC, а питание на Rpi в свою очередь подается уже от USB-адаптера.
Включаем. Подключаемся по minicom:
sudo minicom -d /dev/ttyUSB0
Никакого вывода не видно. Наверняка какая-то проблема в драйвере последовательного порта. Пробуем отключить инициализацию регистров, и использовать то, что было настроено загрузчиком, заливаем на SD-карту новый образ — вывод появился. Все ясно, значит подключили правильно, а вот драйвер последовательного порта неправильно программируем. Я не буду рассказывать о том, как мы чинили драйвер последовательного порта PL011, но отмечу пару моментов, которые могут быть полезны при разработке под эту платформу. Во-первых, базовые адреса на Rpi вычисляются как-то запутано, в документации их бывает сразу и не найти, поэтому неплохой способ проверить базовый адрес регистров — это посмотреть посмотреть их в Линуксе:
pi@raspberrypi:~$ ls /sys/bus/amba/devices/20201000.serial
Видим, что адрес 0x20201000.
Второй момент, это то, что имеется доработанный под Rpi Линукс, который можно собрать и скопировать в kernel.img — www.raspberrypi.org/documentation/linux/kernel/building.md
В случае с последовательным портом, это очень помогло понять частоту входного UARTCLK, необходимого для программирования baud rate — достаточно вставить printk() в нужном месте в drivers/tty/serial/amba-pl011.c.
В результате без каких-то существенных изменений удалось запустить тот же образ что и для QEMU на железе.
Вот, пожалуй, и все, поскольку разбирать исходники драйверов не имеет смысла, ведь можно просто изучить их у нас в репозитории. В целом же сложилось впечатление, что под Raspberry имеется очень мало портов других не-Linux ОС. Например, я не нашел ни FreeRTOS (выяснилось, что какой-то репозиторий есть на GitHub’е, но не в официальных релизах), ни для NuttX, ни чего-то подобного. Да и обсуждения на форумах говорят о том, что RTOS там якобы не нужен и берите лучше Arduino поиграться — www.raspberrypi.org/forums/viewtopic.php?t=201540
Пример на Osdev оказался неработающим, поэтому если кто-то захочет что-то сделать на голом железе, то смотрите лучше примеры у нас :)
Полноценная поддержка новых Rpi 2/3/4 у нас пока в только планах. Но некоторая поддержка, скорее всего, будет производиться в рамках GSoC 2020, одна из самых популярных идей у студентов. Собственно, для GSoC мы поддержку Rpi1 в Embox и восстанавливали. Если у кого-то есть мысли, зачем нужен для Rpi RTOS, пишите в комментариях, будем рады :)
Кроме того, если будете изучать исходники RaPi или просто Embox то мы в радостью ответим на вопросы:
Рассылка: embox-ru@googlegroups.com
Телеграмм чат: t.me/embox_chat
Автор: alexkalmuk