Yocto Project - это Open Source инфраструктура которая позволяет самостоятельно собрать дистрибутив Linux с нужными функциям для встраиваемых систем на архитектурах ARM, PowerPC, MIPS, x86 и x86-64. Название Yocto происходит от приставки дольних единиц измерения в СИ, эквивалентную 10-24. Для использования Yocto на встраиваемой системе необходимо включить в дистрибутив так называемый BSP (Board Support Package), который будет состоять из драйверов и пакетов обеспечивающих работу аппаратного обеспечения. В частности на основе Yocto создаются дистрибутивы для Intel Edison с названием Yocto* complete image, которые предлагается скачать на стринице загрузки https://software.intel.com/en-us/iot/hardware/edison/downloads. Самостаятельная сборка дистрибутива дает намного больше возможностей в разработке - вы можете включать дополнительные бинарные пакеты в систему, конфигурировать ядро Linux (в частности добавлять в ядро модули для поддержки новых устройств), добавлять патчи с исправлениями которые выходят еще до выпуска дистрибутива, имеете возможность создавать бинарные пакеты ipk для менеджера opkg, используемого в Yocto, запускать дистримутив в эмуляторе QEMU. В статье мы собрем дистрибутив и слегка модефицируем его для своих нужд.

Внимание: эта статья описывает сборку ранней версии Yocto, гайда по сборке новой версии тут

В качестве системы на которой будет выполнятся сборка я буду использовать Ubuntu 14.04.4 LTS, Trusty Tahr

Все мои действия будут основаны на http://www.intel.com/content/dam/support/us/en/documents/edison/sb/edisonbsp_ug_331188007.pdf. Сначала устанавливаем инструменты необходимые для сборки :

sudo apt-get install build-essential git diffstat gawk chrpath texinfo

Теперь нам нужен архив исходников, они называются edison-src-wwXX.tgz. Я буду использовать версию 05-15 (edison-src-ww05-15.tgz) отсюда https://downloadcenter.intel.com/download/24909/Intel-Edison-OS-Image-release-2-0. Во всех старших версиях присутствует критический баг при использовании SPI из-за которого ядро ложиться в Kernal Panic и выполняющий процесс зависает до перезагрузки. Сразу скажу что в старших версиях пути по которым будут лежать некоторые файлы (например setup.sh и oe-init-build-env, о которых вы узнаете дальше). В этом случае вам просто нужно выполнить find -name имя_файла.

Распакуем архив и запустим процесс инициализации сборочной среды: 

tar -xf edison-src-ww05-15.tgz
cd edison-src
mkdir bitbake_download_dir
mkdir bitbake_sstate_dir
./device-software/setup.sh --dl_dir=./bitbake_download_dir --sstate_dir=./bitbake_sstate_dir

--dl_dir указывает на папку для хранения загрузок из интернета а --sstate_dir на папку кеша сборки. После выполнения setup.sh должен быть такой вывод:

We are building in external mode
Extracting upstream Yocto tools in the /home/user/edibuild/edison-src/poky directory from archive
Unpacking Mingw layer to poky/meta-mingw/ directory from archive
Unpacking Darwin layer to poky/meta-darwin/ directory from archive
Initializing yocto build environment
Setting up yocto configuration file (in build/conf/local.conf)
** Success **
SDK will be generated for linux32 host
Now run these two commands to setup and build the flashable image:
cd /home/user/edibuild/edison-src
source poky/oe-init-build-env
bitbake edison-image

Теперь можем активировать переменные среды:

source ./poky/oe-init-build-env

И запустить сборку:

bitbake edison-image

Сборка может занять несколько часов, а пока мы рассмотрим основыне принципы строения Yocto.

В результате полученный стартовый дистрибутив будет называться poky-edison и иметь версию 1.6.1, это видно в выводе bitbake:

Build Configuration:
BB_VERSION = "1.22.0"
BUILD_SYS = "i686-linux"
NATIVELSBSTRING = "Ubuntu-14.04"
TARGET_SYS = "i586-poky-linux"
MACHINE = "edison"
DISTRO = "poky-edison"
DISTRO_VERSION = "1.6.1"
TUNE_FEATURES = "m32 core2"
TARGET_FPU = ""

Проект Yocto очень похож на проект OpenEmbedded. OpenEmbedded это отдельная инфраструктура для сборки дистрибутивов, по назначению аналогичная с Yocto, и эти два проекта тесно сотрудничают. Принципиальное сходство в том что они оба используют систему сборки BitBake. По сути это программа которая выполняет сценарии сборки исходных кодов в бинарные пакеты. Сами сценарии в терминах Bitbake называются рецептами (файлы с расширением .bb), или же в более широком смысле метаданным. Если вы когда-либо собирали пакеты под RPM-based системы, то можно провести аналогию с конфигами для утилиты rpmbuild - в них указывается какой архив с исходниками использовать для генерации пакета, каким образом его собирать, какие действия выполнять после сборки.

Все рецепты в Yocto делят на слои. В одном слое есть много рецептов.  С точки зрения файловой системы слой как правило это папка с названием meta-название в которой хранятся папки с пакетами в которых уже лежат рецепты .bb. Основной базовый слой метаданных - это meta-yocto который разрабатывается только в рамках проекта Yocto, это набор стандартных пакетов которые поставляются в дистрибутиве по умолчанию. Именно они сейчас собираются.

Еще очень популярная группа слоев которая не включена по умолчанию и может браться из проекта OpenEmbedded-Core. В частности это базовый слой oe-core. Вы можете подключить этот слой и получите возможность добавить в дистрибутив кучу дополнительных пакетов которых нет в meta-yocto

Тюнинг дистрибутива и добавление пакетов

Основные настройки BSP хранятся в файле edison-src/device-software/meta-edison-distro/recipes-core/images/edison-image.bb . Рассмотрев этот файл вы увидите много директив

IMAGE_INSTALL += 'название'

Это вклюения пакетов в дистрибутив. Посмотреть все возможные пакеты из стандартного слоя yocto можно тут: http://recipes.yoctoproject.org/rrs/recipes/1.6/All/, обратите внимание на версию, у нас 1.6, что видно в выводе bitbake в параметре DISTRO_VERSION . Вы можете убрать пакеты из предустановки закомментировав такие строки, либо добавить их в PACKAGE_EXCLUDE

PACKAGE_EXCLUDE = "package1 package2"

Добавление слоев из meta-openembedded

В стандартном слое много пакетов но их не всегда хватает. Например мне нужены пакеты vim, openvpn и usb-modeswitch которых там нет. Добавим слой в проект:

cd /home/user/edibuild/edison-src/device-software/
git clone https://github.com/openembedded/meta-openembedded.git
cd meta-openembedded

Теперь нам нужно чекаутнуться на бранчу для нашей версии Yocto. Как вы помните у нас 1.6. Ветка называется как кодовое имя, которое можно узнать тут https://wiki.yoctoproject.org/wiki/Releases, то есть у нас daisy.

git checkout daisy

В репозитарии много слоев, слой по сути представляет самой каталог meta-xxx в папке meta-openembedded:

$ ls -la  /home/user/edibuild/edison-src/device-software/meta-openembedded/
...
drwxrwxr-x  9 user user 4096 кві  9 02:12 meta-efl
drwxrwxr-x  6 user user 4096 кві  9 02:12 meta-filesystems
drwxrwxr-x  7 user user 4096 кві  9 02:12 meta-gnome
drwxrwxr-x  5 user user 4096 кві  9 02:12 meta-gpe
drwxrwxr-x  7 user user 4096 кві  9 02:12 meta-initramfs
drwxrwxr-x  8 user user 4096 кві  9 02:12 meta-multimedia
drwxrwxr-x 10 user user 4096 кві  9 02:12 meta-networking
drwxrwxr-x 19 user user 4096 кві  9 02:12 meta-oe
drwxrwxr-x  4 user user 4096 кві  9 02:12 meta-perl
drwxrwxr-x  4 user user 4096 кві  9 02:12 meta-ruby
drwxrwxr-x  5 user user 4096 кві  9 02:12 meta-systemd
drwxrwxr-x  6 user user 4096 кві  9 02:12 meta-webserver
drwxrwxr-x 11 user user 4096 кві  9 02:12 meta-xfce
...

Что бы понять какие слои вам нужны найдите какие пакеты где лежат:

$ cd /home/user/edibuild/edison-src/device-software/meta-openembedded/
$ find -name vim* ./meta-oe/recipes-support/vim ... $ find -name openvpn* ./meta-networking/recipes-support/openvpn ...

То есть мне нужны meta-oe и meta-networking, их нужно добавить в edison-src/build/conf/bblayers.conf:

# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
LCONF_VERSION = "6"

BBPATH = "${TOPDIR}"
BBFILES ?= ""
BBLAYERS ?= " \
  /home/user/edibuild/edison-src/poky/meta \
  /home/user/edibuild/edison-src/poky/meta-yocto \
  /home/user/edibuild/edison-src/poky/meta-yocto-bsp \
  /home/user/edibuild/edison-src/device-software/meta-edison \
  /home/user/edibuild/edison-src/device-software/meta-edison-distro \
  /home/user/edibuild/edison-src/device-software/meta-edison-middleware \
  /home/user/edibuild/edison-src/device-software/meta-edison-arduino \
  /home/user/edibuild/edison-src/device-software/meta-edison-devtools \
  /home/user/edibuild/edison-src/device-software/meta-openembedded/meta-oe \
  /home/user/edibuild/edison-src/device-software/meta-openembedded/meta-networking \
  "
BBLAYERS_NON_REMOVABLE ?= " \
  /home/user/edibuild/edison-src/poky/meta \
  /home/user/edibuild/edison-src/poky/meta-yocto \
  "

Теперь можем отредактировать edison-src/device-software/meta-edison-distro/recipes-core/images/edison-image.bb добавив в него имена пакетов:

IMAGE_INSTALL += "vim"
IMAGE_INSTALL += "openvpn"
IMAGE_INSTALL_append += " usb-modeswitch"

Все теперь можно по новой запустить процесс сборки source ..../oe-init-build-env и bitbake edison-image.

 

Конфигурирование ядра Linux

Иногда необходимо добавить в Linux драйвера для каких-нибудь специфичных устройств, которых нет по дефолту. Для этого нам нужно зайти в menuconfig следующим образом:

bitbake virtual/kernel -c menuconfig

После изменения нужных настроек необходимо сохраниь конфиг, например в предлагаемый файл .config. Теперь нужно забекапить оригинальный defconfig и скопировать вместо него наш:

mv ../device-software/meta-edison/recipes-kernel/linux/files/defconfig  ../device-software/meta-edison/recipes-kernel/linux/files/defconfig_back
cp ../build/tmp/work/edison-poky-linux/linux-yocto/3.10.17+gitAUTOINC+6ad20f049a_c03195ed6e-r0/linux-edison-standard-build/.config ../device-software/meta-edison/recipes-kernel/linux/files/defconfig

Для контроля можете посмотреть дифф и сверить какие опции поменялись:

diff ../device-software/meta-edison/recipes-kernel/linux/files/defconfig ../device-software/meta-edison/recipes-kernel/linux/files/defconfig_back 

Затем нужно опять пересобрать дистрибутив.

Прошивка собранного образа

После сборки yocto нужно сгенерировать файлы для прошивки при помощи postBuild.sh и прошить при помощи flashall.sh. У меня вывод postBuild выглядел так:

 

~/edibuild/edison-src/build$ ../device-software/utils/flash/postBuild.sh
1+0 records in
1+0 records out
4194304 bytes (4,2 MB) copied, 0,0215163 s, 195 MB/s
1+0 records in
1+0 records out
4194304 bytes (4,2 MB) copied, 0,012597 s, 333 MB/s
1+0 records in
1+0 records out
4194304 bytes (4,2 MB) copied, 0,020364 s, 206 MB/s
1+0 records in
1+0 records out
4194304 bytes (4,2 MB) copied, 0,0128462 s, 327 MB/s
1+0 records in
1+0 records out
4194304 bytes (4,2 MB) copied, 0,00999699 s, 420 MB/s
1+0 records in
1+0 records out
4194304 bytes (4,2 MB) copied, 0,0118049 s, 355 MB/s
1+0 records in
1+0 records out
4194304 bytes (4,2 MB) copied, 0,0325766 s, 129 MB/s
cp: cannot stat ‘/home/user/edibuild/edison-src/build/tmp/deploy/images/edison/vmlinux’: No such file or directory
find: `/home/user/edibuild/edison-src/u-boot': No such file or directory
Image Name: Edison Updater script
Created: Sat Apr 9 18:31:58 2016
Image Type: PowerPC Linux Script (uncompressed)
Data Size: 14683 Bytes = 14.34 kB = 0.01 MB
Load Address: 00010000
Entry Point: 00010000
Contents:
Image 0: 14675 Bytes = 14.33 kB = 0.01 MB
**** Done ***
Files ready to flash in /home/user/edibuild/edison-src/build/toFlash/
Run the flashall script there to start flashing.

Из Linux

 

Для прошивки из линукса понадобится dfu-util. На убунтах в репозитариях он старый (DFU 1.0, а нужно 1.1) по этому нужно ссобрать:

git clone git://git.code.sf.net/p/dfu-util/dfu-util
cd dfu-util/
./autogen.sh
sudo apt-get install libusb-1.0-0-dev
./configure
make && sudo make install

Теперь запускаем flashall.sh подключаем и перезагружаем плату (для входа в бутлоадер) для начала прошивки. На отладочной плате мини-брейкаут перезагрузить можно зажав сначала на 10 секунд кнопку питания до выключения светодиода и потом нажать ее на пару секунд пока он не мигнет. После 'того через десяток секунд начнется прошивка что вы увидите в консоле.

Из Windows

Если вы как и я собирали Yocto из VirtualBox то загрузится в бутлодер через проброс USB в VirtualBox наврядли получится - проброс весьма медленный и не удовлетворяет таймаут бутлоадера. По этому вам нужно просто заархивировать папку toFlash и скопировать на Windows:

/edibuild/edison-src/build$ zip -r yocto_custom_090416_1 toFlash/

Идиология названий архивов следующая - в имени мы используем дату создания архива и номер архива сегодня если за один день мы делали несколько попыток. Такой подход обезопасит нас от неправильных прошивок и позволит однозначно указать версию.

Потом нужно разархивровать архив на Windows и запустить из cmd скрипт flashall.bat.  Единственное что в разархивированный каталог нужно положить dfu-util.exe, вот. Дальнейшие действия такие же как и при прошивки из Linux.

Процедура прошивки в консоле выгядит примерно так:

>flashall.bat
Using U-boot target: edison-blankrndis
Now waiting for dfu device 8087:0a99
Please plug and reboot the board
Dfu device found
Flashing IFWI
Download        [=========================] 100%      4194304 bytes
Download done.
Download        [=========================] 100%      4194304 bytes
Download done.
Flashing U-Boot
Download        [=========================] 100%       245760 bytes
Download done.
Flashing U-Boot Environment
Download        [=========================] 100%        65536 bytes
Download done.
Flashing U-Boot Environment Backup
Download        [=========================] 100%        65536 bytes
Download done.
Rebooting to apply partiton changes
Dfu device found
Flashing boot partition (kernel)
Download        [=========================] 100%      5980160 bytes
Download done.
Flashing rootfs, (it can take up to 5 minutes... Please be patient)
Download        [=========================] 100%    536870912 bytes
Download done.
Rebooting
U-boot & Kernel System Flash Success...
Your board needs to reboot to complete the flashing procedure, please do not unp
lug it for 2 minutes.