SlideShare a Scribd company logo
M5StackをRustで動かすまで
インターフェース オフ会 @ CQ出版
2019/06/17
Kenta IDA (@ciniml)
自己紹介
•井田 健太 (@ciniml)
•仕事:FPGAの論理設計
• 最近はなぜかGoのコードを書いている…
•Rustレベルは入門
• 実践Rust入門読んでます。
2019/6/17M5StackをRustで動かすまで
M5Stackとは
•ESP32を使ったプロトタイピング・モジュール
• Wi-Fi, Bluetooth 4.2
• グラフィック液晶
• ボタン
• バッテリー
• そこそこしっかりした筐体 (重要)
2019/6/17M5StackをRustで動かすまで
ESP32とは
•Espressifが製造・販売しているマイコン
• Wi-Fi, Bluetooth 4.2
• Xtensa LX6 dual core @240[MHz] max
• →ARMではない
2019/6/17M5StackをRustで動かすまで
RustのXtensa対応
•Rust(rustc)の対応にはLLVMの対応が必要
• rustcはLLVMを使ってコード生成している
•LLVMのXtensa対応
• 2019年2月13日に対応
• https://esp32.com/viewtopic.php?t=9226
• GitHubに対応版がある (llvm-xtensa)
• https://github.com/espressif/llvm-xtensa
• LLVMのmainstreamに入ったわけではない
2019/6/17M5StackをRustで動かすまで
rustcのXtensa対応
•LLVMのmainstreamが対応してないので当然未対応
•対応版を作るしかない
•つくれるのか?
• llvm-xtensa はLLVM6.0ベース
• 最新のrustcはLLVM9.0
• LLVMのプロジェクト構成、9.0から完全に別物…
• llvmとclangとかに分かれてたのが、llvm-projectにまとまった感じ?
• →最新は諦めて、LLVM6.0のころのrustcを使う
2019/6/17M5StackをRustで動かすまで
Xtensa対応に必要なこと
• rustcのターゲットを追加する
• Xtensaバックエンドのリンクと初期化処理を追加
• XtensaのABI情報を追加
• ターゲット定義の追加
• 細かい変更箇所はGitHubに書いておきました
• https://github.com/ciniml/rust
• ということをやっていたら、既に他の人がやっていた
• https://github.com/MabezDev/xtensa-rust-quickstart
• 私の方のrustcは1.28.0、向こうは1.34.0 負けた…
• 新しい物が動くのはありがたいので1.34.0の方を使うことにする
2019/6/17M5StackをRustで動かすまで
ESP32でRustを使うときの方針
•ベアメタル
• ESP-IDF(ESP32公式フレームワーク)を使用しない
• スタートアップコードから直接Rustのコードを実行
• →ESP-IDFは一部バイナリのみ提供部分あり
• e.g. Wi-Fi, Bluetoothなど無線部分、ペリフェラルのドライバなど
• アプリケーションを作るのにはあまり現実的では無い
•→ESP-IDFからRustのメインルーチンを呼び出す方針にす
る 2019/6/17M5StackをRustで動かすまで
ESP-IDFとRustのコードの結合
•extern “C”なrust_main関数を定義
• ESP-IDFのmain関数から呼び出す
•Rust側の全コードをESP-IDFの1コンポーネントとする
•staticlibとしてビルドしてIDFからライブラリとして参照
•あとはIDF単体のアプリと同じ
2019/6/17M5StackをRustで動かすまで
ESP32上でのRustの環境
•とりあえずno_std
• std動くようになるといいですね
•現状はlibcoreでがんばる
• ESP-IDF側のlibcのmallocが使えるのでヒープは使える
• malloc/freeを呼び出すGlobalAlloc実装を作るだけ
2019/6/17M5StackをRustで動かすまで
ESP-IDFの関数呼び出し
•bindgenを使ってCFFIの定義を生成
• ヘッダー入力するとRustの定義を生成してくれるツール
•CFFI定義だけなので、UnsafeとSafeの橋渡しが必要
•SPI Masterのラッパーを書いたがそこそこ大変
• ESP-IDFのSPI Masterドライバの呼び出しをラップ
• ベアメタルで書くよりはマシなはず
2019/6/17M5StackをRustで動かすまで
RustでFreeRTOSの機能を使う
•freertos-rs クレート
• https://github.com/hashmismatch/freertos.rs
•FreeRTOSのAPI呼び出しはCで書いたshim経由
• プラットフォームごとにshimを書けば良い
•但しESP32のFreeRTOS固有の機能(デュアルコア)未対応
• xTaskCreatePinnedToCore (コア指定してタスク作成)が呼べ
ない
• →freertos-rsを修正してコア指定できるように対応 2019/6/17M5StackをRustで動かすまで
Rustで周辺回路を扱う
•embedded-hal クレート
• 組み込み向けでよく使われる周辺回路の抽象化
• ADC, I2C, SPI, GPIOなどのトレイトが定義されている
•embedded-hal経由で外部ICを扱うドライバ
• awesome embedded rustにまとめられている
• https://github.com/rust-embedded/awesome-
embedded-rust
2019/6/17M5StackをRustで動かすまで
RustでM5Stackの液晶を扱う
•M5Stackの液晶はILI9341
• Arduino向け実装が一番よく出来ている
•Rust用にも ili9341 クレートがある
• ただし、作りかけであまり機能は多くない
•Ili9341クレートは初期化処理と指定座標への点描画のみ
• 実際の描画処理は embedded-graphics クレートが担当
2019/6/17M5StackをRustで動かすまで
embedded-graphicsクレート
•図形描画や画像データの読み込みと描画制御を担当
• 線分や楕円の描画アルゴリズムなど
• ビットマップ・フォントの描画
•実際の描画は Drawable トレイトを実装した型が担当
•PC上のシミュレータもあってよく出来ている
•https://docs.rs/embedded-
graphics/0.5.0/embedded_graphics/
2019/6/17M5StackをRustで動かすまで
現在の進捗
• M5Stackの液晶表示に成功
• ただしすごく遅いので要改良
• SPIの送信処理が非効率
• FreeRTOSのタスク間通信
• 乱数生成タスクで描画座標生成
• 描画タスクで描画処理
• Wi-Fiとかはまだ
• AP接続までは確認できている
2019/6/17M5StackをRustで動かすまで
Rust入門した感想
• unsafeばかり触ってるのでまだ分からない
• まだあまりborrow checkerに怒られてない
• SPIドライバ作るときにちょっと怒られたけど…
• ライフタイムが怪しいコードを書くとコンパイル時に死ぬのが良い
• C++だとそのまま通ってSEGVとかになりがち
• Result<T,E>の楽な扱い方がよく分かってない
• 今朝ようやくtry!マクロの存在に気付いた
• 早くsafeな世界に行きたい
2019/6/17M5StackをRustで動かすまで
おしまい
2019/6/17M5StackをRustで動かすまで

More Related Content

M5StackをRustで動かす