image


Многим устройствам на базе встраиваемых систем необходим интернет. Проводное подключение к интернету для них не всегда возможно, и если устройства находятся в зоне действия сотовой связи, то к интернету можно подключиться с помощью GSM/3G/4G-модемов.


В этой заметке описан процесс создания дистрибутива ОС Linux для встраиваемой системы при помощи инструментария Yocto Project, позволяющий подключать устройство к интернету через GSM/3G/4G-модем и протокол PPP.


Содержание



Оборудование и программное обеспечение


Дистрибутив ОС Linux для встраиваемой системы будем собирать с помощью Yocto Project версии THUD 2.6.4 на ПК под управлением ОС Ubuntu 18.04.


Роль встраиваемой системы будет играть устройство BeagleBone Black Rev. C с подключенным к нему LTE-модемом Quectel EC21-E. Для этого мы воспользуемся отладочным набором UMTS&LTE EVB для тестирования UMTS и LTE модулей Quectel. Структурная схема стенда, с которым мы будем экспериментировать, приведена на рис. 1.


image


Рисунок 1 — Структурная схема стенда


Подготовка ПК для сборки дистрибутива


Убедитесь, что на вашем ПК есть 50 ГБ свободного дискового пространства и на нем установлены:


  • Git версии 1.8.3.1 или новее;
  • Tar версии 1.27 или новее;
  • Python версии 3.4.0 или новее.

Установим необходимые пакеты:


$ sudo apt-get install gawk wget git-core diffstat unzip texinfo                        gcc-multilib build-essential chrpath socat                         cpio python python3 python3-pip python3-pexpect                        xz-utils debianutils iputils-ping libsdl1.2-dev xterm

На этом подготовка ПК для сборки дистрибутива с использованием инструментария Yocto Project закончена. Любопытные читатели могут получить более подробную информацию ознакомившись с Yocto Project Quick Build.


Создание проекта и сборка дистрибутива


Создадим в домашней директории каталог, где у нас будет хранится репозитории Poky и мета-слои с рецептами. Назовем его habr-yocto-lte:


~$ mkdir habr-yocto-lte

Перейдем в директорию habr-yocto-lte и создадим пустой git репозиторий:


~$ cd habr-yocto-lte
~/habr-yocto-lte$ git init

Добавим в созданный git-репозиторий, в виде подмодулей, проект Poky и слой meta-ti:


~/habr-yocto-lte$ git submodule add -b thud git://git.yoctoproject.org/poky.git
~/habr-yocto-lte$ git submodule add -b thud git://git.yoctoproject.org/meta-ti

Poky это как раз тот самый инструмент, с помощью которого мы будем собирать наш дистрибутив, а meta-ti – это слой, который объединяет в себе наборы рецептов, классов и конфигурационных файлов для процессоров Texas Instruments. Подробнее о том, что такое Poky и мета-слои можно узнать из Yocto Project Overview and Concepts Manual.


Создадим файл oe-init-build-env и сделаем его исполняемым:


~/habr-yocto-lte$ touch oe-init-build-env
~/habr-yocto-lte$ chmod +x oe-init-build-env

Добавим в него следующий код:


#!/bin/sh
source $(pwd)/poky/oe-init-build-env build

Файл oe-init-build-env мы будем запускать всякий раз, при открытии нового окна терминала. Давайте запустим его командой:


~/habr-yocto-lte$ source ./oe-init-build-env

При первом выполнении скрипта в папке ~/habr-yocto-lte будет создана папка build, содержащая конфигурационные файлы и результаты сборки дистрибутива, а в окне терминала мы увидим нечто вроде этого:


### Shell environment set up for builds. ###

You can now run 'bitbake <target>'

Common targets are:
    core-image-minimal
    core-image-sato
    meta-toolchain
    meta-ide-support

You can also run generated qemu images with a command like 'runqemu qemux86'

В принципе, теперь у нас все готово для сборки дистрибутива, но мы сделаем еще несколько «штрихов»:


  • Добавим слой meta-ti и удалим слой meta-poky-bsp. Для этого запишем в переменную BBLAYERS, которая находится в файле ~/habr-yocto-lte/build/conf/bblayers.conf, следующее значение:

BBLAYERS ?= "         /home/alex/habr/poky/meta         /home/alex/habr/poky/meta-poky         /home/alex/habr/meta-ti         "

  • В качестве целевой системы, на которой будет работать наш дистрибутив выберем beaglebone. Разрешим запись истории сборки, это поможет нам понять какие пакеты были установлены в дистрибутив, узнать их размер и др. Формат пакетов сделаем ipk и разрешим модули ядра. Вместо sysvinit будем использовать systemd. Обновим конфигурацию дистрибутива, добавив в конец файла ~/habr-yocto-lte/build/conf/local.conf следующие строки:

MACHINE = "beaglebone"
INHERIT += "buildhistory"
BUILDHISTORY_COMMIT = "1"
PACKAGE_CLASSES = "package_ipk"
CORE_IMAGE_EXTRA_INSTALL += " kernel-modules"
DISTRO_FEATURES_append = " systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED += "sysvinit"
VIRTUAL-RUNTIME_init_manager = "systemd"
VIRTUAL-RUNTIME_initscripts = "systemd-compat-units"

Запустим сборку дистрибутива:


~/habr-yocto-lte/build$ bitbake –k core-image-base

Пока собирается дистрибутив можете пойти вздремнуть, у вас есть на это часа 4 :). Потом будет собираться всё гораздо быстрее.


Дистрибутив сохранится в каталоге ~/habr-yocto-lte/build/tmp/deploy/images/beaglebone


Добавление поддержки протокола PPP в ядро ОС


Устройство, на котором будет установлен дистрибутив, созданный в предыдущем разделе, уже сможет распознать LTE-модуль Quectel EC21-E, т.к. его драйвера есть в ядре Linux. Однако для подключения устройства к интернету нам необходимо добавить поддержку протокола PPP в ядро Linux, а также добавить в наш дистрибутив пакет ppp и написать для него файл расширения рецепта, который «расскажет» bitbake как и куда установить в нашем дистрибутиве необходимые файлы для pppd и chat, являющиеся частью пакета ppp.


Для конфигурирования ядра выполним команду:


~/habr-yocto-lte/build$ bitbake virtual/kernel -c menuconfig

Откроется стандартное окно menuconfig в котором надо выбрать:


Device drivers --->
    [*] Network device support --->
        <M> PPP (point-to-point protocol) support
            <M> PPP BSD-Compress compression
            <M> PPP Deflate compression
            <*> PPP filtering
            <M> PPP MPPE compression (encryption)
            <*> PPP multilink support
            <M> PPP over Ethernet
            <M> PPP support for async serial ports
            <M> PPP support for sync tty ports 

Сохраняем конфигурацию и выходим из menuconfig. Учтите, что эта конфигурация будет применяться только на том ПК, на каком она была сохранена. Для того что бы она применялась на любом ПК при клонировании проекта из репозитория, необходимо сохранить конфигурацию в файле defconfig и написать рецепт расширения для recipes-kernel.


Сохраним конфигурацию ядра в файле defconfig:


~/habr-yocto-lte/build$ bitbake virtual/kernel -c savedefconfig

Файл defconfig сохранится в каталоге ~/habr-yocto-lte/build/tmp/work/beaglebone-poky-linux-gnueabi/linux-ti-staging/4.19.94+gitAUTOINC+5a23bc00e0-r22a/build


Все рецепты расширения и рецепты, написанные нами, будем хранить в отдельном мета-слое. Создадим и назовем его meta-habr:


~/habr-yocto-lte/build$ bitbake-layers create-layer ~/habr-yocto-lte/meta-habr

В каталоге ~/habr-yocto-lte появится директория meta-habr – это и есть наш мета-слой. В этой директории будет пример рецепта recipes-example, он нам не нужен, удалим его, а затем добавим наш мета-слой в файл bblayers.conf:


~/habr-yocto-lte/build$ rm -r ~/ habr-yocto-lte/meta-habr/recipes-example/
~/habr-yocto-lte/build$ bitbake-layers add-layer ~/habr-yocto-lte/meta-habr

Пришло время сделать рецепт расширения для ядра Linux. Создаем необходимые каталоги и файлы:


~/habr-yocto-lte$  mkdir – p meta-habr/recipes-kernel/linux/linux-ti-staging/beaglebone
~/habr-yocto-lte$  touch meta-habr/recipes-kernel/linux/linux-ti-staging_%.bbappend

Копируем ранее созданный файл defconfig в каталог ~/habr-yocto-lte/meta-habr/recipes-kernel/linux/linux-ti-staging/beaglebone


~/habr-yocto-lte$ cp ~/habr-yocto-lte/build/tmp/work/beaglebone-poky-linux-gnueabi/linux-ti-staging/4.19.94+gitAUTOINC+5a23bc00e0-r22a/build/defconfig  meta-habr/recipes-kernel/linux/linux-ti-staging/beaglebone

и добавляем в файл linux-ti-staging_%.bbappend следующий код:


FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://defconfig"

Теперь конфигурация ядра, определенная в файле defconfig будет применяться всегда при сборке дистрибутива. Соберём его и убедимся, что требуемые модули PPP установлены:


~/habr-yocto-lte/build$ bitbake –k core-image-base
~/habr-yocto-lte/build$ cat buildhistory/images/beaglebone/glibc/core-image-base/installed-packages.txt | grep "ppp"
--------------------------------------------------------
kernel-module-ppp-async-4.19.94-g5a23bc00e0_4.19.94+git0+5a23bc00e0-r22a_beaglebone.ipk
kernel-module-ppp-deflate-4.19.94-g5a23bc00e0_4.19.94+git0+5a23bc00e0-r22a_beaglebone.ipk
kernel-module-ppp-generic-4.19.94-g5a23bc00e0_4.19.94+git0+5a23bc00e0-r22a_beaglebone.ipk
kernel-module-ppp-mppe-4.19.94-g5a23bc00e0_4.19.94+git0+5a23bc00e0-r22a_beaglebone.ipk
kernel-module-pppoe-4.19.94-g5a23bc00e0_4.19.94+git0+5a23bc00e0-r22a_beaglebone.ipk
kernel-module-pppox-4.19.94-g5a23bc00e0_4.19.94+git0+5a23bc00e0-r22a_beaglebone.ipk
kernel-module-ppp-synctty-4.19.94-g5a23bc00e0_4.19.94+git0+5a23bc00e0-r22a_beaglebone.ipk

Добавление в дистрибутив пакета ppp


Пакеты программ добавляются в дистрибутив с помощью переменной IMAGE_INSTALL_append. Добавим её в конец файла local.conf и присвоим ей значение соответствующее имени пакета:


IMAGE_INSTALL_append = " ppp"

Соберём дистрибутив и убедимся, что пакет ppp установлен:


~/habr-yocto-lte/build$ bitbake –k core-image-base
~/habr-yocto-lte/build$ cat buildhistory/images/beaglebone/glibc/core-image-base/installed-packages.txt | grep "ppp_"
--------------------------------------------------------
ppp_2.4.7-r0_beaglebone.ipk

Теперь в нашем дистрибутиве есть все для того чтобы подключить устройство к интернету через LTE-модем. Однако мне лично не очень хочется настраивать pppd и chat, входящие в пакет ppp, непосредственно на устройстве. Поэтому давайте добавим необходимые скрипты для этих программ в наш дистрибутив с помощью расширения рецепта ppp.


Скрипты для pppd и chat


Создадим три файла скриптов habrppp, habr-chat-connect и habr-chat-disconnect со следующим содержимым:


  • habrppp
    /dev/ttyUSB3
    921600
    user "beeline"
    password "beeline"
    connect 'chat -s -v -f /etc/ppp/peers/habr-chat-connect'
    disconnect 'chat -s -v -f /etc/ppp/peers/habr-chat-disconnect'
    hide-password
    noauth
    debug
    defaultroute
    noipdefault
    persist
  • habr-chat-connect
    ABORT "BUSY"
    ABORT "NO CARRIER"
    ABORT "NO DIALTONE"
    ABORT "ERROR"
    ABORT "NO ANSWER"
    TIMEOUT 30
    "" AT
    OK ATE0
    OK ATI;+CSUB;+CSQ;+CPIN?;+COPS?;+CGREG?;&D2
    OK AT+CGDCONT=1,"IP","static.beeline.ru",,0,0
    OK ATD*99#
    CONNECT ""
  • habr-chat-disconnect
    ABORT "ERROR"
    ABORT "NO DIALTONE"
    "" +++
    "" +++
    "" +++

Несколько комментариев по представленным выше скриптам.
LTE-модуль Quectel EC21-E определятся в системе в виде четырёх последовательных портов:


  • ttyUSB0 – порт отладки
  • ttyUSB1 – порт для сообщений GPS NMEA
  • ttyUSB2 – порт для AT-команд
  • ttyUSB3 – порт для установления соединения PPP

Если в вашей системе есть другие USB-устройства, то нумерация портов, возможно, будет отличаться от приведенной выше, но последовательность останется та же. Поскольку в нашей системе нумерация портов соответствует выше приведенной, то в скрипте habrppp мы указали в качестве порта для соединения по протоколу PPP порт /dev/ttyUSB3.


Обратите внимание на поля user и password в скрипте habrppp, а также на APN в команде AT+CGDCONT в скрипте habr-chat-connect, они должны быть установлены согласно рекомендациям сотового оператора.


Рецепт расширения для пакета ppp


Осталось совсем чуть-чуть. Создадим каталоги и файл для рецепта расширения ppp:


~/habr-yocto-lte$ mkdir –p meta-habr/recipes-connectivity/ppp/ppp/beaglebone
~/habr-yocto-lte$ touch meta-habr/recipes-connectivity/ppp/ppp_%.bbappend

Скопируем скрипты, написанные в предыдущем разделе в папку ~/habr-yocto-lte/meta-habr/recipes-connectivity/ppp/ppp/beaglebone и добавим следующее содержимое в файл ppp_%.bbappend:


FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" 

SRC_URI += "file://habrppp \             
            file://habr-chat-connect \             
            file://habr-chat-disconnect \             
            file://20-habr-modem.rules \             
            " 

do_install_append () {  
        install -m 0755 ${WORKDIR}/habrppp ${D}${sysconfdir}/ppp/peers/habrppp  
        install -m 0755 ${WORKDIR}/habr-chat-connect ${D}${sysconfdir}/ppp/peers/habr-chat-connect  
        install -m 0755 ${WORKDIR}/habr-chat-disconnect ${D}${sysconfdir}/ppp/peers/habr-chat-disconnect    
        mkdir -p ${D}${sysconfdir}/udev/rules.d     
        install -m 0755 ${WORKDIR}/20-habr-modem.rules ${D}${sysconfdir}/udev/rules.d/20-habr-modem.rules 
}

Вы, наверное, заметили, что к тем трем файлам скрипта добавился файл 20-habr-modem.rules. Это правило для udev, согласно которому при возникновении в системе порта ttyUSB3 будет автоматически запущена служба pppd с нужными нам настройками. Таким образом наше устройство будет всегда подключаться к интернету при подключении модема к USB-порту. Содержимое файла 20-habr-modem.rules:


SUBSYSTEM=="tty", KERNEL=="ttyUSB3", TAG+="systemd", ENV{SYSTEMD_WANTS}="ppp@habrppp.service"

Заключение и ссылка на проект


Осталось собрать наш дистрибутив, с помощью программы balenaEtcher записать его образ на microSD карту памяти и запустить на устройстве. Теперь наше устройство подключено к интернету:


~$ ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

ppp0      Link encap:Point-to-Point Protocol
          inet addr:XXX.XXX.XXX.XXX  P-t-P:XXX.XXX.XXX.XXX  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:13 errors:0 dropped:0 overruns:0 frame:0
          TX packets:17 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:432 (432.0 B)  TX bytes:611 (611.0 B)

Подключением к интернету через протокол PPP можно управлять вручную, с помощью команд pon и poff. Для установления соединения выполните команду:


~$ pon habrppp

Для завершения соединения:


~$ poff habrppp



Проект доступен по адресу https://gitlab.com/amamaev/habr-yocto-lte. Для клонирования репозитория выполните команду:


~$ git clone --recursive https://gitlab.com/amamaev/habr-yocto-lte.git

Не забудьте скорректировать пути к слоям в файле bblayers.conf