image

В прошлой статье, мы с вами рассмотрели на что способен одноплатный компьютер, который стоит всего 1.000 рублей. Как мы выяснили, перспективы у данного девайса весьма неплохие, однако по факту, Orange Pi продаёт практически голую железку, которую нужно дорабатывать самому. Да, тут есть Ubuntu/Fedora, да, тут выведена гребенка с I2C/SPI — однако из коробки это всё работает криво-косо, либо не работает совсем. Даже обещанные шины SPI/I2C фактически не доступны в системе «из коробки». Материалов о доработке этого одноплатника в сети мало, поэтому я решил довести его до ума сам и поделится с вами — в том числе, готовыми бинарными образами! Интересно, на что способен доработанный одноплатник по цене ящика пива? :)

Над чем будем работать


В прошлой статье, мы с вами определились с потенциальными перспективами такого устройства. По цене 3х ESP32, производитель предлагает нам два полноценных вычислительных ARM-ядра, 256 мегабайт оперативной памяти, 512 мегабайт встроенной NAND-памяти, контроллер питания с возможностью работы от литий-ионных АКБ и 3G модем. Но в бочке меда нашлась ложка дегтя: никто не собирался это всё поддерживать и Orange Pi практически сразу «забили» на поддержку устройства, ограничившись портом Debian/Ubuntun на устройство.

image

Более того, производитель даже не описал как работать с GPIO и шинами устройства — что фактически превращало его из одноплатника в обычную ТВ-приставку, только без нормального видеовыхода. Меня крайне удивило, почему над такой дешевой платой не хотело работать коммьюнити — большинство людей только видели всю ситуацию и шли оставлять негативный отзыв, не попытавшись даже разобраться. А ведь для опытного линуксоида-эмбеддера здесь работы на день-два!

Ко всему прочему, в Linux не работает GSM-стек. Да, совсем. Производитель даже не стал кооперироваться с MediaTek, чтобы попытаться реализовать работу с модемом на уровне системы. А ведь фактически, вся работа с модемом происходит лишь на уровне AT-команд. Так в чем же проблема была?

image

Со всем этим мне и предстоит разобраться! Клонируем репозиторий с исходниками ядра и бежим собирать!

Собираем ядро. I2C и SPI


Вместо типичного Buildroot, Orange Pi использует свою собственную простую систему сборки на shell-скриптах: в качестве тулчейна используется уже готовый linaro. Отчасти, это связано с самими чипами, на которых работают их устройства — MediaTek, например, не использует Mainline ядро и в процессе сборке имеет ещё кучу шагов для подготовки финального образа. Там даже menuconfig не работает и все изменения приходится делать в уже сгенерированной когда-то конфигурации.

Клонируем репозиторий с системой сборки и запускаем скрипт:

git clone https://github.com/orangepi-xunlong/OrangePi_Build
cd OrangePi_Build
./Build_OrangePi.sh


image

Выбираем нашу плату — 3G IoT и ждем, пока система сборки фактически скачает все необходимое для сборки — исходный код ядра, папки external (драйвера, загрузчик и порт linux MediaTek). Обратите внимание, OrangePi даже систему сборки завязали на конкретной версии системы: только Ubuntu 18.04, но на самом деле, ядро соберется без проблем практически где угодно. После того, как все было скачано, переходим в папку с скриптом сборки и запускаем скрипт сборки:

cd ../OrangePi3G_iot/
./build.sh


А нет, не запускаем — скрипт жалуется на то, что не может поставить некоторые пакеты. Не беда — ставим bsdtar и python minimal вручную и идем править код скрипта. Находится в он scripts/general.sh: убираем оттуда устаревшие имена пакетов.

image

После этого, компиляция ядра должна пройти успешно. Обратите внимание на версию вашей платы — те, что продают сейчас — именно A. Если пытаться подкинуть им ядро для B, то они будут уходить в kernel panic из-за отсутствия eMMC.

image

Если mkbootimg будет жаловаться на libstdc++6, то ставим его x86 версию из репозиториев.

Готовое ядро будет лежать в output/kernel/boot.img, которое можно прошить на устройство. С одним маленьким нюансом — оно рассчитано на загрузку из внутренней памяти, которой критически мало для дистрибутива Linux! У нас нет boot_sd.img, который есть в оригинальном дистрибутиве. Попытка разобрать образ стандартным AndImgTool не увенчалась успехом — рамдиск встроен прямо в образ zImage, а не отдельно, как это обычно бывает у Android-образов.

image

Покопавшись в скриптах сборки, я так и не понял логику создания boot_sd, ничего связанного с sd я не нашел даже grep'ом по всей папке. Ну что-ж, тогда попробуем обходным путем: скомпилируем нужные драйвера в виде загружаемых модулей (ko). Идём в наш конфиг, расположенный в linux/arch/arm/configs/3giot_defconfig и меняем CONFIG_I2C_CHARDEV и CONFIG_SPI_SPIDEV на m. Пояснение: y заставит систему сборки скомпоновать драйвер статически с ядром, а m выделит его в виде отдельного модуля ko, который затем можно загрузить через insmod.

image

Снова собираем ядро, на этот раз компиляция занимает не больше минуты. Нужные нам файлы появятся в linux/drivers/spi/spidev.ko и linux/drivers/i2c/i2c-d-ev.ko. Переносим их на хост-пк, а затем и на само устройство с помощью SSH:

image

Загружаем модули ядра:

insmod i2c-dev.ko


И та-дам! Целых две i2c шины появилось в системе (/dev/i2c-0, /dev/i2c-1). Устанавливаем i2c-tools и идем проверять с помощью i2cdetect: первая шина полностью свободна под наши проекты, а на второй по некоторым адресам висит периферия (FM-радио как вариант):

image

I2C теперь точно работает! Но как насчет SPI?

insmod spidev.ko
Device or resource busy.


Увы! spidev нельзя подгружать динамически, только статически линковать с ядром, чего мы сделать пока не можем. Однако техническая возможность заставить работать SPI есть: например, написать свой драйвер, который транслирует команды из юзерспейса в SPI API, которое работает на уровне ядра.

GPIO


В прошлой статье, я вкратце рассказал, как работать с gpio из user-space на уровне терминала. Однако, большинство разработчиков потенциально будет пользоваться нативным API для GPIO — ну не всерьез же им парсить вывод состояния в консоль? Поэтому я решил написать крошечную библиотеку для работы с GPIO, такую же простую, как и DigitalWrite/DigitalRead!

Давайте сначала разберемся, как именно работать с драйвером GPIO. Для этого открываем исходники ядра и смотрим внимательно, что нам предлагает драйвер: в нашем случае, это вызовы IOCTL, да еще и простые и понятные. Это просто отлично! Я написал single-header библиотеку минут за 10: без проверки ошибок, но работоспособная.

void gpioInit();
void gpioSetDir(int num, byte dir);
byte gpioGetDir(int num);
void gpioWrite(int num, byte value);
byte gpioGetState(int num);
byte gpioRead(int num);
void gpioSetPullState(int num, byte enabled, byte up);


Пример использования (141 — крайний пин на гребенке):

#define GPIO_IMPL
#include "gpio.h"
#include <stdio.h>

void testPin(int pin)
{
	printf("Pin state %i is %i\n", pin, gpioGetState(pin));
	gpioSetDir(pin, 1);
	gpioWrite(pin, 0);
	printf("Pin state %i is %i\n", pin, gpioGetState(pin));
	gpioWrite(pin, 1);
	printf("Pin state %i is %i\n", pin, gpioGetState(pin));
}

int main(int argc, char** argv)
{
	gpioInit();
	testPin(141);
}


image

Модем


Скажу сразу: пока что завести модем мне не удалось, но я активно работаю над этим. В этой части статьи я распишу свои находки и догадки касательно модемов на чипах MediaTek.

В устройствах MediaTek, драйвер для общения с GPS, A-GPS и модемом один — ccci, судя по всему cross chip communication interface. Именно ccci создает устройства, с в которые поступает вход с микрофона и выход на динамики, а также он создает управляющие интерфейсы для общения с различными модулями этого SoC.

При старте ядра, ccci создаёт много устройств — ccci_ioctl, ccci_ipc, ccci_fs и самое нужное нам — ttyC0/ttyC1/ttyC2 — в зависимости от количества СИМ-карт в системе. Кроме ccci, в системе есть некий 6620_launcher — бинарник, который загружает прошивку Wi-Fi и gsm0710muxd — специальный сервис, который позволяет в GPRS-сетях одновременно разговаривать и сидеть в интернете.

На смартфонах MTK есть factory mode — так называемый тестовый режим, который гоняют на заводах. Вы, вероятно, когда-то видели китайские меню похожее на рекавери — это и есть factory mode. Из этого режима можно дозвонится в 911 и активировать модем без запуска Android и RIL. Как это работает? Идём читать исходники ядра!

В factory-режиме, для каждого теста, программа активирует модем заново. Для этого есть функции тестового режима для работы с AT-командами и для инициализации модема. Сначала, она открывает терминал /dev/ttyC0 — именно там происходит общение с модемом с помощью AT-команд:

image

После этого, программа выводит модем из режима сна с помощью команды «AT+ESLP=0», инициализирует СИМ-карту с помощью команды «AT+ESIMS» и задает режим работы с помощью «AT+EFUN=1» и «AT+CREG=1». После этого, модем начинает искать сеть и доступен для обычного общения с помощью AT-команд. Однако, написав тестовую софтину для общения с модемом из под Debian, я получал ошибки вида Device not found. Почему? Пока не знаю. Однако я продолжаю изучать данный вопрос!

Заключение


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

К счастью, довести гаджет до ума мы смогли своими силами. Весьма странно, что такой крупный и уважаемый производитель как Orange Pi, банально решил «забить» на поддержку собственного устройства. И я лично считаю, что не стоит закидывать в долгий ящик их тем читателям, которые купили когда-то себе подобный девайс и забили, смирившись с отсутствием гайдов.

Немного энтузиазма, опыта и видения будущего проекта — и все получится :)

Комментарии (16)


  1. Godless
    25.07.2023 08:24

    Это чудо можно относительно несложно превратить в сетевую колонку ? Не пробовали ?
    Чтобы пачку таких можно было по квартире раскидать для одновременного вывода звука ?

    Я так понял для звука тоже надо или готовую плату брать, или паять что-то...


    1. MDXE1337 Автор
      25.07.2023 08:24
      +1

      Да, подойдет, тут есть ЦАП и готовый звуковой тракт. Здесь уже даже джек распаян! Если под линух есть нужный софт или запилите сами - будет работать без проблем.


    1. vviz
      25.07.2023 08:24
      +1

      Вполне работают колонки на основе KaRadio+icecast+mpd+RompR


    1. DmSting
      25.07.2023 08:24

      Гуглите LMS - LogitechMediaServer и плеер squeeze, ну а следом esp-squeeze


  1. amateur80lvl
    25.07.2023 08:24

    Разве там не 4 ядра?


    1. MDXE1337 Автор
      25.07.2023 08:24

      Два. MT6572. 4 у 6582.


  1. phpmyadmin
    25.07.2023 08:24
    +1

    icewm, geany - уже почти забыл как они выглядят)


  1. shadrap
    25.07.2023 08:24

    не видел я оранжей 3г за 1000 , как минимум 2600р - а это уже больше 10-ка esp32 +SIM800... )



  1. Worky
    25.07.2023 08:24

    Обьясните, в чем смысл производителю изготовить плату и "кинуть" с поддержкой? или его "кинул" прозводитель чипа?


    1. MDXE1337 Автор
      25.07.2023 08:24

      Потому что это очень дешевая плата, и потому что ее проектировали с косяками изначально:

      Чипы MediaTek поддерживают параллельный, MIPI и RGB интерфейсы дисплеев, но не умеют хдми, а оранжи решили специально сделать MIPI и продавать дисплей отдельно втридорога (на которые особо никто не "клевал"). Так и получилось, что одноплатник остался без возможности вывода картинки.

      Плюс изначально не было поддержки i2c/spi, но они были разведены на гребенке. Почему так? Я хз.

      Сейчас в похожем ценовом сегменте есть платы Lctech. Их не особо поддерживают, однако производитель поступил проще: сразу добавил поддержку своей платы в мейнлайн ядро и теперь нет никаких проблем с запуском актуальной версии линуха :)


    1. NutsUnderline
      25.07.2023 08:24

      нажежда что пипл схавает и своими силами допилит, бесплатно, да еще и добавки попросит. это не единтвенная у них такая плата. на плате с процом H6 сделали pci который толком запустить не смогли (был костыль с гипервизором). были вроде вполне ниче платы но исчезли из производства. нам никогда не узнать каким местом они там думали, но вероятно - считали деньги


  1. FirstEgo
    25.07.2023 08:24

    Я крайний раз с таким удовольствием наблюдал за проектом, наверное, во времена плеера из журнала vogue))

    Спасибо за старания!!!))


  1. Paskin
    25.07.2023 08:24

    я получал ошибки вида Device not found.

    Я бы в этом случае смотрел бы в сторону device tree. Драйверы ядра работают с абстракциями типа "пин_RxD" и "пин_ТxD" - а соответствие физическим "ножкам" микроконтроллера и параметрам конкретной платы задается именно там.


    1. MDXE1337 Автор
      25.07.2023 08:24

      В том и суть, что ядро старое - там нет devicetree. 3.4.67 если не ошибаюсь, все настройки через machine-файлы.