Программирование на Python и установка Docker для Sipeed Lichee RV RISC-V

Lichee RV

В первой части познакомились с процессором Allwinner D1 на RISC-V архитектуре, рассмотрели возможности, поработали с одноплатным компьютером Sipeed Lichee RV. Старый образ операционной системы содержал многие недоработки, которые не позволяли полностью оценить работу одноплатника. В продолжение рассмотрения Lichee RV, возьмем новый образ Ubuntu, построенный на последнем ядре Linux 5.19, окончательный выпуск которого ожидается в конце июля 2022 года. Поработаем с GPIO из Python`а и установим Docker. Теперь полноценно протестируем новый образ, проверим на что способна плата и начнем уже программировать на Python.
Особенностью разработчиков китайских одноплатников является крайне слабая поддержка программного обеспечения, включая разработку образов операционных систем. Компания Sipeed с начала этого года, после продаж модуля Lichee RV, не опубликовала ни одного обновления программного обеспечения.

Многие китайский одноплатники превратились бы в музейный экспонат, если не проект Armbian. Armbian — это самый популярный дистрибутив Linux, предназначенный для одноплатных компьютеров построенных на ARM процессоре, список поддерживаемых плат огромен: Orange Pi, Banana Pi, Odroid, Olimex, Cubietruck, Roseapple Pi, Pine64, NanoPi и др. Сравнительно давно появилась поддержка Raspberry Pi.

Lichee RV

Один из ведущих мейнтейнеров проекта Armbian, Олег сделал порт для процессора Allwinner D1. В ветке обсуждения можно отслеживать последние изменения. На данный момент порт работает на платах Nezha D1 и Lichee RV (Dock).

  • Для платы Nezha D1 поддерживается: HDMI, LAN, USB, аналоговый вывод через 3.5 jack;
  • Для платы Lichee RV Dock поддерживается: HDMI, WiFi, USB, USB-LAN.


Образы можно скачать по ссылке.

Все дальнейшие работы выполнялись на образе Armbian_22.08.0-trunk_Nezha_jammy_current_5.19.0.img.xz от 2022.06.27. Для запуска потребуется micro-SD карта и программа balenaEtcher, с помощью которой образ записывается на карту-памяти.


Первый запуск Armbian сопровождается инициализацией системных настроек, в рамках которых необходимо ответить на несколько вопросов связанных с конфигурацией системы. Если нет возможности подключить HDMI-панель, то можно подключить USB-TTL UART конвертер и в терминальном режиме выполнить начальную инициализацию и настройку (предыдущий пост, раздел — Подключение по UART).

После успешного запуска выполним команды uname -a и lsb_release -a.

Результат выполнения:

root@nezha:~# uname -a
Linux nezha 5.19.0-rc1-d1 #trunk Mon Jun 27 13:50:54 MSK 2022 riscv64 riscv64 riscv64 GNU/Linux
root@nezha:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04 LTS
Release:        22.04
Codename:       jammy
root@nezha:~#


Образ построен на Ubuntu 22.04 LTS (jammy), ядро Linux 5.19.0-rc1-d1.

Приветствие пользователя в терминале
Lichee RV
Приветствие пользователя в терминале


Отобразим картинку neofetch:

Lichee RV
Запуск программы neofetch на Lichee RV

Запустим менеджер задач, утилита htop. Температура во время работы составляет 48.5°C в холостом режиме.

Lichee RV
Запуск утилиты htop на Lichee RV

Загрузка памяти RAM составляет всего 117 Мб из 512.


Все ключевые устройства такие как HDMI, WiFi, USB, поддерживаются. Единственное, на данный момент нет поддержки небольшого дополнительного дисплея 1.14″ SPI на контроллере Sitronix ST7789V.

Вывод списка устройств утилитой inxi
Результат выполнения:
root@nezha:~# inxi -Fc0
System:
  Host: nezha Kernel: 5.19.0-rc1-d1 riscv64 bits: 64 Console: pty pts/0
    Distro: Ubuntu 22.04 LTS (Jammy Jellyfish)
Machine:
  Type: RISCV System: Allwinner D1 Nezha details: N/A
CPU:
  Info: single core model: N/A variant: c906 bits: 64 type: UP
  Speed (MHz): 1008 max: 1008 core: 1: 1008
Graphics:
  Device-1: sun20i-d1-dw-hdmi driver: sun8i_dw_hdmi v: N/A
  Device-2: sun20i-d1-display-engine driver: sun4i_drm v: N/A
  Display: server: No display server data found. Headless machine? tty: 117x40
  Message: Unable to show GL data. Required tool glxinfo missing.
Audio:
  Device-1: sun20i-d1-dw-hdmi driver: sun8i_dw_hdmi
  Sound Server-1: ALSA v: k5.19.0-rc1-d1 running: yes
Network:
  Device-1: sun20i-d1-emac driver: N/A
  Device-2: mmc-pwrseq-simple driver: pwrseq_simple
  IF-ID-1: docker0 state: down mac: 02:42:21:0c:9a:20
  IF-ID-2: usb0 state: down mac: 6a:74:8e:f9:16:6c
  IF-ID-3: wlan0 state: up mac: 74:ee:2a:6b:43:59
Drives:
  Local Storage: total: 14.88 GiB used: 4.65 GiB (31.2%)
  ID-1: /dev/mmcblk0 model: ASTC size: 14.88 GiB
Partition:
  ID-1: / size: 13.93 GiB used: 4.58 GiB (32.9%) fs: ext4 dev: /dev/mmcblk0p2
  ID-2: /boot size: 511 MiB used: 50.3 MiB (9.8%) fs: vfat dev: /dev/mmcblk0p1
  ID-3: /var/log size: 46.8 MiB used: 13.7 MiB (29.3%) fs: ext4 dev: /dev/zram1
Swap:
  ID-1: swap-1 type: zram size: 238.6 MiB used: 22.2 MiB (9.3%) dev: /dev/zram0
Sensors:
  Missing: Required tool sensors not installed. Check --recommends
Info:
  Processes: 110 Uptime: 5h 40m Memory: 477.2 MiB used: 152 MiB (31.9%) Init: systemd runlevel: 5
  Shell: Bash inxi: 3.3.13


Для загрузки устройств используется конфигурация дерева устройств sun20i-d1-nezha.dto. Что такое дерево устройств можно узнать подробнее в статье Работа с GPIO. Часть 2. Device Tree overlays.

Файл sun20i-d1-nezha.dto располагается по пути /boot/dtb/allwinner, для конвертации в читаймый текстовый вид (DTS) из бинарного, необходимо выполнить команду:

$ dtc -I dtb -O dts sun20i-d1-nezha.dtb -o sun20i-d1-nezha.dts


На самой плате Dock размещен RGB-светодиод и пользовательская кнопка обозначенная как KEY.

RGB-светодиод


RGB-светодиод на микросхеме WS2812 подключен к контакту PC0, управляется с помощью виртуальной файловой системы Sysfs.

Lichee RV
Схема подключения RGB-светодиод к контакту PC0

По пути /sys/class/leds располагается устройство rgb: indicator.

Результат выполнение команды tree
root@nezha:/sys/class/leds/rgb:indicator# tree
.
├── brightness
├── device -> ../../../2008000.led-controller
├── max_brightness
├── multi_index
├── multi_intensity
├── power
│   ├── async
│   ├── autosuspend_delay_ms
│   ├── control
│   ├── runtime_active_kids
│   ├── runtime_active_time
│   ├── runtime_enabled
│   ├── runtime_status
│   ├── runtime_suspended_time
│   └── runtime_usage
├── subsystem -> ../../../../../../class/leds
├── trigger
└── uevent

3 directories, 15 files


Для управления цветом необходимо узнать индексы цветов. Прочитаем содержимое файла multi_index.

root@nezha:~# cat /sys/class/leds/rgb:indicator/multi_index
red green blue


Управление светодиодом осуществляется с помощью файла multi_intensity. Например, зададим синий цвет в максимальной яркости:

$ echo 0 0 255 > /sys/class/leds/rgb:indicator/multi_intensity


А теперь включим бирюзовый цвет:

$ echo 48 213 200 > /sys/class/leds/rgb:indicator/multi_intensity


Lichee RV
Включение RGB-светодиода на Sipeed Lichee RV Dock

Пользовательская кнопка (KEY)


Кнопка KEY подключена к контакту ADC_LRADC. Это низкоскоростной АЦП (LRADC) имеет 6-битное разрешение для ключевого приложения. LRADC может работать с максимальной частотой преобразования 2 кГц. Регистрирует напряжение в диапазоне от 0 до 3.3 В.

Lichee RV
Схема подключения кнопки KEY к контакту ADC_LRADC

Ниже фрагмент данного устройства из sun20i-d1-nezha.dto

keys@2009800 {
  compatible = "allwinner,sun20i-d1-lradc allwinner,sun50i-r329-lradc";
  reg = <0x2009800 0x400>;
  clocks = <0x02 0x68>;
  resets = <0x02 0x2f>;
  interrupts = <0x4d 0x04>;
  status = "okay";
  vref-supply = <0x1a>;
  wakeup-source;

  button-160 {
    label = "OK";
    linux,code = <0x160>;
    channel = <0x00>;
    voltage = <0x27100>;
    };
};


Параметр linux, code определяет код кнопки, полный список кодов доступен в файле input-event-codes.h. Параметр voltage определяет напряжение срабатывания в 2.71 В.

Модуль Wi-Fi


На несущей плате Lichee RV Dock размещен модуль Realtek RTL8723DS беспроводной связи Wi-Fi 4 (802.11b/g/n) и Bluetooth 4.2. Образ включает в себя драйвера для чипов Realtek: RTL8723DS, RTL8712, R8188EU. Включена поддержка модулей связи USB-Dongle Wi-Fi и Ethernet (проверено rt8152). В предыдущем образе была проблема с обнаружением и работой Wi-Fi модуля. В частности, подключение к точкам доступа работало только в графическом режиме. В новом образе модуль связи работает штатно.

Результат выполнения команды iwlist wlan0 scan для сканирование эфира:

root@nezha:~# iwlist wlan0 scan
wlan0     Scan completed :
          Cell 01 - Address: **:**:**:**:**:99
                    ESSID:"asus"
                    Protocol:IEEE 802.11bgn
                    Mode:Master
                    Frequency:2.437 GHz (Channel 6)
                    Encryption key:on
                    Bit Rates:72 Mb/s
                    Extra:rsn_ie=30140100000fac040100000fac040100000fac020c00
                    IE: IEEE 802.11i/WPA2 Version 1
                        Group Cipher : CCMP
                        Pairwise Ciphers (1) : CCMP
                        Authentication Suites (1) : PSK
                    Quality=100/100  Signal level=68/100
                    Extra:fm=0003
          Cell 02 - Address: **:**:**:**:**:94
                    ESSID:"Home"
                    Protocol:IEEE 802.11bgn
                    Mode:Master
                    Frequency:2.412 GHz (Channel 1)
                    Encryption key:on
                    Bit Rates:300 Mb/s
                    Extra:rsn_ie=30140100000fac040100000fac040100000fac020000
                    IE: IEEE 802.11i/WPA2 Version 1
                        Group Cipher : CCMP
                        Pairwise Ciphers (1) : CCMP
                        Authentication Suites (1) : PSK                   
                    Quality=0/100  Signal level=29/100
                    Extra:fm=0003
****


Для подключения к Wi-Fi сети из консоли, не используя графическую оболочку, используется удобная утилита nmtui (пакет network-manager), без необходимости ручной правки конфигурационных файлов. Утилита nmtui успешно сканирует доступные Wi-Fi сети и подключается к любой сети. После перезагрузки Lichee RV, восстанавливается сетевое соединение с Wi-Fi точкой доступа.

При вызове команды iwconfig сообщается корректная информация:

root@nezha:~# iwconfig
lo        no wireless extensions.

usb0      no wireless extensions.

wlan0     IEEE 802.11bgn  ESSID:"asus"  Nickname:""
          Mode:Managed  Frequency:2.437 GHz  Access Point: **:**:**:**:**:99
          Bit Rate:72.2 Mb/s   Sensitivity:0/0
          Retry:off   RTS thr:off   Fragment thr:off
          Encryption key:****-****-****-****-****-****-****-****   Security mode:open
          Power Management:off
          Link Quality=97/100  Signal level=68/100  Noise level=0/100
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0


Звуковые устройства


Звуковой сервер ALSA работает без ошибок, но воспроизведение звука и запись на микрофон не выполнялось.
На несущей Dock плате выведен разъем GPIO на 40-pins с шагом 2,54 мм частично совместимый с аналогичным разъемом Raspberry Pi, так же присутствую линии питания на 3.3V и 5V, но некоторые выводы GND не соответствуют выводам на Raspberry Pi. Схему контактов можете рассмотреть в предыдущем посте.

Выведены интерфейсы: 1x TWI, 1x SPI, 6x PWM, 4x UART, MIPI DSI, RGB, LVDS.

Для управления контактами GPIO используется библиотека Libgpiod. В репозитории размещен пакет последней версии (версия 1.6), поэтому установим данную библиотеку командой:

$ sudo apt-get update
$ sudo apt-get install -y libgpiod-dev gpiod


После этого выполним команду gpiodetect для вывода списка существующих чипов GPIO, метки и количество линий. Результат выполнения:

root@nezha:~# gpiodetect
gpiochip0 [2000000.pinctrl] (224 lines)


Устройство gpiochip0 соответствует контактам разъема GPIO на 40-pins.

Команда gpioinfo выведет информацию о линиях GPIO конкретного контроллера GPIO (или всех контроллеров GPIO, если они не указаны).

Результат выполнения команды gpioinfo
root@nezha:~# gpioinfo
gpiochip0 - 224 lines:
        line   0:      unnamed       unused   input  active-high
...
        line  31:      unnamed       unused   input  active-high
        line  32:      unnamed       kernel   input  active-high [used]
        line  33:      unnamed       kernel   input  active-high [used]
        line  34:      unnamed       unused   input  active-high
...   
        line  39:      unnamed       unused   input  active-high
        line  40:      unnamed       kernel   input  active-high [used]
        line  41:      unnamed       kernel   input  active-high [used]
        line  42:      unnamed       kernel   input  active-high [used]
        line  43:      unnamed       kernel   input  active-high [used]
        line  44:      unnamed       unused   input  active-high
...   
        line  63:      unnamed       unused   input  active-high
        line  64:      unnamed       kernel   input  active-high [used]
        line  65:      unnamed       unused   input  active-high
        line  66:      unnamed       kernel   input  active-high [used]
        line  67:      unnamed       kernel   input  active-high [used]
        line  68:      unnamed       kernel   input  active-high [used]
        line  69:      unnamed       kernel   input  active-high [used]
        line  70:      unnamed       kernel   input  active-high [used]
        line  71:      unnamed       kernel   input  active-high [used]
        line  72:      unnamed       unused   input  active-high
...   
        line 105:      unnamed       unused   input  active-high
        line 106:      unnamed       kernel   input  active-high [used]
        line 107:      unnamed       kernel   input  active-high [used]
        line 108:      unnamed       kernel   input  active-high [used]
        line 109:      unnamed       kernel   input  active-high [used]
        line 110:      unnamed       kernel   input  active-high [used]
        line 111:      unnamed       kernel   input  active-high [used]
        line 112:      unnamed       kernel   input  active-high [used]
        line 113:      unnamed       unused   input  active-high
        line 114:      unnamed       kernel   input  active-high [used]
        line 115:      unnamed    "usbvbus"  output  active-high [used]
        line 116:      unnamed "usb0_vbus_det" input active-high [used]
        line 117:      unnamed "usb0_id_det" input active-low [used]
        line 118:      unnamed       kernel   input  active-high [used]
        line 119:      unnamed       unused   input  active-high
...   
        line 159:      unnamed       unused   input  active-high
        line 160:      unnamed       kernel   input  active-high [used]
        line 161:      unnamed       kernel   input  active-high [used]
        line 162:      unnamed       kernel   input  active-high [used]
        line 163:      unnamed       kernel   input  active-high [used]
        line 164:      unnamed       kernel   input  active-high [used]
        line 165:      unnamed       kernel   input  active-high [used]
        line 166:      unnamed         "cd"   input  active-high [used]
        line 167:      unnamed       unused   input  active-high
...   
        line 191:      unnamed       unused   input  active-high
        line 192:      unnamed       kernel   input  active-high [used]
        line 193:      unnamed       kernel   input  active-high [used]
        line 194:      unnamed       kernel   input  active-high [used]
        line 195:      unnamed       kernel   input  active-high [used]
        line 196:      unnamed       kernel   input  active-high [used]
        line 197:      unnamed       kernel   input  active-high [used]
        line 198:      unnamed       kernel   input  active-high [used]
        line 199:      unnamed       kernel   input  active-high [used]
        line 200:      unnamed       kernel   input  active-high [used]
        line 201:      unnamed       kernel   input  active-high [used]
        line 202:      unnamed       unused   input  active-high
        line 203:      unnamed       unused   input  active-high
        line 204:      unnamed      "reset"  output   active-low [used]
        line 205:      unnamed       unused   input  active-high
...   
        line 223:      unnamed       unused   input  active-high


Некоторые контакты из разъема задействованы в конфигурации по интерфейсам I2C, SPI, и т.д. Поэтому до использования контакта для подключения светодиода, кнопки или другой периферии необходимо проверять занятость.

В дереве устройств, устройство контакты GPIO называется pinctrl@2000000. В конфигурации перечислены все контакты и их названия, если вызвать команду cat /sys/kernel/debug/pinctrl/2000000.pinctrl/pinmux-pins то можно узнать соответствие номера контакта к его метки, и так же занятость.

Результат выполнения:

root@nezha:~# cat /sys/kernel/debug/pinctrl/2000000.pinctrl/pinmux-pins
Pinmux settings per pin
Format: pin (name): mux_owner|gpio_owner (strict) hog?
pin 32 (PB0): device 2502800.i2c function i2c2 group PB0
pin 33 (PB1): device 2502800.i2c function i2c2 group PB1
pin 34 (PB2): UNCLAIMED
...
pin 39 (PB7): UNCLAIMED
pin 40 (PB8): device 2500000.serial function uart0 group PB8
pin 41 (PB9): device 2500000.serial function uart0 group PB9
pin 42 (PB10): device 2502000.i2c function i2c0 group PB10
pin 43 (PB11): device 2502000.i2c function i2c0 group PB11
pin 44 (PB12): UNCLAIMED
pin 64 (PC0): device 2008000.led-controller function ledc group PC0
pin 65 (PC1): UNCLAIMED
...
pin 104 (PD8): UNCLAIMED
...
pin 113 (PD17): UNCLAIMED
...
pin 210 (PG18): UNCLAIMED


Из отчета видим, что контакты:

  • pin 32 (PB0) и pin 33 (PB1) заняты под I2C шину;
  • pin 40 (PB8) и pin 41 (PB9) заняты под интерфейс UART;
  • pin 64 (PC0) занят под RGB-светодиод на микросхеме WS2812;
  • pin 104 (PD8) и pin 113 (PD17) свободны для подключения.


Формула для вычисления номера GPIOXX

Расчет номера контакта (линия, порт) делается по названию самого контакта. Формула расчетов для процессоров Allwinner не меняется. Порядковый номер получаем путем простого расчета. Например, контакт PD8, для получения номера контакта на процессоре произведем расчет по формуле:
(позиция буквы в алфавите — 1) * 32 + позиция вывода. Первая буква не учитывается т.к. P — PORT, позиция буквы D в алфавите = 4, получаем (4–1) * 32 + 8 = 104. Физический номер контакта PD8 является номер 104. У каждого разработчика SoC может быть свой алгоритм расчета номера контактов, должен быть описан в Datasheet к процессору.

Подключение светодиода и кнопки


Как в публикации Управляем контактами GPIO из C# .NET 5 в Linux подключим светодиод и кнопку, но только логику обработку сигналов напишем на Python.

  • К контакту с номером линии 113, метка PD17 подключим светодиод;
  • К контакту с номером линии 104, метка PD8 подключим кнопку.


Обратите внимание, максимальное допустимое напряжение на контактах GPIO составляет 3.3 В.

Команда gpioset установит значение для линии GPIO. Например, следующая команда попытается включить светодиод. Команда: gpioset 0 113=1, где 0 — gpiochip0, 113 — номер линии (контакта), 0 — логическое значение, может быть »0» или »1». Выполнение команды:

root@nezha:~# gpioset 0 113=1
root@nezha:~#


В результате выполнения команды, светодиод включится.

Команда gpiomon осуществляет мониторинг состояния линии GPIO и выводит значение при изменение состояния. Будем мониторить состояние кнопки, которая подключена на линию 104, название «PВ8». Команда: gpiomon 0 104, где 0 — gpiochip0, 104 — номер линии (контакта). Результат выполнения команды:

root@nezha:~# gpiomon 0 104
event:  RISING EDGE offset: 104 timestamp: [   11950.645719439]
event: FALLING EDGE offset: 104 timestamp: [   11951.143717188]
event:  RISING EDGE offset: 104 timestamp: [   11953.794611629]
event: FALLING EDGE offset: 104 timestamp: [   11954.324853635]
event:  RISING EDGE offset: 104 timestamp: [   11956.510412585]
event: FALLING EDGE offset: 104 timestamp: [   11957.104961601]


Кнопка несколько раз нажималась. RISING — повышение, изменение напряжения с 0V до 3.3V, кнопка нажата и удерживается состояние. FALLING — понижение, изменение напряжения с 3.3V до 0V, происходит отпускание кнопки, и кнопка переходит в состояние «не нажата».

Техническую работу светодиода и кнопки проверили, теперь перейдем к программированию.


Написание программы на Python можно сказать даже проще чем на .NET. Помимо среды исполнения потребуется установить обертку-библиотеку над библиотеками Libgpiod.

Установим Python:

sudo apt-get update
sudo apt-get install python3


Затем установим библиотеку gpiod, пакет python3-libgpiod:

sudo apt-get install python3-libgpiod


После установки библиотеки, по пути /usr/share/doc/python3-libgpiod/examples будут расположены примеры на Python работы улитит Libgpiod. Например скрипт gpioset.py, по аналогии с утилитой gpioset позволяет изменять состояние контакта на логический »0» или »1», для выключения и включения светодиода.

Мигание светодиодом


Воспользуемся примерами и напишем небольшой скрипт для мигания светодиодом на контакте PD17.

Файл: blink.py

# GPIO used PD17

import gpiod
import time

chip=gpiod.Chip('gpiochip0')

lines = chip.get_lines([113])
lines.request(consumer='foobar', type=gpiod.LINE_REQ_DIR_OUT, default_vals=[0])

while True:
    lines.set_values([1])
    time.sleep(1)
    lines.set_values([0])
    time.sleep(1)


В строке lines.request (…) указывается потребитель (consumer), наименование приложения использующее данный ресурс. Далее константа LINE_REQ_DIR_OUT указывает на направление линии на вывод, и указывается начальное значение выключено »0».

Запустим программу:

$ python3 blink.py


После запуска программы светодиод мигает с интервалом в 1 секунду:

Обработка событий кнопки


Не все контакты поддерживают обработку аппаратных прерываний. Поэтому до подключения кнопки необходимо обратиться к спецификации на SoC Allwinner D1 файл D1_Datasheet_V0.1(Draft Version).pdf. На 47 странице в колонке Function14 указана функция PD-EINT8, которая означает поддержку прерываний. Кстати, на этом процессоре все доступные контакты GPIO подерживают прерывания, в отличие от Allwinner A64 ARM64.

Воспользуемся уже подключенной кнопкой на контакте PD8 и реализуем логику программы при которой на удержание кнопки горит светодиод, при отпускание кнопки светодиод гаснет.

Файл: button.py

# GPIO used PD8, PD17
import gpiod
import sys
#
default_state=1

chip=gpiod.Chip('gpiochip0')

linesKey = chip.get_lines([104])
linesLed = chip.get_lines([113])

linesKey.request(consumer='foobar', type=gpiod.LINE_REQ_EV_BOTH_EDGES)
linesLed.request(consumer='foobar', type=gpiod.LINE_REQ_DIR_OUT, default_vals=[default_state])

while True:
  ev_lines = linesKey.event_wait(sec=1)
  if ev_lines:
      for line in ev_lines:
              event = line.event_read()
              #print_event(event)
              if event.type == gpiod.LineEvent.RISING_EDGE:
                evstr = ' RISING EDGE'
                linesLed.set_values([not(default_state)])
              elif event.type == gpiod.LineEvent.FALLING_EDGE:
                evstr = 'FALLING EDGE'
                linesLed.set_values([default_state])
              else:
                raise TypeError('Invalid event type')
              print('event: {} offset: {} timestamp: [{}.{}]'.format(evstr,
                      event.source.offset(),
                      event.sec, event.nsec))


Запустим программу:
Docker поддерживается из коробки, необходимо лишь установить пакет docker.io.

$ sudo apt-get update
$ sudo apt-get install -y docker.io


Для проверки текущей версии Docker необходимо выполнить команду:

$ docker version


Результат выполнения:

root@nezha:/boot/dtb/allwinner# docker version
Client:
 Version:           20.10.12
 API version:       1.41
 Go version:        go1.17.3
 Git commit:        20.10.12-0ubuntu4
 Built:             Mon Mar  7 17:27:43 2022
 OS/Arch:           linux/riscv64
 Context:           default
 Experimental:      true

Server:
 Engine:
  Version:          20.10.12
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.17.3
  Git commit:       20.10.12-0ubuntu4
  Built:            Mon Mar  7 15:57:50 2022
  OS/Arch:          linux/riscv64
  Experimental:     false
 containerd:
  Version:          1.5.9-0ubuntu3
  GitCommit:
 runc:
  Version:          1.1.0-0ubuntu1
  GitCommit:
 docker-init:
  Version:          0.19.0
  GitCommit:


Запустим тестовый контейнер с Ubuntu 22.04:

root@nezha:~# docker run -it ubuntu:22.04 /bin/bash
Unable to find image 'ubuntu:22.04' locally
22.04: Pulling from library/ubuntu
1edfbf9ed16b: Pull complete
Digest: sha256:b6b83d3c331794420340093eb706a6f152d9c1fa51b262d9bf34594887c2c7ac
Status: Downloaded newer image for ubuntu:22.04
root@17b3d67b8e90:/# uname -a
Linux 17b3d67b8e90 5.19.0-rc1-d1 #trunk Mon Jun 27 13:50:54 MSK 2022 riscv64 riscv64 riscv64 GNU/Linux
root@17b3d67b8e90:/#


При выборе контейнеров обращайте внимание, что они должны быть для архитектуры RISC-V с меткой riscv64. Для сборке своего контейнера используйте инструмент Buildx (инструкция Сборка Docker контейнеров для ARM архитектуры используя Buildx). Только при сборке укажите платформу --platform linux/riscv64, например:

$ docker buildx build --platform linux/riscv64 -f Dockerfile -t timeweb/ubuntu:riscv64 . --push


В образ Armbian_22.08.0-trunk_Nezha_jammy_current_5.19.0_xfce_desktop.img.xz включена графическая облочка XFCE. Не смотря на малую производительность процессора, интерфейс реагирует без задержек, каких либо проблем с отображением экрана не замечено.

Lichee RV
Оболочка XFCE на Lichee RV

Еще немного скриншотов
Lichee RV
Запуск утилиты htop в оболочке XFCE на Lichee RV

Lichee RV
Запуск утилиты mc в оболочке XFCE на Lichee RV

Lichee RV
Отображение системной информации в оболочке XFCE на Lichee RV


Работа графического интерфейса:
Обновился модуль Lichee RV, теперь доступна версия с 1 Гб RAM. В новой версии Dock, разъем для массива микрофонов заменили на интерфейс MIPI LCD/RGB на 30 контактов для подключения 720p30 LCD-панелей, добавили второй микрофон и порт USB-C для отладки JTAG+UART на базе BL702 RISC-V MCU, для покупки bundle: RV D1 Dock Pro.

MangoPi MQ-Pro


Помимо Sipeed Lichee RV на рынке существуют и другие платы с процессором Allwinner D1. Среди них наиболее удачно выглядит MangoPi MQ-Pro. Плату разработал стартап MangoPi. В отличие от Lichee RV, на плате размещен 40-Pins разъем GPIO, который полностью совместимый с аналогичным разъемом на Raspberry Pi 3. Форм фактор платы выполнен в стиле Raspberry Pi Zero, что более удобнее для DIY проектов, чем исполнение в виде модуля (SoM). Отдельно выведен разъем MIPI DSI для подключения дисплеев с сенсорным экраном. Последняя модификация v1.3 выполнена в розовом цвете тестолита. Есть версии с 512 Мб и 1 Гб RAM.

MangoPi MQ-Pro
MangoPi MQ-Pro

Стоимость модели с 512MB составляет $29.99, модель с 1GB стоит $38.56, без учета доставки.


Работа нового образа порадовала, работает довольно шустро в пределах возможностей процессора. Многие проблемы, которые были в старом образе, успешно решены. Вручную расширять раздел на карте памяти не требуется, эту задачу берет на себя скрипт из Armbian. Очень порадовала возможность запускать Docker-контейнеры из коробки. Система работает стабильно, зависаний не было замечено. Дополнительно для платы есть образ на базе российской операционной системы ALT Linux. Использование ОС ALT Linux вместе с платой на Allwinner D1 может стать неплохим «отечественным» решением на период санкций.

Пока в текущем образе нет поддержки dt-overlays, в отличие от плат на ARM-процессоре. Но DTO можно загружать динамически, в продолжение попробуем это проверить. К следующей публикации будет доработано расширение .NET FastIoT для возможности удаленной отладки приложений на Python, где и протестируем работу интерфейсов I2C, SPI, UART.


coe2kha8u8_pypip-2k3wk3ppa0.png

© Habrahabr.ru