Многим устройствам на базе встраиваемых систем необходим интернет. Проводное подключение к интернету для них не всегда возможно, и если устройства находятся в зоне действия сотовой связи, то к интернету можно подключиться с помощью GSM/3G/4G-модемов.
В этой заметке описан процесс создания дистрибутива ОС Linux для встраиваемой системы при помощи инструментария Yocto Project, позволяющий подключать устройство к интернету через GSM/3G/4G-модем и протокол PPP.
Содержание
- Оборудование и программное обеспечение
- Подготовка ПК для сборки дистрибутива
- Создание проекта и сборка дистрибутива
- Добавление поддержки протокола PPP в ядро ОС
- Добавление в дистрибутив пакета ppp
- Скрипты для pppd и chat
- Рецепт расширения для пакета ppp
- Заключение и ссылка на проект
Оборудование и программное обеспечение
Дистрибутив ОС Linux для встраиваемой системы будем собирать с помощью Yocto Project версии THUD 2.6.4 на ПК под управлением ОС Ubuntu 18.04.
Роль встраиваемой системы будет играть устройство BeagleBone Black Rev. C с подключенным к нему LTE-модемом Quectel EC21-E. Для этого мы воспользуемся отладочным набором UMTS<E EVB для тестирования UMTS и LTE модулей Quectel. Структурная схема стенда, с которым мы будем экспериментировать, приведена на рис. 1.
Рисунок 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 NMEAttyUSB2
– порт для 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