LoginSignup
17
14

More than 1 year has passed since last update.

産業用堅牢ハードでElixir:e-RT3にNervesポーティング

Last updated at Posted at 2021-06-06

はじめに

タイトルがやったことのすべてを語っていますが、今回Nervesのポーティングにトライし、無事動作させることができました!

そこで、これからNervesポーティングのトライをする人のために、ポーティング作業のポイントをまとめてみました。

ターゲットマシン

ターゲットマシンは @myasu さんが記事を量産している
横河電機製の「リアルタイムOSコントローラ(e-RT3)」の「汎用OS対応CPUモジュール」です。

彼が

  • 「Nervesのポーティングができるんじゃないか💡」
  • 産業用堅牢ハードにNervesが載ったら💡」

とアイデアを持ってきてくれたことが、このハードがターゲットマシンとなったきっかけでした。

この「汎用OS対応CPUモジュール」は、なかなか尖っていてユーザーが走らせたいOSを自由に選定することができる機種です。そのため、OSがブートする仕様のドキュメントや、Linuxカーネルソースが提供されています。

ユーザーが走らせたいOSを自由に選定できるように仕様/ソースが開かれているので、今回のポーティングを成功させることができました。

※「汎用OS対応CPUモジュール」は長いので、本記事内では以降「e-RT3」とよびます。

ポーティングのアウトライン

Nervesのポーティング手順はnerves_system_brのREADMEに以下のようにまとめられています。

  1. Create a minimal Buildroot defconfig that boots and runs on the board. This doesn't use Nerves at all.
  2. If the defconfig requires a writable root filesystem, figure out how to make it read-only. This should be pretty easy unless you're using systemd. Since Nerves uses a custom init system, keep in mind for later that systemd may be helping initialize something on the board that will need to be done manually later.
  3. Take a look at the Flash memory layout and compare that to the layouts used in one of the supported systems. We use fwup to create images. There's a lot of variety in how one can lay out Flash memory and deal with things like failbacks. At this point, just see if you can get fwup to create an image.
  4. Clone one of the official systems that seems close for your board. Update the nerves_defconfig based on the Buildroot defconfig that works.
  5. Build the system using mix or manually by running the create-build.sh script.

私はこの順に作業を進めましたが、振り返ると、初めてLinuxのポーティングをする私がまずすべきは大枠の理解でした。

大枠というのは、「ターゲットマシンのブートする仕組み」です。
これが分かると、あとはBuildrootの使い方を勉強して、カーネルとdtbを作ることで、上記手順の2までを終わらすことができました。
手順3,4,5は、nerves_system_rpi3をベースとし改造を加えました(何をしたかを文字に起こすのが難しいところです)。

まずは、e-RT3のブートの仕組みを理解する

このモジュールは電源が投入されると内蔵ROM(?)にあるブートローダー、U-Bootを読み込み起動します。

そのU-BootはモジュールのSDスロット1, 2に挿さるSDにuEnv.txtが順にないか確認し、あればそれに従い動作します。※uEnv.txtはU-bootのスクリプトのようなものです。

提供されているUbuntuイメージにも当然uEnv.txtがあり、動作するリファレンスとしてとても役に立ちました。

uEnv.txtのポイント

uEnv.txtを使う際のポイントは、

  • カーネル、dtbがどこにあるか
    • これは作成するSDイメージの構成によって定まります
  • それらをRAMのどこ(のアドレス)に読み込ませるべきか
    • これはターゲットマシンの仕様で、e-RT3ではドキュメントに記載されていました
  • カーネルパラメータ(root=rootfsのデバイス等)をどうするか
    • これはUbuntuのuEnv.txtにあるパラメータを踏襲しつつ、改造します

です。

上記がわかると、uEnv.txtを使い、ターゲットマシンのRAMにカーネルとdtbを読み込ませて、カーネルパラメータを渡して、uBootのbootm/z コマンドでカーネルを起動させることができます。

次に、Buildrootを使って、カーネル, dtb, rootfsをつくる

ターゲットマシンの起動の仕組みが分かると、カーネルとdtb、ルートファイルシステムの作成が必要なことがわかります。これらはLinuxのカーネルソースをダウンロードして、コンフィギュレートしてコンパイルすることで作成可能ですが、NervesではBuildrootを使ってこれを行います。

Buildrootは組み込み向けのLinuxシステム(カーネル、dtb、rootfs)を構成するためのツールです。

Linuxのカーネルソースで使うmake menuconfigが、Buildrootにもあり(Buildroot用にラップされています)、コンフィギュレートすることができます。

Buildrootはコンフィギュレーションに応じ、必要なものをダウンロードしホストマシンでクロスコンパイルを行います。必要なものというのは、例えば、

  • 指定したバージョンのLinuxカーネルソース
  • カーネルのパッチ(リアルタイムパッチ等)
  • クロスコンパイラ(ターゲットマシン用バイナリを作成するコンパイラ)
  • イメージ作成のためのfwup

などです。これにより、Buildrootに登録されているboardであれば、コンフィギュレーションのみでlinuxシステムを構成できます。

e-RT3はBuildrootのboardには登録されていないので、該当する設定を作成してやる必要があります。

e-RT3 Linuxカーネルソースの調査とカーネル類の生成

提供されているカーネルソースを調査すると、それが以下のように構成されているだろうとわかりました。

image.png

※e-RT3はザイリンクスのZynq-7000を採用しており、ザイリンクスのlinux-xlnxのコードが部分的に適用されていそうでした。

下段2つはBuildrootをコンフィギュレートすることで、ダウンロードさせることができます。
なので、カバーできない上段2つをパッチとして用意できれば、e-RT3の機能をカバーできるカーネルを作れます。
aufsパッチはNervesには不要のため、無視しました。

そこで、上図の下段3つで構成されるカーネルソースを作り、それと提供されているカーネルソースの差分から上段2段の合成パッチを作ることで、最終的なカーネルソースが下図となるようにしました。

image.png

合成パッチを作成したら、Buildrootのリファレンスに従いboardディレクトリに必要な設定ファイルを作成し、makeするとカーネル類が生成できます。(詳細は割愛
※BR2_ROOTFS_POST_IMAGE_SCRIPTを使い、SDに焼けるimg, fwを作成できるようにすると大変楽ができます。

リファレンスは、 https://buildroot.org/docs.html からアクセスできる以下の2つを参考しました。
どちらも分かりやすい素晴らしいドキュメントです。

このとき作成したe-RT3向けのbr2-externalはここに公開しています。

作成したカーネルの起動確認

作成したイメージ(buildroot-dir/output/images/f3rp70.img)をSDに焼いて、

image.png

シリアルをつないで、電源を投入すればBuildrootで作成したミニマルなLinuxが起動できます。

image.png

最後に、Nervesになるように合わせ込む

何をしたか記載するのが難しいですが、
今回作成したnerves_system_f3rp70nerves_system_rpi3をベースに作成しました。
両者のdiffを見てもらうことで何を変更したか確認いただけると思います。

※あわせこみでは、Buildroot用のdefconfigをnerves_system_f3rp70のnerves_defconfigにリネームしています。

Nervesの起動確認

プロジェクトを作って動作させれば、yey!!

image.png

Nervesがポーティングできたら

Nervesになってしまえば、

  • Elixirの強みである、並行処理、プロセス監視復旧機能がフルに
  • Elixirで作られているライブラリを存分に

に使えます。例えば、

  • 通常のLinux環境でsystemdやshellスクリプトで行っていたデーモンの監視復旧はElixirだけで作成する
  • Nginx, ApacheはElixirのPhoenixで代用する

ことができます。そして、設定ファイルが/etcに散ることもないです。

これらは純粋にNervesの強みです。

※私がNervesを一押しする理由は「なぜ僕はNervesに期待するのか」に書いています。

※追記:hex.pmに公開しました→ https://hex.pm/packages/nerves_system_f3rp70

e-RT3固有の対応が必要なところ

e-RT3のIOはメーカー固有のlibm3.soを介して叩く必要が有ります。

たとえば、DIOはGPIOでないので、circuits_gpioは使えません。なので、@myasu さんがリアルタイムOSコントローラ e-RT3 (Elixirから制御編)でやられているようにNIFsを介する必要が有ります。

circuits_gpioのようなライブラリを作成するのがよさそうです。

まとめ

  • 横河電機製の産業用堅牢ハード, e-RT3(F3RP70)
  • 組み込みLinuxの開発体験ゲームチェンジャーであるNerves をポーティングできました🎉

今回の経験により、以下が押さえられれば、単純なポーティングならばできるだろうという自信が持てました。

  • ブートの仕様が分かる
  • 動作するカーネルソース(dtsを含む)がある

※本取り組みの動機などはFA設備技術勉強会 in ROBOMECHで、ラダーを使わないコントローラというタイトルで発表を行っています。こちらもぜひご覧いただけると嬉しいです。

謝辞

  • ポーティングのきっかけを作った @myasu さん
  • 開かれたハードを提供されている 横河電機 さん
  • 僕らの味方 Nerves

に感謝します。Thank you!!

17
14
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
14