RaspberryPi 3 model B+にXenomaiを導入する手順 その１

#概要
今回とある事情でリアルタイムカーネルの処理能力について調べる必要が出てきたので、RaspberryPi3にリアルタイムKernelであるXenomaiを導入した。
その時にXenomaiの公式フォーラム通りに作業したのに全然うまくいかず苦戦しまくったので、導入方法についてまとめた。
Xenomai導入について日本語の記事が極端に少なく、海外の投稿をみないと結構難しい(英語読めない人だときつい)
これから同じことしたい人の道しるべにもなればいいかなって思ったり？
（ちなみこれがQiita初投稿）

#注意事項
2020年時点での導入方法だよ！使う環境次第でうまくいかない可能性がある。
*RPi4でこれと同じ手法でやるとうまくいかないらしい。

#目次
- Xenomaiって何?
- 作業環境
- 作業内容

#Xenomaiって何？
- リアルタイムオペレーティングシステムを実現させる際に、Kernelにリアルタイム処理能力を持たせるためのパッチとそのライブラリ群を指す。
- Linuxベースで作られてるのでLinuxOSにしか適用できない
- Xenomaiを導入するとリアルタイム性を実現するいろいろなAPIを使用できるようになる。
- 詳しくは下記に書いてある

###XenomaiのGitlab(wiki)
[https://gitlab.denx.de/Xenomai/xenomai/-/wikis/home](https://gitlab.denx.de/Xenomai/xenomai/-/wikis/home)

#作業環境
- RaspberryPi3 model B+
    - CPU:Broadcom BCM2837B0,ARMv8(Cortex-A53)
    - メモリ:1G
    - OS: Raspbian 64bit
    - kernel: Linux For Raspbian 4.19.xx(自分の環境では4.19.66)
- Linux環境が入ったPC(64bit環境なら何でもいいと思う)
    - 自分の環境ではWindows10にWindows Subsystem for Linux(WSL)を入れてUbuntu 18.04の環境を使用した
- ネット接続環境

Linux環境が入ったPCはなくてもできるが、その場合RPiでKernelをセルフコンパイルすることになるので、結構な時間がかかるのを覚悟

主に作業は二段階あって、１段階目はXenomaiが使えるようにKernelを構築する。２段階目はXenomai本体をビルドしてXenomaiのライブラリ等を使えるようにする。今回は１段階目を説明する。

#作業内容（kernel 準備編）
今回はセルフコンパイルとクロスコンパイル両方試したが、クロスコンパイルで試した方法を記載する（気が向いたらセルフコンパイル方法も書くかも）
###準備1
今回はLinuxカーネル4.19.xxx(xxxはその時のstableのサブレベル)
Linux環境でターミナルを起動し、自分のhomeディレクトリ下でコンパイルとか
ダウンロードしたものをまとめておく用のディレクトリを作る

```
linux_user@TN-201709F100R:~$ mkdir /kernel_cnst/
linux_user@TN-201709F100R:~$ cd ./kernel_cnst/
```
GithubからRaspberryPi向けのノーマルLinuxカーネルを引っ張ってくる。
(gitのURLから直接DLもできるけど、git使えたほうがいいので、gitコマンドをapt-getなりyumなりで導入しておく)

```
linux_user@TN-201709F100R:~$ git clone https://github.com/raspberrypi/linux -b rpi-4.19.y
```

実行するとgitのリポジトリからlinuxカーネルのソースのダウンロードが開始される。終わったら"linux"なるディレクトリが生成されるので

```
linux_user@TN-201709F100R:~$ cd ./linux/
linux_user@TN-201709F100R:~$ head -4 Makefile
```

で、落としてきたソースのversionをチェック。私が実行した環境では、

```
# SPDX-License-Identifier: GPL-2.0
VERSION = 4
PATCHLEVEL = 19
SUBLEVEL = 127
```
で、これが作業当時のStable版。(もし-bオプションで何も指定しないと、その作業時でのStable版がダウンロードされる。)

###準備2
次に、以下からXenomaiのソースやらパッチをwgetとかで引っ張ってくる。

Xenomai本体:http://xenomai.org/downloads/xenomai/stable/
XenomaiのiPipeパッチ:https://xenomai.org/downloads/ipipe/v4.x/arm/

※1: 導入時点ではXenomaiはVer3.1を使用。KernelのStable版を使う場合は必ず最新版のXenomaiを使うことを推奨
※2: iPipeのパッチはXenomaiのVersionではなく"Linux Kernel"のVersionに依存なのでkernelに合わせて選択すること
※3: armとはRPiにも使われているCPU規格のこと。詳しくはggったほうが早いよ！

これらを落としたら必ず作業ディレクトリ下に配置しておくこと。
（私の環境では上の通りkernel_cnst）

###準備3(セルフコンパイルするときはいらない)
セルフコンパイルならlinux標準のコンパイラがあればいいので必要ないけど、
クロスコンパイルする場合は必要になるので、以下を実行

```
linux_user@TN-201709F100R:~$ cd ~/kernel_cnst/
linux_user@TN-201709F100R:~$ git clone https://github.com/raspberrypi/tools
```

#作業内容(kernelコンパイル)
さあ、ゲームをはじめよう......

すんません。こっから実際にXenomaiカーネルをビルド導入していこう。
このkernelビルドにかかわらず、linux上でコマンド作業するときは必ずログを取るように！（あとで何で失敗したかわからなくなる）

今落としてきたファイルはすべてkernel_cnstディレクトリ下に置かれてるはず。


Xenomaiの機能を使用するためには、カーネルの機能を拡張しなければいけない。
今のディレクトリ構成はこんな感じ

```
~/kernel_cnst/
  →/Xenomai3.x/ *xenomai source
  →/linux/ *kernel source
  →/ipipe_patch_xxx.patch *ipipe_patch
  →/tools/  *cross compile tool set
```

まずはiPipeの機能をカーネルに持たせるために、カーネル自体にパッチ当てる
ipipe自体は自分でディレクトリ作ってその中に入れてもOK


```
linux_user@TN-201709F100R:~$ cd ~/kernel_cnst/
linux_user@TN-201709F100R:~$ cd ./linux/
linux_user@TN-201709F100R:~$ ../Xenomai3.x/scripts/prepare-kernel.sh --linux=./ --arch=arm --ipipe=../ipipe_patch_xxx.patch --verbose
```

最初の難関。
ここで"Build system ready"となったら問題なくパッチが当たっている。"unable patch ~~~~"とかでたら失敗してる。問題はlinuxカーネルのversionとipipeのパッチのversionがあっていないから(wikiにはSublevelは異なっていても大丈夫とか書いてるけど大丈夫じゃなかった)
なので、この場合linuxのversionに合わせてパッチ内容を修正する必要がある
(patch修正についてはほか記事にする予定)

Patchが当たったら、あとはLinuxカーネルをビルドしていく。

```
linux_user@TN-201709F100R:~$ cd ~/kernel_cnst/linux/
linux_user@TN-201709F100R:~$ export CROSS_COMPILE=../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-
linux_user@TN-201709F100R:~$ export KERNEL=kernel7
```

KERNELの環境変数設定するときにPRi4の場合は"kernel7"じゃないので注意。

```
linux_user@TN-201709F100R:~$ make bcm2709_defconfig
linux_user@TN-201709F100R:~$ make menuconfig
```

もしmenuconfigを実行したときに、そんなものはないと言われたら以下を実行しておこう

```
linux_user@TN-201709F100R:~$ sudo apt-get install build-essential libncurses5-dev
```

menuconfigが開いたら以下のようにパラメータを設定([]は設定解除、[x]設定にチェックを入れる)

```
CPU Power Management → CPU Frequency scaling → CPU Frequency scaling　[ ]
Kernel Features → Contiguous Memory Allocator [ ]
Kernel Features → Allow for memory compaction [ ]
Kernel Hacking → KGDB: kernel debugger [ ]
Kernel Features → Time Frequency → 1000Hz
```
これで、makeのためのconfig設定が終わりいよいよビルド

```
linux_user@TN-201709F100R:~$ mkdir ~/xenomai_kernel_build/
linux_user@TN-201709F100R:~$ export INSTALL_MOD_PATH={上で作ったディレクトリ}
linux_user@TN-201709F100R:~$ export INSTALL_DTBS_PATH={上で指定したディレクトリと同じでよい}
linux_user@TN-201709F100R:~$ make –j□ zImage modules dtbs (□には使いたいコア数を入れる)
linux_user@TN-201709F100R:~$ $ make –j□ modules_install 
linux_user@TN-201709F100R:~$ make –j□ dtbs_install(これで設定用のdtbファイルが出来上がるがものはmake zImageのところで生成されたものと同じはず)
```
今のマシンで4コア以下の性能のCPUを使ってるものはないと思うので4でいいと思う。
無事にビルドできたら、以下を実行

```
linux_user@TN-201709F100R:~$ mkdir $INSTALL_MOD_PATH/boot/
linux_user@TN-201709F100R:~$ ./scripts/mkknlimg ./arch/arm/boot/zImage $INSTALL_MOD_PATH/boot/kernel7.img
```
これで、ImageファイルとかKernelをインストールするのに必要なファイル群が
$INSTALL_MOD_PATHに生成されるので、これを圧縮し、USBとかでRPiに持ってくる

```
tar -zcvf kernel_pack.tgz $INSTALL_MOD_PATH
```

###以下PaspberryPiでの作業
持ってきた圧縮ファイルを適当なところに解凍。
RPiのカーネルはソースをビルドして生成されたImageファイルと/boot/下にすでにあるものと置き換えることでKernelの組み換えができる。
<font color="Red">以降の作業を行う前に必ず置き換えるファイルすべてバックアップを取っておくこと</font>
これをやらないと最悪RPiが二度と起動しなくなる。(実際に起動しなくなった)

####バックアップ作業
```
linux_user@TN-201709F100R:~$ sudo mkdir /boot/boot_org/
linux_user@TN-201709F100R:~$ sudo cp  -rd /boot/* /boot/boot_org
linux_user@TN-201709F100R:~$ sudo cp –rd /lib/ /lib_backup/
```

いよいよ新しいカーネルをRPiにインストール

```
linux_user@TN-201709F100R:~$ sudo cp {解凍した$INSTALL_MOD_PATH}/kernel7.img /boot/
linux_user@TN-201709F100R:~$ sudo cp ./arch/arm/boot/dts/*.dtb /boot/
linux_user@TN-201709F100R:~$ sudo cp ./arch/arm/boot/dts/overlays/* /boot/overlays
linux_user@TN-201709F100R:~$ cd {解凍した$INSTALL_MOD_PATH}
linux_user@TN-201709F100R:~$ cp –rd ./* /lib/
```
あとはbootコンフィグを編集

```
linux_user@TN-201709F100R:~$ sudo vi /boot/config.txt
```
以下の2行を追加

```
Kernel=kernel7.img
device_tree= bcm2710-rpi-3-b-plus.dtb
```
再起動するまでは新しく入れたkernelは反映されないので、再起動する前に以下を実行して現在kernelのVersionを確認（本当にkernelの置換ができているかを確認するため）

```
linux_user@TN-201709F100R:~$ uname -a
linux_user@TN-201709F100R:~$ Linux 4.19.xxx
```

確認したらRPiを再起動

```
linux_user@TN-201709F100R:~$ sudo reboot
```

この後正常に起動したらターミナルを立ち上げてkernelのversionを確認

```
linux_user@TN-201709F100R:~$ uname -a
linux_user@TN-201709F100R:~$ Linux 4.19.yyy(今回の作業で入れたkernelのversion)
```
となっていたら、OK。
これでひとまずXenomai用のKernel構築は完了となる。
今回の作業で私が参考にした記事は以下

###参考文献
https://lemariva.com/blog/2018/07/raspberry-pi-xenomai-patching-tutorial-for-kernel-4-14-y

次はXenomai本体のビルドだが、長くなるのでその２へ続く。