В первой части познакомились с процессором 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.
Один из ведущих мейнтейнеров проекта 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
Первый запуск 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.
Отобразим картинку neofetch:
Запуск программы neofetch на Lichee RV
Запустим менеджер задач, утилита htop . Температура во время работы составляет 48.5°C в холостом режиме.
Запуск утилиты htop на Lichee RV
Загрузка памяти RAM составляет всего 117 Мб из 512.
Поддержка устройств
Все ключевые устройства такие как HDMI, WiFi, USB, поддерживаются. Единственное, на данный момент нет поддержки небольшого дополнительного дисплея 1.14″ SPI на контроллере Sitronix ST7789V.
Файл 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.
Схема подключения RGB-светодиод к контакту PC0
По пути /sys/class/leds располагается устройство rgb:indicator .
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
Включение RGB-светодиода на Sipeed Lichee RV Dock
Пользовательская кнопка (KEY)
Кнопка KEY подключена к контакту ADC_LRADC. Это низкоскоростной АЦП (LRADC) имеет 6-битное разрешение для ключевого приложения. LRADC может работать с максимальной частотой преобразования 2 кГц. Регистрирует напряжение в диапазоне от 0 до 3.3 В.
Схема подключения кнопки 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:"<WIFI@REALTEK>" 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 работает без ошибок, но воспроизведение звука и запись на микрофон не выполнялось.
GPIO
На несущей 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, если они не указаны).
В дереве устройств, устройство контакты 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
Написание программы на 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 поддерживается из коробки, необходимо лишь установить пакет 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
XFCE
В образ Armbian_22.08.0-trunk_Nezha_jammy_current_5.19.0_xfce_desktop.img.xz включена графическая облочка XFCE. Не смотря на малую производительность процессора, интерфейс реагирует без задержек, каких либо проблем с отображением экрана не замечено.
Работа графического интерфейса:Обновление плат на процессоре Allwinner D1 RISC-V
Обновился модуль 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.4 выполнена в розовом цвете тестолита. Есть версии с 512 Мб и 1 Гб RAM.
Официальный магазин на Aliexpress — DongshanPI Store. Стоимость модели с 512MB составляет $22.02, модель с 1GB стоит $26.29, без учета доставки.
Итог
Работа нового образа порадовала, работает довольно шустро в пределах возможностей процессора. Многие проблемы, которые были в старом образе, успешно решены. Вручную расширять раздел на карте памяти не требуется, эту задачу берет на себя скрипт из Armbian. Очень порадовала возможность запускать Docker-контейнеры из коробки. Система работает стабильно, зависаний не было замечено. Дополнительно для платы есть образ на базе российской операционной системы ALT Linux. Использование ОС ALT Linux вместе с платой на Allwinner D1 может стать неплохим «отечественным» решением на период санкций.
Пока в текущем образе нет поддержки dt-overlays, в отличие от плат на ARM-процессоре. Но DTO можно загружать динамически, в продолжение попробуем это проверить. К следующей публикации будет доработано расширение .NET FastIoT для возможности удаленной отладки приложений на Python, где и протестируем работу интерфейсов I2C, SPI, UART.
Обсуждение на Habr.com