mcpField
R
rust-no-std

rust-no-std

github.com/mohitmishra786开发269484 次安装18 周前更新
代码仓库

关于 rust-no-std

面向开发或调试 `#![no_std]` 库和裸机固件的 Rust 开发者,说明 `core` 与 `alloc` 的边界、分配器和 panic 处理程序设置,以及主机端测试。

主要功能

  1. 01比较 core、alloc 和 std
  2. 02设置全局分配器
  3. 03选择 no_std panic 处理程序
  4. 04设计支持可选 alloc 的库
  5. 05在主机上测试 no_std crate

适用场景

  1. 01构建不依赖 std 的解析器
  2. 02在 no_std 环境中使用 Vec
  3. 03在笔记本上测试 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

用途

指导 Agent 进行 #![no_std] Rust 开发:了解 core 和 alloc 相较于 std 提供的功能、实现自定义全局分配器、为嵌入式目标选择 panic 处理程序,以及在主机上测试 no_std crate 的策略。

适用场景

编写或调试 #![no_std] Rust 代码时使用此技能,包括面向嵌入式目标的库 crate,或无法链接 std 的裸机固件。关于完整的嵌入式开发工作流(probe-rs 刷写、defmt 日志记录、RTIC),请使用 skills/embedded/embedded-rust。关于交叉编译目标设置,请使用 skills/rust/rust-cross。此技能专门介绍 no_std / core / alloc 的边界以及 panic 处理程序的选择。

示例

  • “我需要一个不依赖 std 的解析器 crate” → 使用 #![no_std] 构建,将 alloc API 设为可选功能,核心 API 使用借用切片
  • “如何在 no_std 环境中使用 Vec?” → 添加 alloc 功能,提供全局分配器(例如 linked-list-allocator),使用 alloc::vec::Vec
  • “如何在笔记本电脑上测试 no_std crate?” → 使用 #![cfg_attr(not(test), no_std)],以便在测试模式下启用 std;或者使用 cargo test --target x86_64-unknown-linux-gnu

工作流

1. no_std crate 结构
// 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 的区别
Crate需要操作系统需要堆提供内容
core否否基本类型、trait、迭代器、fmt、mem、ptr、slice、option、result
alloc否是(分配器)Vec、String、Box、Arc、Rc、HashMap(需要全局分配器)
std是是core + alloc 的全部内容,以及操作系统 API(线程、文件、套接字、环境变量)

std 重新导出 core 和 alloc 中的所有内容,因此在 std 可用时,use std::fmt 和 use core::fmt 等效。

仅在 core 中可用的内容(无堆、无操作系统):

// 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 crate,需提供全局分配器:

// 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);

常见的嵌入式分配器 crate:

  • linked-list-allocator:通用型,支持 no_std
  • buddy-alloc:二的幂次伙伴系统
  • dlmalloc:Doug Lea 的 malloc 移植版本
  • talc:速度快,适用于嵌入式
4. Panic 处理程序

在 no_std 中,必须提供 panic 处理程序——这是 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

相关技能

  • 使用 skills/embedded/embedded-rust,了解在 no_std 中使用 probe-rs、defmt 和 RTIC
  • 使用 skills/rust/rust-cross 设置交叉编译目标
  • 使用 skills/rust/rust-unsafe 了解分配器实现所需的不安全模式
  • 使用 skills/embedded/linker-scripts 设置裸机目标中的堆区域位置

评论

支持 Markdown