yocto(2.6 Thud)でRaspberry-pi Zero W  - Step1 - 最小イメージをビルドしてみた

# はじめに
組み込みの勉強のため、yoctoでRaspberry-pi Zero WのOSイメージをビルドしてみました。
今回はOS起動からwlanの接続までを目標に進めます。

# 方法1 : meta-raspberrypi によるビルド
yocto Projectで提供されているmeta-raspberrypiを用いてビルドした

## 参考サイト
- Raspberry Pi Zero W向けにYoctoをカスタマイズする | ニフティものづくりブログ https://blog.web.nifty.com/engineer/1040
- ラズベリーパイゼロでyocto - メモ http://mickey-happygolucky.hatenablog.com/entry/2017/04/11/015101

## ビルド準備
yoctoビルドに必要なパッケージをインストールやpoky/recipeの取得
### パッケージインストール
yoctoビルドに必要なパッケージをインストール

```bash
sudo apt -y install build-essential chrpath diffstat gawk git libncurses5-dev pkg-config subversion texi2html texinfo python2.7 bc
```
pythonのシンボリックリンクを貼る

```bash
sudo ln -sf /usr/bin/python2.7 /usr/bin/python
```

### poky/各種recipeを取得
gitで取得する

```bash
cd ~
git clone -b thud git://git.yoctoproject.org/poky.git poky-thud
cd ~/poky-thud
git clone -b thud git://git.yoctoproject.org/meta-raspberrypi
git clone -b thud clone git://git.openembedded.org/meta-openembedded
```

###ビルド用ディレクトリの設定
ビルドの作業ディレクトリを設定する。pokyのoe-init-build-envを用いて環境変数の設定も行う
(oe-init-build-envで、bitbakeのpathも通るのでビルドする際は毎回実行が必要)

```bash
mkdir -p ~/rasp/build/conf
oe-init-build-env ~/rasp/build
```

## ビルド用コンフィグファイル
local.conf , bblayers.confによりビルドオプション、ビルド対象を記載
(github: https://github.com/extdada/yocto_raspberrypi_zero)

### bblayers.confの記載

bblayers.confでレシピレイヤの指定を行う。

```:~/rasp/build/conf/bblayers.conf
POKY_BBLAYERS_CONF_VERSION = "2"
 
BBPATH = "${TOPDIR}"
BBFILES ?= ""
 
BBLAYERS ?= " \
  ${HOME}/poky-thud/meta \
  ${HOME}/poky-thud/meta-poky \
  ${HOME}/poky-thud/meta-yocto-bsp \
  ${HOME}/poky-thud/meta-openembedded/meta-oe \
  ${HOME}/poky-thud/meta-openembedded/meta-networking \
  ${HOME}/poky-thud/meta-openembedded/meta-python \
  ${HOME}/poky-thud/meta-raspberrypi \
  "
```

### local.confの編集

local.confで各種設定を行う。主要設定の詳細のみ以下に記載

- MACHINE : meta-raspberrypiで定義された機器ごとの設定を引き出す
    - raspberrypi0-wifi : raspberry-pi zero w
- DISTRO : ディストリビューション定義
    - poky : yoctoのディストリビューション
- DISTRO_FEATURES_append : ディストリビューションの追加を行う
    - bluez5 : Bluetooth Stack
- COMBINED_FEATURES_append : MACHINE_FEATURES_append/DISTRO_FEATURES_appendの同時設定
    - wifi : wifi関連のデバイスドライバ
    - bluetooth : bluetooth関連のデバイスドライバ
- BB_DISKMON_DIRS : yoctoビルドにおけるディレクトリ容量制限
- BB_NUMBER_THREADS : 並列実行スレッド数
- PARALLEL_MAKE : gccの並列実行オプション、BB_NUMBER_THREADSに近い
- IMAGE_INSTALL_append : インストールパッケージの追加
    - linux-firmware-bcm42420 : Broadcomのfirmware?(80211cfg関連)
    - connmam : systemd用のnetwork configurationツール
    - pulseaudio : オーディオ制御
- INHERIT_append = " extrausers" : user追加設定 (以下を参照)
- DISTRO_FEATURES_append += "systemd" : systemd設定(以下を参照)

```:~/rasp/build/conf/local.conf
MACHINE ??= "raspberrypi0-wifi"

DISTRO ?= "poky"

# raspberri pi default
DISTRO_FEATURES_append = " bluez5"
COMBINED_FEATURES_append = " wifi bluetooth alsa ext2 usbgadget usbhost"

PACKAGE_CLASSES ?= "package_rpm"
EXTRA_IMAGE_FEATURES ?= "debug-tweaks"

USER_CLASSES ?= "buildstats image-mklibs image-prelink"
PATCHRESOLVE = "noop"

BB_DISKMON_DIRS ??= "\
    STOPTASKS,${TMPDIR},1G,100K \
    STOPTASKS,${DL_DIR},1G,100K \
    STOPTASKS,${SSTATE_DIR},1G,100K \
    STOPTASKS,/tmp,100M,100K \
    ABORT,${TMPDIR},100M,1K \
    ABORT,${DL_DIR},100M,1K \
    ABORT,${SSTATE_DIR},100M,1K \
    ABORT,/tmp,10M,1K"

PACKAGECONFIG_append_pn-qemu-native = " sdl"
PACKAGECONFIG_append_pn-nativesdk-qemu = " sdl"

# core
BB_NUMBER_THREADS = "12"
PARALLEL_MAKE = "-j 12"

CONF_VERSION = "1"
IMAGE_INSTALL_append = " linux-firmware-bcm43430 connman connman-client pulseaudio pulseaudio-server usbutils sudo wiringpi"
IMAGE_FEATURES_append = " ssh-server-dropbear"

# user setting
INHERIT_append = " extrausers"
EXTRA_USERS_PARAMS = "useradd -P devuser devuser; usermod -P root root;"

# use systemd
DISTRO_FEATURES_append += " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_initscripts = ""
IMX_DEFAULT_DISTRO_FEATURES_append = " systemd"
```

## イメージビルド
設定が完了したのでビルドする

### ビルド実行
実行ホスト側の性能によるが、2～3時間かかる

```bash
cd ~/rasp/build
bitbake rpi-hwup-image
```

### イメージ生成
下記のディレクトリにイメージが生成される。これを書き込む

```bash 
cd ~/rpi/build/tmp/deploy/images/raspberrypi0-wifi/
ls rpi-hwup-image-*
rpi-hwup-image-raspberrypi0-wifi-20190318120523.rootfs.rpi-sdimg
```

## 一応起動するがwlan0が認識されない

SDに上記イメージを書き込むと起動したが、wlan0が認識されない

```bash
$ ifconfig -a
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:1 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
```

lsmodでもデバイス認識されていない

```bash
$ lsmod | grep cfg80211
$ 
```

rfkillのリストも何もない

```bash
$ rfkill list all
$
```

以下の対応したが特に変化なし。

- IMAGE_INSTALL_appendにlinux-firmwareを追加
- poky/openembedded/meta-raspberrypiのbranchをrocko(2.5)に変更

~~(何か知見のある方アドバイスいただけたら幸いです)~~

### 2019/04/05追記

@shino_r 氏より以下のコメントをいただきました
> 方法1でwlan0が使えないのはthudでファーム名称が変わったためと思います。
私の環境ではlinux-firmware-rpidistro-bcm43430でwlan0が動いていますよ。

そのため、IMAGE_INSTALL_appendを修正

```
#IMAGE_INSTALL_append = " linux-firmware-bcm43430 connman connman-client pulseaudio pulseaudio-server usbutils sudo wiringpi"
IMAGE_INSTALL_append = " linux-firmware-rpidistro-bcm43430 usbutils sudo wiringpi wpa-supplicant"
```

上記でビルドしたところ、wlan0認識しました

はじめは存在しませんが、```/etc/network/interfaces```と```/etc/wpa_supplicant.conf```を記載した上で
```ifup wlan0```を実行すると正常に認識、IPアドレス取得できました

```:/etc/network/interfaces
auto lo
iface lo inet loopback

auto wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant.conf
```

```:/etc/wpa_supplicant.conf
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=0
network={
    ssid="hoge"
    psk="hogehoge"
    key_mgmt=WPA-PSK
    proto=RSN
    pairwise=CCMP
    group=CCMP
}
```

ありがとうございました


# 方法2: meta-rpiレイヤを使用する

上記方法でwlan0が認識しないため、別の方法で対応
Jumpnow Technologiesで提供されいているmeta-rpiを利用してビルドする

## 参考サイト

- Building Raspberry Pi Systems with Yocto  https://jumpnowtek.com/rpi/Raspberry-Pi-Systems-with-Yocto.html

## ビルド準備

必要なパッケージに差分はありません

### poky/recipe等の取得

```bash
cd ~
git clone -b thud git://git.yoctoproject.org/poky.git poky-thud
cd ~/poky-thud
git clone -b thud git://git.yoctoproject.org/meta-raspberrypi
git clone -b thud clone git://git.openembedded.org/meta-openembedded
git clone -b thud https://github.com/meta-qt5/meta-qt5
mkdir -p ~/rpi
cd ~/rpi
git clone -b thud git://github.com/jumpnow/meta-rpi
```

###ビルド用ディレクトリの設定
ビルドの作業ディレクトリを設定する。pokyのoe-init-build-envを用いて環境変数の設定も行う
(oe-init-build-envで、bitbakeのpathも通るのでビルドする際は毎回実行が必要)

```bash
mkdir -p ~/rpi/build/conf
oe-init-build-env ~/rpi/build
```

## ビルド用コンフィグファイル

### サンプルファイルのコピー

meta-rpiにサンプルが存在するので、そちらを利用する

```bash
cd ~/rpi
cp meta-rpi/conf/local.conf.sample build/conf/local.conf
cp meta-rpi/conf/bblayers.conf.sample build/conf/bblayers.conf
```

サンプルのbblayers.confのレイヤディレクトリ指定は以下の通りなので、上記設定をしていれば問題ない

- ~/poky-thud : poky, meta-openembedded, meta-qt5, meta-raspberrypi
- ~/rpi : meta-rpi

### local.confの修正

以下の項目を修正する

- MACHINE : raspberrypi0-wifi
- EXTRA_USERS_PARAMS : 任意のユーザ名。パスワードに変更

## ビルド実行

meta-rpiではconsole-imageがイメージとなる。

```bash
cd ~/rpi/build
bitbake console-image
```

## SDカードへの書き込み

meta-rpiに対してSDカードへの書き込みスクリプトも用意されている。

### パーティション分割

```bash
cd ~/rpi/meta-rpi/scripts
sudo ./mk2parts.sh sdb
```

### ネットワークの設定

スクリプト側でwpa_supplicant.confのコピーを行う処理があるため、指定の場所に配置すると自動配置される。

```bash
cp interfaces-example interfaces
cp wpa_supplicant.conf-sample wpa_supplicant.conf
```

```bash:wpa_supplicant.conf
country=JP
ctrl_interface=/var/run/wpa_supplicant
ap_scan=1

network={
    key_mgmt=WPA-PSK
    ssid="<ssid>"
    psk="<pass>"
}
```

### SDカードへの書き込み

作業用ディレクトリの作成や環境変数の設定を行い、書き込み用スクリプトを実行する

```bash
sudo mkdir /media/card
export OETMP=~/rpi/build/tmp
export MACHINE=raspberrypi0-wifi
./copy_boot.sh sdb
./copy_rootfs.sh sdb console
```

## 起動

wlan0が認識された！
とりあえずスタンドアローン状態から開放されたので今回はここまで

# 今後の展望

- SSH設定
    - open-sshを追加する
- LTEのUSBドングルを認識させる
- meta-raspberrypiのみでビルドするとwlan0が認識される理由を調査
    - 差分を見て判断するしかない…？
- meta-rpiでインストールされるパッケージを削減する
    - まずQt5は外したい