Zephyr RTOS 〜 ターゲット毎の設定や選定基準 〜

# 1. はじめに

この記事では、ターゲット毎の個別設定や選定基準などについて触れていきます。

背景として、ボード毎に flash や debug の設定や推奨ツールが指定されていますが、環境やツールのバージョンによってはうまく動かないケースもあり、その解消方法のヒントの共有を目的としています。

また、Zephyr は非常に多くのボードをサポートしていますが、実際にどんな規模やターゲットが Zephyr 採用に適しているのか、実例を交えて紹介していきたいと思います。

なお、記事中に出てくる Playbook リポジトリはこちらに公開しておりますので、ご興味ある方ご覧いただければと思います。

https://github.com/Corgeek/ZephyrOpsPlaybook

# 2. west flash / west debug の挙動

基本的には Zephyr 公式のメタツールである west コマンドを経由して flash や debug を行うのですが、実際の処理は openocd / pyocd や jlink, stm32cubeprogrammer など多種多様なツールに処理が渡されます。

## 2.1. ある程度採用するボードが決まっている場合

それぞれのツールは、ボード毎に適した個別設定がされているのが通例で、非常に数多くのボードを提供しているからこそ、同じベンダーでも新旧で異なるツールが必要だったりと、その見極めが必要になってきます。

実際の個別設定の配置例(Nucleo F401RE)

```
└── zephyr/                                   # 公式の Zephyr リポジトリ
    └── boards/                               # boards 依存の処理
        ├── st/                               # ベンダー名: STM
        │   ├── nucleo_f401re/                # ボード名: Nucleo F401RE
        │   │   ├── nucleo_f401re.dts         # Nucleo F401RE 用 DTS
        │   │   └── support                   # 個別の Runner 設定
        │   │       └── openocd.cfg           # openocd 向けの設定
```

そのため、ターゲットが決まっている場合は、下記からボードの個別情報を検索し、その中の **Programming and Debugging** には必ず目を通すようにしてください。

https://docs.zephyrproject.org/latest/boards/index.html

## 2.2. 様々なボードで運用を想定している場合

一方で、様々なボードで試したい場合は、あらかじめそれぞれのツールをインストールしておくのが手堅い方法だと感じています。

下記に代表的なツールのインストール方法を羅列しておきます。

| ツール | 方法 | 補足 |
|---|---|---
| openocd | (Windows) `choco install openocd`<br>(Ubuntuは不要) | 最新ソースからのコンパイルなら尚良 |
| pyocd | pyocd pack --install (ターゲット) | `.venv/bin/activate` 後に実施<br> `pyocd pack --find stm32f4` などで検索 |
| jlink | ダウンロード＆インストール | [SEGGER 公式](https://www.segger.com/downloads/jlink) |
| stm32cubeprogrammer | ダウンロード＆インストール | [STM 公式サイト](https://www.st.com/ja/development-tools/stm32cubeprog.html) <br> ※ただし flash 機能のみ |

# 3. Playbook 側での各ターゲット毎の設定

ZephyrOpsPlaybook では、実際に各ボードで動作が確認できたものを下記で管理しており、`scripts/setup.bat`  / `scripts/setup.sh` を実行することでそれらを指定できるようにしています。
(未登録・空定義の場合は、ボードが標準指定しているツールを採用します)

```json:scripts/support/runner.json
{
    "flash": {
        "bbc_microbit": "--runner openocd",
        "bbc_microbit_v2": "--runner openocd",
        "rpi_pico": "--runner openocd",
        "nucleo_f030r8": "--runner openocd",
        "nucleo_f401re": "--runner openocd",
        "nucleo_l552ze_q": "--runner openocd"
    },
    "debug": {
        "bbc_microbit": "--runner openocd",
        "bbc_microbit_v2": "--runner openocd",
        "rpi_pico": "--runner openocd",
        "nucleo_f030r8": "--runner openocd",
        "nucleo_f401re": "--runner openocd",
        "nucleo_l552ze_q": "--runner openocd"
    },
}
```

例えば、BOARD_TYPE=nucleo_f401re を登録した後 setup を実行すると、以下のように `west flash` 用の runner と `west debug` 用の runner を変数として書き出し、
`scripts/build.bat` `scripts/debug.bat` 実行時にそれらを引用するようにしています。

```bash:west_env.bat
BOARD_TYPE=nucleo_f401re
RUNNER_FLASH="--runner openocd"
RUNNER_DEBUG="--runner openocd"
```

```bash:scripts/build.bat
if [ ${?} = 0 ] && [ "${FLASH}" = "TRUE" ]; then
	west flash ${RUNNER_FLASH}
fi
```

```bash:scripts/debug.bat
west debugserver ${RUNNER_DEBUG}
```

# 4. Zephyr 採用例の紹介

ここでは、公開されている情報から採用例を確認していきます。
ボード単位で紹介するとキリがないのですが、他にも紹介して欲しい等ありましたら、
私も知りたいのでぜひコメントをいただけると幸いです。

## 4.1. SC-Sat1 用のフライトソフトウェア

Space Cubics 社が開発した宇宙機器に必要な高い信頼性を持つボード「SC-Sat1」向けのソフトウェア

https://github.com/spacecubics/scsat1-fsw

## 4.2. Chromebook の embedded controller

Chromebook のキーボード入力やバッテリー管理、ファンや各種ポートの制御など、
各メーカー固有機能などを制御するためのマイコンにも採用されています。

**ボード毎の処理**

https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/chip/

また、類似の役割として下記リポジトリも存在します。

https://github.com/intel/ecfw-zephyr

## 4.3. Nordic 社の公式開発環境

無線通信機器、特に BLE(Bluetooth Low Energy) では世界シェア4割(出荷数6割)を占めている Nordic が、公式開発環境に Zephyr を取り入れいています。
(Zephyr 本体の開発にも相当力を入れています)

https://developer.nordicsemi.com/nRF_Connect_SDK/doc/v1.7-branch/matter/nrfconnect_platform_overview.html

なお、CortexM0/M0+ を採用した nrf51 系も一部 Zephyr がサポートしていますが、
ほとんどの SoC は BLE を利用できるほど RAM に余裕がなく、ペアリングができる程度なのでご注意を。

## 4.4. 株式会社フォトシンスのIoT機器

ブログや採用情報から Zephyr を採用しているのが伺えます。

https://akerun.hateblo.jp/entry/2019/12/06/164004


# 5. 筆者の実績を踏まえた導入対象の傾向

筆者も業務で Zephyr を採用した製品開発に携わったことがあり、それらを基にRTOSが採用されている性能や規模についても紹介したいと思います。

## 5.1. 筆者が携わったプロダクト紹介

下記は、筆者が携わった主要なプロダクトの MCU 性能と採用 OS です。

![実績と対象の領域.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38092/dde88b82-01af-5ec4-75fe-af39cc049874.png)

また、年代や開発規模(エレキやメカなどは含めずソフトのみ)も掲示しておきます。<br>(※古い＝若い頃の情報精度はやや低め)

| 年代 | 規模 | OS | MCU | カテゴリ |
|---|---|---|---|---|
| 2009年頃 | 300人月 | μITron | 400MHz(SH4A) | 量産・車載(カーナビ) |
| 2011年頃 | 30人月 | Android | 1GHz(CortexA9) | 試作・車載(カーナビ) |
| 2012年頃 | 500人月 | Linux | 800MHz(CortexA8) | 量産・車載(カーナビ) |
| 2014年頃 | 400人月 | Linux | 1GHz(CortexA9) | 量産・車載(カーナビ) |
| 2016年頃 | 100人月 | Linux | 800MHz(CortexA9) | 量産・民生(オーディオ) |
| 2018年頃 | 10人月 | mbed | 50MHz(CortexM0) | 試作・民生<br>(スマートネックスピーカー) |
| 2020年頃 | 50人月 | Zephyr | 180MHz/64MHz<br>(CortexM4F) | 量産・医療<br>(パワードスーツ系) |
| 2023年頃 | 20人月 | Zephyr | 96MHz(CortexM4) | 量産・民生(PC系) |

## 5.2. Zephyr を採用するプロダクト規模

これらの実績からも、Zephyr 採用に適しているのは「CortexM4 〜 CortexR 系 の領域で、多機能を求められながらも汎用OSを載せられない中間的な規模」だと捉えています。

また「大は小を兼ねる」とは言いますが、小(CortexM0/M0+相当)だとメモリが足りずに Zephyr の機能を活かしきれない事が多く、せいぜい「大は中を兼ねる」でしょうか。
(rpi_pico は例外的に RAM が多いですが)

実際に一部のボードでは、RAM 不足を理由に GPIO 利用に制限をかけていたりします。

```: nucleo_f030r8, nucleo_f031k6, stm32f0_disco, nucleo_l053r8, stm32f030_demo
/* Due to limited available memory, don't enable gpiod and gpiof */
/* (Test cases fail due to 'SRAM' region overflow) */
&gpiod {status = "disabled";};
&gpiof {status = "disabled";};
```

とはいえ、RAM の少なさや機能制限を理解した上で運用すれば、非常に移植性が高く多機能なOSを採用するメリットは高く、Cortex M0/M0+ 系利用の場合でも一考の余地はあると考えています。

## 5.3 Zephyr の品質に対する取り組み

その他、Zephyr の取り組みとして下記も紹介しておきます。

* ISO26262 を含む各業界に合わせた取り組み

https://docs.zephyrproject.org/latest/safety/safety_overview.html

* Zephyr のコーディングルールに一部 MISRA C を採用

https://docs.zephyrproject.org/latest/contribute/coding_guidelines/index.html

* Coverity (静的解析ツール)による定期的な解析

https://scan.coverity.com/projects/zephyr

# 6. まとめ

ターゲット毎の設定の紹介や選定基準について、実績を交えながら紹介してみました。
これらが Zephyr 採用判断の際のヒントになると幸いです。

なお、私の Qiita 一連の記事で案内している ZephyrOpsPlaybook リポジトリは、筆者の量産・車載での経験が源流にあり、設計思想もここに準拠しています。
(現在は守破離しており、1～50人規模を想定した設計)

そのため、試作系や1人/単発案件などで利用する方にとっては「無駄に複雑」「無駄な処理」と感じる方もいらっしゃるかもしれません。
ですが、移植性やソフトウェア資産の再利用という観点では、案件の規模を問わず活かせるのではという想いで公開しております。

万人受けする設計方針ではないとは思いますが、生産性を高める一助になると幸いです。

一方で、今回を機に dev/minimal というブランチも設けました。
こちらは main 関数で while ループしているだけの最小限の実装に留めていますので、
VSCode との連携や Runner の管理など、部分的な機能だけを利用したい方、参考にしていただければと思います。

https://github.com/Corgeek/ZephyrOpsPlaybook/tree/dev/minimal