domain-embedded について
組み込み開発向けの Rust ドメインスキルです。no_std、ヒープ不使用、リアルタイム性、割り込み安全性の制約と設計パターンをまとめ、メモリや並行処理、ハードウェアアクセスの方針を示します。
主な機能
- 01no_std とヒープ不使用の制約
- 02割り込み安全性とクリティカルセクション
- 03周辺機器の所有権パターン
- 04PAC、HAL、フレームワークの階層
- 05組み込み crate の参考情報
活用シーン
- 01動的割り当てなしの静的コレクション選定
- 02ISR 共有状態の設計
- 03割り込み処理中のブロッキング回避
- 04HAL による周辺機器アクセスの整理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ actionbook/ rust-skills --skill domain-embeddedインストール後、Claude Code で/domain-embeddedを入力して読み込まれたか確認します。
詳細
プロジェクトのコンテキスト(自動挿入)
対象の設定:
!cat .cargo/config.toml 2>/dev/null || echo "No .cargo/config.toml found"
埋め込みドメイン
レイヤー 3:ドメインの制約
ドメインの制約 → 設計上の影響
| ドメインルール | 設計上の制約 | Rust への影響 |
|---|---|---|
| ヒープなし | スタック割り当て | heapless、Box/Vec は使用しない |
| std なし | Core のみ | #![no_std] |
| リアルタイム | 予測可能なタイミング | 動的割り当てなし |
| リソース制限あり | 最小限のメモリ | 静的バッファー |
| ハードウェア安全性 | 安全なペリフェラルアクセス | HAL + 所有権 |
| 割り込み安全性 | ISR 内でブロックしない | アトミック、クリティカルセクション |
重要な制約
動的割り当てなし
RULE: Cannot use heap (no allocator)
WHY: Deterministic memory, no OOM
RUST: heapless::Vec<T, N>, arrays
割り込み安全性
RULE: Shared state must be interrupt-safe
WHY: ISR can preempt at any time
RUST: Mutex<RefCell<T>> + critical section
ハードウェアの所有権
RULE: Peripherals must have clear ownership
WHY: Prevent conflicting access
RUST: HAL takes ownership, singletons
下のレイヤーをたどる ↓
制約から設計へ(レイヤー 2):
"Need no_std compatible data structures"
↓ m02-resource: heapless collections
↓ Static sizing: heapless::Vec<T, N>
"Need interrupt-safe state"
↓ m03-mutability: Mutex<RefCell<Option<T>>>
↓ m07-concurrency: Critical sections
"Need peripheral ownership"
↓ m01-ownership: Singleton pattern
↓ m12-lifecycle: RAII for hardware
レイヤー構成
| レイヤー | 例 | 目的 |
|---|---|---|
| PAC | stm32f4、esp32c3 | レジスターアクセス |
| HAL | stm32f4xx-hal | ハードウェア抽象化 |
| フレームワーク | RTIC、Embassy | 並行処理 |
| トレイト | embedded-hal | ポータブルなドライバー |
フレームワークの比較
| フレームワーク | スタイル | 最適な用途 |
|---|---|---|
| RTIC | 優先度ベース | 割り込み駆動型アプリ |
| Embassy | 非同期 | 複雑な状態機械 |
| ベアメタル | 手動 | シンプルなアプリ |
主要なクレート
| 目的 | クレート |
|---|---|
| ランタイム(ARM) | cortex-m-rt |
| パニックハンドラー | panic-halt、panic-probe |
| コレクション | heapless |
| HAL トレイト | embedded-hal |
| ロギング | defmt |
| フラッシュ/デバッグ | probe-run |
設計パターン
| パターン | 目的 | 実装 |
|---|---|---|
| no_std のセットアップ | ベアメタル | #![no_std] + #![no_main] |
| エントリーポイント | 起動 | #[entry] または embassy |
| 静的状態 | ISR からのアクセス | Mutex<RefCell<Option<T>>> |
| 固定バッファー | ヒープなし | heapless::Vec<T, N> |
コードパターン:静的ペリフェラル
#![no_std]
#![no_main]
use cortex_m::interrupt::{self, Mutex};
use core::cell::RefCell;
static LED: Mutex<RefCell<Option<Led>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let led = Led::new(dp.GPIOA);
interrupt::free(|cs| {
LED.borrow(cs).replace(Some(led));
});
loop {
interrupt::free(|cs| {
if let Some(led) = LED.borrow(cs).borrow_mut().as_mut() {
led.toggle();
}
});
}
}
よくある間違い
| 間違い | ドメイン制約への違反 | 修正方法 |
|---|---|---|
| Vec の使用 | ヒープ割り当て | heapless::Vec |
| クリティカルセクションなし | ISR との競合 | Mutex + interrupt::free |
| ISR 内でブロック | 割り込みの取りこぼし | メインループに処理を委譲 |
| 安全でないペリフェラル | ハードウェアの競合 | HAL の所有権 |
レイヤー 1 へたどる
| 制約 | レイヤー 2 のパターン | レイヤー 1 の実装 |
|---|---|---|
| ヒープなし | 静的コレクション | heapless::Vec<T, N> |
| ISR の安全性 | クリティカルセクション | Mutex<RefCell> |
| ハードウェアの所有権 | シングルトン | take().unwrap() |
| no_std | Core のみ | #![no_std]、#![no_main] |
関連スキル
| 場面 | 参照先 |
|---|---|
| 静的メモリ | m02-resource |
| 内部可変性 | m03-mutability |
| 割り込みパターン | m07-concurrency |
| ハードウェア向けの unsafe | unsafe-checker |
コメント
Markdown 対応