💡
Arduino UnoでRustデバドラを作ろうとしたら別のOSSが生まれた
📝 本記事はストーリー編です。技術詳細はこちらで読めます。
はじめに - なぜRustでデバドラを作ったのか
RustでArduino Unoが動くavr-hal
を見つけ、example通りにビルドするとLチカ成功。
「これは…ディスプレイも動かしたくなるやつ!」という流れに。
2025年7月末、37℃の酷暑の中、電気街で部品を調達(朦朧としながら…)。
しかし、既存クレートは非同期専用やUno非対応ばかり。
なので 「こうなったら自分で作るしかない!」 と腹をくくる。
最初の壁 - 初期化シーケンスとデータシート地獄 - 砂嵐との戦い
ディスプレイドライバは「初期化シーケンス」という謎のコマンド列を送る必要があるらしい。
配線抽象化のためGroveシールドを使っていたこともあり、難易度が急上昇。
- データシートやMycroPythonドライバの熟読
- 既存クレートの実装解析
- U8g2の通信方式調査
- C++サンプルを試すと動くんだよなこれが
-> しかし初期化シーケンスのコマンド列が全然わかんねえな……
ようやく流れの構造はわかってきたが、
SH1107とSH1107Gの違いが理解できず、後で知って発狂。
ギャー!ソフトウェア的には大差ないじゃん!
流れ把握によりなんとか動いたが、表示は砂嵐。
原因切り分けのため、ufmt::uwriteln!
でログを挟みまくる。
- 独自エラー型とかあると DX 良いよね
- forループでI2Cアドレス探索
- デバッグコードがジェネリック型レベルでメインロジックまで侵食
「これ…切り出したら汎用ロガーになるのでは?ドライバの可読性も上がるし」と思い立つ。
横道に逸れだす
ここから方向転換。
ドライバ内にあったデバッグ処理を分離し、開発ブランチ専用の汎用ロガー・デバッガに。
- 現場で使える計測ツール化を目指す
- CIの整備
- 差分出力・コードベース削減
Rust のマクロ機能を用いた便利化
草稿をリリースしてしばらくした8/14、Clineでのテスト中に気付く。
「毎回シリアル型をcore::fmt::Write
にwrapしてない?」
そこで:
- ボイラープレートを圧縮したアダプタマクロを実装
- 便利マクロを詰め合わせたワークフロー支援クレート化
- no_std環境でも楽にデバッグ可能に
得られた知見
今回の開発で得た学び:
- I2Cのログ出力方法
- no_std環境でのデバッグ手法
- AVRの厳しいメモリ制約下では
alloc
を避け,heapless
を活用 - Rustのライフタイムとジェネリック型の使い方
- OSS開発は方向転換しても面白い
おわりに
最初はRustで初めてのデバイスドライバ開発のつもりが、
最終的にデバッグワークフローツールという別物が完成。
やってみて分かったのは、
「目的地より寄り道のほうが学びは多い」 ということでした。
Discussion