点灯させよう
embedded-hal
この章では、micro:bit の背面にあるたくさんの LED のうち 1 つを点灯させます。これは基本的に組み込みプログラミングにおける「Hello World」です。この作業を行うために、embedded-hal が提供するトレイトの 1 つ、具体的にはピンをオンまたはオフにできる OutputPin トレイトを使います。
micro:bit の LED
micro:bit の背面を見ると、5x5 の正方形に並んだ LED があり、通常は LED マトリクスと呼ばれます。このようなマトリクス配置を使うことで、それぞれの LED を駆動するために 25 本の別々のピンを使わなくても、どの列とどの行を点灯させるかを制御するために 10 本(5+5)のピンだけで済みます。
NOTE micro:bit v1 のチームはこれを少し異なる形で実装していました。schematic page によると、 実際には 3x9 のマトリクスとして実装されていますが、いくつかの列は単に未使用のままになっています。
通常であれば、特定の LED を点灯させるためにどのピンを制御すべきかを判断するには、 ここで micro:bit v2 schematic または micro:bit v1 schematic を それぞれ読む必要があります。 しかし幸運なことに、先ほど述べた micro:bit BSP を使うことで、 こうした詳細はすべてきれいに抽象化されています。
実際に点灯してみよう!
LED マトリクス内の LED を点灯させるのに必要なコードは、実際にはとてもシンプルですが、少し準備が必要です。まずコードを見て、そのあとで順を追って確認していきましょう。
#![deny(unsafe_code)]
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use panic_halt as _;
use microbit::board::Board;
use microbit::hal::prelude::*;
#[entry]
fn main() -> ! {
let mut board = Board::take().unwrap();
board.display_pins.col1.set_low().unwrap();
board.display_pins.row1.set_high().unwrap();
loop {}
}
最初の数行から main 関数までは、以前に見た基本的なインポートとセットアップを行っているだけです。 しかし、main 関数はこれまで見てきたものとはかなり異なっています。
最初の行は、多くの Rust 製 HAL が内部でどのように動作しているかに関係しています。
前に説明したように、これらは PAC クレートの上に構築されており、PAC クレートは
チップ上のすべてのペリフェラルを(Rust 的な意味で)所有しています。
let mut board = Board::take().unwrap(); は基本的に、
これらのペリフェラルを PAC から取得し、変数に束縛します。この特定のケースでは、
HAL だけでなく BSP 全体を扱っているため、これによって
ボード上のほかのチップの Rust 表現の所有権も取得します。
NOTE: ここでなぜ
unwrap()を呼ぶ必要があるのか疑問に思っているなら、理論上はtake()が 複数回呼び出される可能性があるからです。そうなると、ペリフェラルが 2 つの別々の変数で表現されることになり、 2 つの変数が同じリソースを変更してしまうため、多くの分かりにくい挙動が起こりえます。これを避けるため、 PAC は、ペリフェラルを 2 回取得しようとすると panic するように実装されています。
これで、row1 と col1 に接続された LED を、row1 ピンを high に設定することで点灯できます
(つまりオンにします)。
col1 を low のままにしておける理由は、LED マトリクス回路の仕組みにあります。
さらに、embedded-hal は、ハードウェアに対するあらゆる操作が、
ピンのオン・オフ切り替えのような単純なものであっても、エラーを返す可能性があるように設計されています。
このケースではそれが起こる可能性は非常に低いので、結果に対して単に unwrap() を使えます。
テストする
この小さなプログラムをテストするのはとても簡単です。まずこれを src/main.rs に入れます。
そのあと、前のセクションと同じように cargo embed コマンドを実行し、書き込みを行います。
そして前と同様に GDB を開いて、GDB stub に接続します。
$ # 前のセクションの GDB デバッグコマンド
(gdb) target remote :1337
Remote debugging using :1337
cortex_m_rt::Reset () at /home/nix/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-rt-0.6.12/src/lib.rs:489
489 pub unsafe extern "C" fn Reset() -> ! {
(gdb)
ここで GDB の continue コマンドを使ってプログラムを実行すると、micro:bit の背面にある LED の 1 つが点灯するはずです。