Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

点灯させよう

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 するように実装されています。

これで、row1col1 に接続された 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 つが点灯するはずです。