mcpField
R
rust-no-std

rust-no-std

github.com/mohitmishra786開発269484 回インストール18 週間前に更新
リポジトリ

rust-no-std について

`#![no_std]` のライブラリやベアメタルファームウェアを開発・デバッグする Rust 開発者向けのスキルです。`core` と `alloc` の違い、アロケーターやパニックハンドラーの設定、ホストでのテストを解説します。

主な機能

  1. 01core、alloc、std の比較
  2. 02グローバルアロケーターの設定
  3. 03no_std のパニックハンドラー選択
  4. 04alloc を任意で使うライブラリ設計
  5. 05ホストでの no_std クレートのテスト

活用シーン

  1. 01std を使わないパーサーの構築
  2. 02no_std 環境での Vec の利用
  3. 03ノート PC での no_std ライブラリのテスト
  4. 04組み込みターゲット向けコードの確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill rust-no-std

インストール後、Claude Code で/rust-no-stdを入力して読み込まれたか確認します。

詳細

Rust no_std

目的

エージェント向けに、#![no_std] の Rust 開発を説明します。core と alloc が std と比べて提供する機能、カスタムグローバルアロケーターの実装方法、組み込みターゲットでのパニックハンドラーの選択、ホストマシンで no_std クレートをテストする方法を解説します。

使用する場面

#![no_std] の Rust コードを記述またはデバッグするときに使用してください。対象は、組み込みターゲット向けのライブラリークレート、または std とリンクできないベアメタルファームウェアです。組み込み開発のワークフロー全体(probe-rs による書き込み、defmt ロギング、RTIC)については、skills/embedded/embedded-rust を使用してください。クロスコンパイルのターゲット設定については、skills/rust/rust-cross を使用してください。このスキルでは、特に no_std/core/alloc の境界とパニックハンドラーの選択に焦点を当てます。

例

  • 「std なしで動作するパーサークレートが必要です」→ #![no_std] を使った構成にし、alloc API をフィーチャーゲートし、コア API では借用スライスを使用します
  • 「no_std 環境で Vec を使うにはどうすればよいですか?」→ alloc フィーチャーを追加し、グローバルアロケーター(例:linked-list-allocator)を用意して、alloc::vec::Vec を使用します
  • 「ノート PC で no_std クレートをテストするにはどうすればよいですか?」→ #![cfg_attr(not(test), no_std)] を使ってテストモードでは std を使えるようにするか、cargo test --target x86_64-unknown-linux-gnu を実行します

ワークフロー

1. no_std クレートの構成
// src/lib.rs
#![no_std]

// core is always available (no OS needed)
use core::fmt;
use core::mem;
use core::slice;

// alloc: heap collections — requires a global allocator
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use alloc::{vec::Vec, string::String, boxed::Box, format};

pub fn add(a: u32, b: u32) -> u32 {
    a + b
}
# Cargo.toml
[features]
default = []
alloc = []       # opt-in to heap allocation

[dependencies]
# no_std-compatible dependencies only
2. core、alloc、std の比較
クレートOS が必要ヒープが必要提供する機能
coreいいえいいえプリミティブ型、トレイト、イテレーター、fmt、mem、ptr、slice、option、result
allocいいえはい(アロケーター)Vec、String、Box、Arc、Rc、HashMap(グローバルアロケーターが必要)
stdはいはいcore + alloc のすべて、および OS API(スレッド、ファイル、ソケット、環境変数)

std は core と alloc のすべてを再エクスポートするため、std が利用できる場合は use std::fmt と use core::fmt は同等です。

core だけで利用できる機能(ヒープなし、OS なし):

// These work in no_std:
core::fmt::Write           // trait for write! macro
core::iter                 // iterators
core::ops                  // operators (+, -, *, Deref, etc.)
core::option::Option
core::result::Result
core::mem::{size_of, align_of, swap, replace}
core::ptr::{read, write, null, NonNull}
core::slice, core::str
core::sync::atomic         // atomic types
core::cell::{Cell, UnsafeCell, RefCell}
core::cmp, core::convert, core::clone, core::default
core::num                  // numeric conversions
core::panic::PanicInfo     // for panic handler
3. カスタムグローバルアロケーター

no_std で alloc クレートを使用するには、グローバルアロケーターを用意します。

// src/allocator.rs — embedded allocator using linked_list_allocator
use linked_list_allocator::LockedHeap;

#[global_allocator]
static ALLOCATOR: LockedHeap = LockedHeap::empty();

pub fn init_heap(heap_start: usize, heap_size: usize) {
    unsafe {
        ALLOCATOR.lock().init(heap_start as *mut u8, heap_size);
    }
}
[dependencies]
linked-list-allocator = { version = "0.10", default-features = false }
// src/main.rs (bare-metal)
#![no_std]
#![no_main]

extern crate alloc;
use alloc::vec::Vec;

mod allocator;

// In init code (after BSS/data init):
allocator::init_heap(0x20010000, 0x10000);  // 64KB heap at RAM+64KB

// Now alloc types work:
let mut v: Vec<u32> = Vec::new();
v.push(42);

一般的な組み込み向けアロケータークレート:

  • linked-list-allocator:汎用、no_std
  • buddy-alloc:2 のべき乗を利用したバディシステム
  • dlmalloc:Doug Lea の malloc の移植版
  • talc:高速で、組み込み用途に適しています
4. パニックハンドラー

no_std では、Rust が必須としているパニックハンドラーを用意する必要があります。

// Option 1: halt on panic (simplest, production)
use core::panic::PanicInfo;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}  // spin forever
}

// Option 2: print panic info via defmt (embedded with debug probe)
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
    defmt::error!("{}", defmt::Display2Format(info));
    cortex_m::asm::udf();  // undefined instruction → hard fault
}

// Option 3: use a panic crate (in Cargo.toml)
// panic-halt = "0.2"   — spin loop
// panic-reset = "0.1.1" — reset MCU
// panic-probe = "0.3"   — defmt + probe-rs
5. 移植性のある no_std ライブラリーの作成

alloc の有無にかかわらず動作するように、ライブラリーを設計します。

#![no_std]
#[cfg(feature = "alloc")]
extern crate alloc;

pub struct Parser<'a> {
    data: &'a [u8],         // borrowed slice: no allocation needed
    pos: usize,
}

impl<'a> Parser<'a> {
    pub fn new(data: &'a [u8]) -> Self {
        Parser { data, pos: 0 }
    }

    // Core API: return borrowed data, no allocation
    pub fn next_token(&mut self) -> Option<&'a [u8]> { /* ... */ None }

    // Alloc API: only when alloc feature is enabled
    #[cfg(feature = "alloc")]
    pub fn collect_all(&mut self) -> alloc::vec::Vec<&'a [u8]> {
        let mut tokens = alloc::vec::Vec::new();
        while let Some(tok) = self.next_token() {
            tokens.push(tok);
        }
        tokens
    }
}
6. ホストでの no_std のテスト
# Cargo.toml
[dev-dependencies]
std = []   # allow std in tests only (via cfg)

[features]
std = []
// lib.rs
#![cfg_attr(not(test), no_std)]  // no_std except during tests
// Tests compile normally with std — only library code is no_std

または、別のテストハーネスを使用します。

# Run tests targeting the host (std available for test framework)
cargo test --target x86_64-unknown-linux-gnu

# Test with the actual embedded target using QEMU
cargo test --target thumbv7em-none-eabihf  # fails: no test runner on bare metal

# Solution: use defmt-test or probe-run for on-target testing
# Or: architecture-neutral pure logic tests on host
# Check no_std compliance without hardware
cargo check --target thumbv7em-none-eabihf
cargo build --target thumbv7em-none-eabihf

関連スキル

  • no_std で probe-rs、defmt、RTIC を使う場合は、skills/embedded/embedded-rust を使用してください
  • クロスコンパイルのターゲット設定については、skills/rust/rust-cross を使用してください
  • アロケーター実装で必要となる unsafe パターンについては、skills/rust/rust-unsafe を使用してください
  • ベアメタルターゲットでのヒープ領域の配置については、skills/embedded/linker-scripts を使用してください

コメント