二十年来の夢をmruby/cで叶えた

# 要約
* What - 何を作ったのか?
  * 組み込みソフトウェアのうち「タスク」部分のみを、無線接続＆短時間で再起動なしに書き換える仕組みを作った<br>（UX・・・User eXperience）<br>（DIY・・・Do It Yourself）

    | クリティカルタスク<br>(C言語) | UXタスク<br>(Ruby) | DIYタスク<br>(Ruby) |
    | :---: | :---: | :---: |
    | ↑ | mruby/c VM | ← |
    | リアルタイムOS | ← | ← |
    | ハードウェア依存部 | ← | ← |
    | ハードウェア | ← | ← |

* How - どのように実現したのか？
  * プレスリリースが公開されました
    https://prtimes.jp/main/html/rd/p/000000004.000031161.html
* Why - なぜ作ったのか？
  * 本投稿で開発の背景について書いてみます

***
**以下の内容は、あくまで私見であり、所属先の立場や意見とは一切関係ございません。**
***

# なぜ作ったのか？
## 学生時代に似たような構想を持っていた
* 高専生の頃にモータドライバ基板や赤外線リモコン基板のプログラムを担当していたが、同じ基板(ハードウェア)を複数枚搭載する場合でも、ソフトウェアはパラメータ違いを複数開発する場合があった
* 全てアセンブリ言語で記述されていたため、一部を書き換える場合であっても知識・経験だけでなく実装者のクセが出るため属人化していた
### 考えていたこと
* 制御パラメータ(定数)だけでなく、状態遷移やシーケンスの部分をEEPROMで定義できる仕組みを作り、共通ファームウェアでEEPROM部分だけを書き換えることで全ての用途に対応できる
* EEPROM部分はPC以外でも書き換えが出来るようにしたい<br>（例：PalmOS(CLIÉ)、Zaurus、Cassiopeia、京ぽん(AH-K3001V)など）
* マルチプラットフォーム対応とするためにコンパイラはJavaScriptで実装していた<br>（NetFrontやOpera、NetscapeNavigatorで動作するようにしたかった）
* PICマイコンへのデータ転送はイヤホン端子を用いた独自の多値FSKを開発していた
  * 受信回路のBOMを減らす為にコンパレータを内蔵したPIC16F88を使用
  * 双方向通信は困難であったためエラー訂正を実装していた
### 開発を中止した理由
* 使用していたPICマイコンでは性能が足りなかった (PIC16F84A, PIC16F88, 等)
* 開発途中でArduinoが登場し、これでええやん、となった

## 社会人になってから感じていた課題
* 統計的手法を用いた量産品設計を行う中で、最大公約数的なものづくりにならざるを得ない部分を解決して、ひとりひとりに寄り添ったものづくりが出来ないかと考えるようになった
* 組み込みソフトウェアは大きく複雑になってきており、専門のソフトウェアエンジニア以外が把握することは難しくなりつつある
* モデルベース開発によるラピッドプロトタイピングは非常に有用だが、専用ハードウェアが必要となる事や量産製品への落とし込みには課題があると感じていた
* ヒトとのインタフェースとなる製品に於いては理論だけでなく感性によるチューニング(作り込み)を実現したいと考えていた

## そして実現へ
* 業務としてNordic製SoCを扱うことになり、触れているうちに良い機会(Opportunity)を得たのではないかと考えるようになった（環境、タイミング、技術力の全てが揃った）
* 2024年3月頃から個人的なプロジェクトとして具体的な実現策を検討しはじめた<br>（mruby/cの他にはeLua, MicroPython, mJS, Scratchなどを検討していた）
* 2024年6月頃にNordic nRF52832上でmruby/cを用いたLチカを達成<br>https://qiita.com/uist1idrju3i/items/41f38a1531360e0e6fdb

# 実現したいこと＆実現しつつあること
1. 思いついたら直ぐに・気軽に・実機で試せる「思考速度のプロトタイピング」
    * Rubyのコードを編集・保存すると直ちに実機の動作が変わる仕組みを実現した
    * 文字通り瞬く間に世界を変えるために0.1秒以内を目標に開発（現在は約24ms）
    * レベルに応じて使用可能なAPI(メソッド)に制限を設けることで安定性と高速性を両立する
    * マイコンの再起動を伴わない (書換対象以外の処理は継続実行される、例えばBluetoothLE通信は維持されるため無線接続デバッグコンソールの接続も維持される)
1. ビジュアルプログラミング環境により、誰もが実用的な組み込みプログラミングを行える
    * 専門知識を持ったソフトウェアエンジニアだけでなく、システム設計者やメカ設計者も実製品の挙動を書き換えながら製品の作り込みができるようにしたい
1. エンドユーザ自身が、作成したプログラムを保有するデバイス上で動作させられる「DIYできる価値」
    * 自分専用に使いやすくカスタマイズすることが出来るだけでなく、アイデア次第で様々な使い方が出来るようになる

# 夢のつづき
* あらゆる組み込み機器でも同様の仕組みが提供されるようにしたい<br>（もっとプログラミング可能な世界にする）
* 多くの方に組み込みプログラミングの楽しさを感じてほしい
  * 優れた開発体験を実現したい
  * 教育・ホビー・製品まで使える開発環境(エコシステム)を実現したい

# 実際に使ってみて感じたこと
* コード変更が実機に反映されるまでの速度が速く、安定動作することによる快適な開発体験を経験すると従来手法に戻れなくなりそう
* 新しいセンサやアクチュエータを使うときに便利そう（例えばI2Cコマンドをシーケンスを変えながら試せる）
* 生産工場で用いる出荷検査プログラムを書いても良さそう<br>（製品ソフト内に検査用ロジックを組み込む必要が無くなる）

# ベンチマーク
## 測定結果(参考値)
| **＼** | **ビルド** | **転送** | **再読込** | **合計** |
| :---: | :---: | :---: | :---: | :---: |
| **従来手法**<br>nRF52840 | 45s | 22s<br>(有線接続) | 0.1s | 約67s |
| **Blink**<br>nRF52840 | 0.01s | 2.45〜2.70ms<br>(BluetoothLE) | 11〜12ms | 約24ms |
| **Blink**<br>nRF54L15 | 0.01s | 1.68〜2.00ms<br>(BluetoothLE) | 5ms | 約17ms |

* nRF52840は64 MHz Cortex-M4 with FPUを搭載している
* nRF54L15は128 MHz Arm Cortex-M33を搭載している
* 使用したmrubyコンパイラ(mrbc)はx86_64バイナリのためRosetta2を使用している
  * 今回のベンチマーク結果にはx86_64バイナリを用いて測定した結果の0.01sを採用しているが、`% rbenv install mruby-dev`によりインストールしたarm64バイナリを使用すると0.00sであった
* 敢えてmacOSにて測定している
  * Windows11(24H2)では、Blinkは影響が小さいが、従来手法はより長い時間を要する

## 「従来手法」の測定
* ビルド時間、転送時間の測定
  * VisualStudioCodeの表示を目視で確認し、ストップウォッチにより測定した
* 再読込時間の測定
  ソフトウェアによる初期化処理時間を以下のコードにより測定した上で、ハードウェアの起動に掛かる時間を加算した
    ```c
    #include <stdint.h>
    #include <stdlib.h>
    #include <zephyr/init.h>
    #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    
    static int blink_init(void);
    SYS_INIT(blink_init, APPLICATION, 0);
    
    static int blink_init(void) {
      int64_t timestamp = k_uptime_get();
    
      /* ここで初期化処理を実施する */
    
      // 結果表示
      printk("Initialized (%lli ms)", k_uptime_delta(&timestamp));
      return EXIT_SUCCESS;
    }
    ```

## 「Blink手法」の測定
* ビルド時間
  * `% time mrbc`コマンドを用いて測定した
* 転送時間
  * Blink転送ツールにより測定している
* 再読込時間
  * `k_uptime_delta`関数を用いて、現行バイトコードの実行終了〜新バイトコードの実行開始までの時間を測定した

## 測定環境
MacBook Pro 14″ (2021, M1 Pro)
![IMG_4120.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931783/40f7cde5-76e3-bbad-426e-53861425b188.jpeg)

# 余談
プログラミングを始めたきっかけやバックグランドについて
* 小学生
  * 実家にSHARP MZ-5500があったので公民館(図書室)で借りたBASIC本を写経してプログラミングに触れたのがきっかけ
  * WindowsME (NEC PC-VL1000N/87D)への移行に合わせて「日本語プログラム言語 ひまわり」と「VisualBasic 6.0」を扱うようになった
  * コンピュータの中の世界では神のような不思議な体験が面白かった
* 中学生
  * 「美佳のタイプトレーナ」でタッチメソッドを習得したことでボトルネックが解消され、更にプログラミングにのめり込んでいった（キーボードはTopre Realforce 106Sを愛用）
  * フリーソフトウェアを作って配布していたところ感謝の電子メールが届くようになったことで、技術で役に立つ仕事に就きたいと考えるようになった
  * フリーソフトウェアはレンタルスペースを借りて配信していたが、自宅サーバ(OpenBlockS266)で配信するようになったことでLinuxとネットワークの知識を~~苦しんで~~覚えつつ情報セキュリティにも興味を持つようになった
  * ソフトウェアではハードウェアの限界は超えられない、と考えるようになり電気電子工学科へ進む
* 高専生
  * アセンブリ言語はCPUに近い位置で会話ができる面白さから組み込みプログラミングに没頭した
* 社会人
  * 2024年6月 Rubyの学習を開始