Contents
ツールチェーンの基本構成
組み込み Rust 開発で最低限必要なのは コンパイラ・ビルド補助ツール·デバッガ の三要素です。これらが揃っていれば、ソースコードからフラッシュまで一貫した CLI 操作が可能になります。
rustup と必須コンポーネント
rustup は Rust 本体と各種ツールチェーンを管理する公式インストーラです。組み込み開発では Nightly ビルドに加えて以下のコンポーネントを入れることが推奨されます。
|
1 2 3 4 5 6 |
# Nightly のインストール(2026‑04‑01 時点の最新版) rustup toolchain install nightly # 必要なコンポーネントを追加 rustup +nightly component add rust-src llvm-tools-preview |
ポイント:
rust-srcが無いとcargo build --target …が失敗しやすく、エラーメッセージは「cannot find source for cratecore」となります。上記コマンドで解決できます。
llvm‑tools と cargo-binutils
組み込み向けの最適化・サイズ測定には LLVM のツール群が不可欠です。cargo-binutils はこれらを Cargo 経由で呼び出すラッパーです。
|
1 2 3 |
cargo +nightly install cargo-binutils --locked rustup +nightly component add llvm-tools-preview # 再度念のため実行 |
トラブルシューティング例
| 症状 | 原因候補 | 対処法 |
|---|---|---|
cargo size が “command not found” |
cargo-binutils 未インストール | 上記コマンドで再インストール |
| ビルド後のバイナリが 1 MiB 超過 | デフォルトで LTO が無効 | RUSTFLAGS="-C link-arg=-s -C opt-level=z" を環境変数に設定 |
GDB/LLDB デバッグ環境
組み込みデバッガとしては GDB が広く使われていますが、LLVM の lldb でも同等の機能を提供します。JTAG/SWD アダプタと併用することでブレークポイントや変数ウォッチが可能です。
|
1 2 3 4 5 |
# GDB をインストール(Ubuntu 例) sudo apt-get install gdb-multiarch # VS Code 用拡張 (rust-analyzer + Cortex‑Debug) の推奨設定は後述 |
Cargo と embedded-hal の活用方法
Cargo は Rust のビルド・依存管理の中心です。組み込み開発では embedded-hal というハードウェア抽象化レイヤー(HAL)クレートを介してデバイス固有コードと汎用ロジックを分離します。
プロジェクト構成例(ワークスペース)
以下は、複数ボード向けに共通ロジックを common クレート、各ボード固有コードを pico, f4_discovery と分割した Cargo ワークスペース の雛形です。
|
1 2 3 4 |
# Cargo.toml (ルート) [workspace] members = ["common", "boards/pico", "boards/f4_discovery"] |
boards/pico/Cargo.toml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[package] name = "pico-demo" version = "0.1.0" edition = "2021" [dependencies] cortex-m = "0.7" cortex-m-rt = "0.7" panic-halt = "0.2" rp2040-hal = { version = "1.2", features = ["rt"] } common = { path = "../../common" } [profile.release] codegen-units = 1 debug = false lto = true |
この構成により、common に書いたロジックは どのボードでも同じコード として再利用できます。
HAL クレートの選び方とバージョン管理
| ボード | 推奨 HAL クレート | 現行安定版 (2026‑05) | 主な更新頻度 |
|---|---|---|---|
| Raspberry Pi Pico | rp2040-hal |
1.2.0(2025‑03) | 月次パッチ |
| STM32F4 Discovery | stm32f4xx-hal |
0.10.1(2025‑12) | 3–4 回のメジャーリリース/年 |
| STM32F401 Nucleo‑64 | stm32f4xx-hal (サブセット) |
同上 | 上表参照 |
選定指針
- API の安定性:0.x 系は頻繁に破壊的変更が入ることがあるため、1.0+ が出ているか確認。
- ドキュメントとサンプル数:GitHub README.md と examples/ ディレクトリの充実度を評価。
ビルド失敗時の典型的な対処法
- ターゲットが未登録
- エラーメッセージ例:
error: target 'thumbv7em-none-eabihf' is not installed -
対策:
rustup target add thumbv7em-none-eabihf -
リンクエラー(undefined reference to
_start) - 原因: スタートアップコードが欠如、または
features = ["rt"]が抜けている。 -
対策: HAL の Cargo.toml で
features = ["rt"]を明示。 -
サイズが大きすぎる
- 原因: デバッグシンボルが残っている、最適化レベルが低い。
- 対策:
[profile.release]にopt-level = "z"とdebug = falseを設定。
デバッグ・フラッシュツールの実践的設定
組み込みデバイスへの書き込みとデバッグは cargo‑embed と probe‑rs 系ツールが事実上の標準です。以下では重複を排除し、代表的な設定例とトラブル対策をまとめます。
cargo‑embed の統一設定例
cargo‑embed は Cargo.toml のメタデータか .cargo/config.toml にボード情報を書くだけで、ビルド・フラッシュ・デバッグが 1 コマンド で完結します。ここでは Raspberry Pi Pico と STM32F4 Discovery 両方に対応できる汎用設定を示します。
|
1 2 3 4 5 6 7 8 9 10 |
# .cargo/config.toml (プロジェクトルート) [build] target = "thumbv6m-none-eabi" # デフォルトは Pico 用 [target.thumbv6m-none-eabi] runner = "probe-run --chip RP2040" [target.thumbv7em-none-eabihf] # STM32F4 用 runner = "probe-run --chip STM32F407VG" |
Cargo.toml のメタデータ(ボードごとに切り替える例)
|
1 2 3 4 5 6 7 8 9 10 |
[package.metadata.cargo-embed] # Pico 用設定 chip = "RP2040" flash_algo = "rp2040.cfg" # F4 Discovery 用は別プロファイルで上書き可能 [[bin]] name = "f4_demo" required-features = ["stm32"] |
ポイント:
probe-runが自動的にデバイスへ書き込み、GDB サーバとして起動します。VS Code のlaunch.jsonに以下を追加すればブレークポイントが即座に有効になります。
|
1 2 3 4 5 6 7 8 |
{ "type": "cortex-debug", "request": "launch", "name": "Debug (probe-run)", "executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/pico-demo", "servertype": "probe-rs" } |
probe‑rs と probe‑run の使い方
probe-rs-cli は低レベルのフラッシュ・デバッグコマンドを提供し、probe-run がその上位ラッパーとして動作します。
|
1 2 3 4 5 6 7 |
# インストール cargo +nightly install probe-rs-cli --locked cargo +nightly install probe-run # 2026‑04 の最新版 # 接続デバイスの確認 probe-run --list-probes |
デバッグ実行例(STM32F4 Discovery)
|
1 2 3 4 5 6 7 |
cargo run \ --target thumbv7em-none-eabihf \ --release \ -p f4_demo \ --features stm32f4xx-hal/rt \ -- -r # probe-run に渡すオプション |
このコマンドは ビルド → フラッシュ → GDB サーバ起動 をシーケンシャルに実行し、ターミナル上で Ctrl‑C で停止できます。
よくある問題と対処フロー
| 症状 | 原因例 | 確認手順 | 解決策 |
|---|---|---|---|
デバッガが接続できない (probe-run: No probe found) |
USB ケーブルの不良、デバイス側電源不足 | lsusb でデバイスが列挙されているか確認 |
別のケーブル・USB ポートに差し替え、外部電源を供給 |
フラッシュ失敗 (Failed to flash) |
不適切なフラッシュアルゴリズムファイル | cargo embed --list-flash-algos で対象ボードが表示されるか確認 |
正しい .cfg ファイルを ~/.probe-rs/flash-algorithms/ に配置 |
| GDB がシンボル情報を取得できない | debug = true がリリースビルドで無効化された |
cargo build --release -vv の出力に .elf が生成されているか確認 |
[profile.release] に debug = 2 を追加して再ビルド |
主な開発ボード比較
ボード概要(個別解説)
Raspberry Pi Pico (RP2040)
デュアルコア Cortex‑M0+(133 MHz)を搭載し、PIO による高速 I/O が特徴です。公式 HAL クレート rp2040-hal は 2025 年 3 月に 1.2.0 がリリースされ、月次でバグフィックスが行われています【^1】。
STM32F4 Discovery Kit
Cortex‑M4(最大 180 MHz)と DSP・FPU を備える高性能ボードです。stm32f4xx-hal は 2025 年 12 月に 0.10.1 がリリースされ、年4回の大規模アップデートが実施されています【^2】。
STM32F401 Nucleo‑64
コンパクトなフォームファクタで、Cortex‑M4(84 MHz)を搭載。stm32f4xx-hal のサブセットとして利用でき、入門者向けの L チカ実装が Qiita に多数掲載されています【^3】。
定量的比較表
| 項目 | Raspberry Pi Pico (RP2040) | STM32F4 Discovery Kit | STM32F401 Nucleo‑64 |
|---|---|---|---|
| CPU / クロック | Cortex‑M0+ 133 MHz | Cortex‑M4 180 MHz | Cortex‑M4 84 MHz |
| フラッシュ / SRAM | 2 MiB / 264 KB | 1 MiB / 192 KB | 512 KB / 96 KB |
| GPIO 数 & 周辺機器 | 30+ GPIO、4 UART、2 I²C、2 SPI、4 ADC | 48 GPIO、6 UART、3 I²C、3 SPI、12 ADC | 42 GPIO、2 UART、1 I²C、1 SPI、12 ADC |
| HAL クレートバージョン | rp2040-hal 1.2 (2025‑03) ★★★☆ |
stm32f4xx-hal 0.10 (2025‑12) ★★★★ |
同上(サブセット) ★★☆☆ |
| 公式サンプル数 | 30+(GitHub)↗【^1】 | 20+(ST 社)↗【^2】 | 5+(Qiita)↗【^3】 |
| 価格 (参考) | 約 $4 ★★★★ | 約 $15 ★★☆☆ | 約 $12 ★★☆☆ |
| コミュニティ規模 | GitHub ⭐3,200、Reddit 活発 ↗【^1】 | ST フォーラム ⭐4,000、Qiita 多数 ↗【^2】 | Nucleo フォーラム ⭐1,500 ↗【^3】 |
★は更新頻度・サンプル充実度を 5 段階で評価したものです。
出典
- 【^1】rp2040‑hal リポジトリ (GitHub, 2026/05)
- 【^2】stm32f4xx‑hal ドキュメント (crates.io, 2026/04)
- 【^3】Qiita 記事検索結果 (2026/03)
ユースケース別選択ガイド
学習・入門向け
| ボード | 推奨理由 | 注意点 |
|---|---|---|
| Raspberry Pi Pico | 低価格・豊富なサンプル、PIO による実験的プログラミングが容易 | M0+ の計算性能は限定的。DSP 系アルゴリズムは不向き |
| STM32F401 Nucleo‑64 | ブレッドボード互換で配線しやすく、Qiita 記事が多数 | ペリフェラル数が少なく、拡張には別途シールドが必要 |
プロトタイピング
| ボード | 強み | 想定プロジェクト例 |
|---|---|---|
| STM32F4 Discovery | 高クロック・DSP/FPU、豊富な I/O、ST のエコシステム | 音声認識、モータ制御、リアルタイム画像処理 |
| Raspberry Pi Pico | PIO による高速ビットバンギング、GPIO 数が多い | センサーネットワーク、低消費電力 IoT デバイス |
製品化移行
| ボード | 移行しやすさ | 推奨シナリオ |
|---|---|---|
| STM32F4 系 | 長期供給保証と豊富な外部 IP があり、量産基板への流用が容易 | 産業機器・医療機器の本格開発 |
| Raspberry Pi Pico | 大量生産体制と低コストが魅力。Rust 用 HAL の安定化が進んでいる | 小型ウェアラブル、エッジ AI デバイス |
実践ハンズオン:サンプルコードとフラッシュ手順
1. LED ブリンク(最小構成)
以下は 共通ロジック (common/src/lib.rs) と各ボードの main.rs に分割した例です。
common/src/lib.rs
|
1 2 3 4 5 6 7 8 9 |
pub fn blink<T: embedded_hal::digital::v2::OutputPin>(mut led: T, delay_ms: u32) -> ! { loop { led.set_high().ok(); cortex_m::asm::delay(delay_ms * 8_000); // Rough delay (CPU MHz に合わせ要調整) led.set_low().ok(); cortex_m::asm::delay(delay_ms * 8_000); } } |
boards/pico/src/main.rs
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#![no_std] #![no_main] use panic_halt as _; use rp2040_hal as hal; use hal::{pac, clocks::Clock}; #[rp2040_hal::entry] fn main() -> ! { // 周辺機器初期化 let mut pac = pac::Peripherals::take().unwrap(); let core = pac::CorePeripherals::take().unwrap(); let mut watchdog = hal::Watchdog::new(pac.WATCHDOG); let clocks = hal::clocks::init_clocks_and_plls( 12_000_000, pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut watchdog, ) .ok() .unwrap(); // GPIO25 (オンボード LED) を出力に設定 let sio = hal::Sio::new(pac.SIO); let pins = hal::gpio::Pins::new( pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS, ); let led_pin = pins.led.into_push_pull_output(); common::blink(led_pin, 500); } |
boards/f4_discovery/src/main.rs(同等)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#![no_std] #![no_main] use panic_halt as _; use stm32f4xx_hal as hal; use hal::{prelude::*, stm32}; #[hal::entry] fn main() -> ! { let dp = stm32::Peripherals::take().unwrap(); // クロック設定 (8MHz 外部クリスタル想定) let rcc = dp.RCC.constrain(); let clocks = rcc.cfgr.freeze(); // LED (PD12) を出力に let gpiod = dp.GPIOD.split(); let led = gpiod.pd12.into_push_pull_output(); common::blink(led, 300); } |
ビルド・フラッシュ手順
|
1 2 3 4 5 6 7 8 |
# Pico 用 cargo build -p pico-demo --release cargo embed # cargo‑embed が自動で flash & run # F4 Discovery 用 cargo build -p f4_demo --release cargo embed --chip STM32F407VG # .cargo/config.toml の runner を利用 |
2. UART エコー(トラブル対処付き)
実装ポイント
embedded-hal::serial::Read/Writeトレイトを使用- ボーレート設定ミスは 通信が途切れる 主因になるので、データシートのクロック分周比を必ず確認
|
1 2 3 4 5 6 7 8 9 10 |
pub fn uart_echo<U: embedded_hal::serial::Read<u8> + embedded_hal::serial::Write<u8>>( mut uart: U, ) -> ! { loop { if let Ok(byte) = nb::block!(uart.read()) { nb::block!(uart.write(byte)).ok(); } } } |
デバッグ時の典型的なエラーと対処
| エラーメッセージ | 原因例 | 修正策 |
|---|---|---|
Parity error |
ボーレート不一致、またはデータビット設定ミス | uart::Config { baudrate: 115_200, parity: None, stopbits: StopBits::One } を明示 |
Overrun error |
受信バッファが埋まる(処理遅延) | 割り込みベースでハンドラを実装し、nb::block! の代わりに DMA 使用を検討 |
まとめ
- ツールチェーン:
rustup + nightly,llvm-tools-preview,cargo-binutils,gdb/lldbが基本。インストール手順と典型的なエラーハンドリングを抑えておけば、環境構築は数分で完了します。 - ボード選定:低価格・学習向けは Raspberry Pi Pico、高性能・量産志向は STM32F4 系 がバランス良く推奨されます。各 HAL クレートのバージョンとコミュニティ規模を指標にすると選択が容易です。
- 実装例:共通ロジックを
commonクレートに分離し、ボード固有コードは最小限に抑える設計が再利用性を高めます。サンプルは LED ブリンク と UART エコー の二つをベースに展開すれば、入門から応用までカバーできます。 - トラブルシューティング:コンパイルエラー・デバッガ接続失敗・フラッシュ失敗の3パターンを中心に対処手順をまとめました。問題が起きたらまずはエラーメッセージと上記表を照合してください。
この情報を元に、まずは公式サンプルリポジトリから 「ブリンク」 をクローンし、前述の cargo embed 手順で実機に書き込んでみましょう。動作確認が取れたら、次は UART エコーや I²C センサ読み取りへとステップアップしてください。
[^1]: rp2040-hal GitHub リポジトリ, Release v1.2.0 (2025‑03-12), https://github.com/rp-rs/rp-hal/releases/tag/v1.2.0
[^2]: stm32f4xx-hal crates.io ページ, Version 0.10.1 (2025‑12‑05), https://crates.io/crates/stm32f4xx-hal/0.10.1
[^3]: Qiita タグ「stm32f4」検索結果(2026‑03 時点) https://qiita.com/tags/stm32f4
本稿の数値・評価は 2026‑05‑01 時点の公式情報とコミュニティデータに基づき、客観性を保つため複数ソースからクロスチェックしています。