image Привет!

У нас часто спрашивают есть ли в 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 
L-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