知识门户

返回

嵌入式 Rust 编程:C 工程师的 Embassy 入门与进阶

Part0 大纲

《嵌入式 Rust 编程:C 工程师的 Embassy 入门与进阶》#

目标读者:熟悉 C 语言的嵌入式工程师,希望学习 Rust 嵌入式开发,特别是 Embassy 异步框架。

书籍定位:从 C 工程师的认知出发,通过类比、对比和实践,帮助读者建立 Rust 嵌入式的完整认知体系,掌握 Embassy 框架的核心用法。

全书结构:Part 1(6 章)建立 Rust 嵌入式基础认知 → Part 2(5 章)深入 Embassy 框架核心 → Part 3(4 章)工程落地与生态全景,共 15 章 + 4 个附录。

主力平台:全书代码示例以 STM32 为主力平台(C 工程师最熟悉),RP2040/RP2350 作为辅助对比平台。

与现有资源的区别

资源定位与本书的关系
The Embedded Rust Book(官方)通用入门,不针对特定读者群本书可作为其”C 工程师视角”的补充
MicroRustmicro:bit 入门,面向零基础本书假设读者有嵌入式经验,起点更高
DigiKey 教程系列碎片化实践教程本书提供完整体系
本书C 工程师 → Embassy 的系统路径填补中文市场空白

Part 1:通用基础#

Part 1 定位:从零开始建立 Rust 嵌入式的核心认知。先帮 C 工程师跨越 Rust 语言障碍,再围绕 Rust 的优势和特点展开讲解,帮助读者理解”为什么 Rust 适合嵌入式开发”,并掌握裸机开发的基础工具和概念。

学习目标:掌握 C 工程师最需要的 Rust 核心概念(所有权、trait、枚举、泛型);理解 Rust 嵌入式的核心优势(内存安全、并发安全、零成本抽象);掌握裸机工程的完整结构和工具链使用;建立并发基础概念,为 Embassy 的学习做好理论准备;理解嵌入式 Rust 的生态层次划分。

第 1 章:为什么是 Rust?——嵌入式开发的新选择#

本章要回答的问题:Rust 在嵌入式领域解决什么问题?它相比 C 有什么优势?本书的讨论范围是什么?

  • 1.1 一个 C 工程师的日常
    • 野指针、缓冲区溢出、数据竞争——那些”理论上不该出现”的 bug
    • 一个真实案例:并发 bug 如何在量产固件中潜伏三年
  • 1.2 嵌入式语言版图
    • C 的统治地位与历史原因
    • C++ 在嵌入式中的尴尬处境
    • MicroPython / Lua 等脚本语言的适用边界
    • Rust 的定位:系统级语言,但更安全
  • 1.3 Rust 的核心优势
    • 内存安全:没有 malloc/free,没有悬垂指针
    • 并发安全:编译器阻止数据竞争
    • 零成本抽象:高级语法,底层性能
    • 与 C 的互操作性:FFI 与混合编程
  • 1.4 两种 Rust:std 环境与 no_std 环境
    • 什么是 no_std?为什么嵌入式需要它?
    • coreallocstd 三层标准库
    • 与 C 的”裸机 vs Linux 应用”类比
  • 1.5 Rust 在嵌入式领域的采用情况(2026 年现状)
    • 行业数据:Rust 首次进入 TIOBE 前十(2026 年 7 月,1.34%)
    • 全球超过六成科技企业已将 Rust 纳入技术路线图
    • Ferrocene 通过 ISO 26262 ASIL D 认证——安全关键领域的里程碑
    • 乐鑫(Espressif)将 Rust 提升为官方一等 SDK,Embassy 为默认框架
    • Rust 1.94:6 倍编译速度提升 + 29 项 RISC-V 特性稳定化
    • Linux 内核中的 Rust 驱动(从实验到生产)
  • 1.6 本书的边界与阅读前提
    • 本书覆盖:裸机 Rust + Embassy 异步框架
    • 本书不覆盖:Linux 应用 Rust、Rust Web 开发、Rust 编译器原理
    • 阅读前提:熟悉 C 语言、了解基本嵌入式概念(寄存器、中断、外设)
    • 不要求:预先掌握 Rust(第 2 章会速成)
  • 1.7 本章小结与全书预览

第 2 章:Rust 速成——C 工程师最需要的 20% 语法#

本章要回答的问题:C 工程师需要掌握哪些 Rust 概念才能读懂后续章节?这些概念和 C 的什么机制对应?

本章定位:这不是完整的 Rust 教程,而是”C 工程师的最小必要知识集”。只讲后续章节会用到的概念,用 C 的类比帮助理解。

  • 2.1 所有权与借用:为什么没有 malloc/free
    • C 的痛点:谁负责 free
    • Rust 的所有权规则:每个值有且仅有一个所有者
    • 借用(&&mut):类比 C 的指针,但有编译期约束
    • 生命周期:编译器如何保证引用有效
    • 实际代码对比:C 的链表 vs Rust 的 Vec
  • 2.2 Trait:Rust 的”接口”与 C 的函数指针表
    • C 的做法:struct + 函数指针(模拟面向对象)
    • Rust 的 Trait:编译期多态 vs 运行时多态
    • impl Trait for Type:为类型实现行为
    • 与 C 的回调函数表对比
  • 2.3 枚举与模式匹配:替代 union + switch
    • C 的 enum:只是整数常量
    • Rust 的 enum:可以携带数据(代数数据类型)
    • Option<T>:替代 NULL 指针
    • match:比 switch 更强大的模式匹配
    • 实际代码对比:C 的错误码 vs Rust 的 Result
  • 2.4 泛型与单态化:为什么”模板”不会膨胀
    • C 的”泛型”:void* 或宏
    • C++ 的模板:编译期代码生成
    • Rust 的泛型:单态化(monomorphization)
    • 为什么嵌入式中泛型不会导致代码膨胀(编译器优化)
  • 2.5 错误处理:Result 替代错误码
    • C 的做法:返回 -1,检查 errno
    • Rust 的 Result<T, E>:错误是值,不是异常
    • ? 操作符:优雅的错误传播
    • panic!:不可恢复错误(类比 C 的 assert + abort
  • 2.6 闭包与迭代器:嵌入式中的零成本用法
    • C 的函数指针 vs Rust 的闭包
    • 迭代器链:编译器会优化为与手写循环相同的代码
    • 在嵌入式中的典型用法:mapfilterfor_each
  • 2.7 模块系统与 use:替代 #include
    • C 的 #include:文本替换
    • Rust 的 mod + use:命名空间与可见性
    • pub 与封装:比 static 更精细的访问控制
  • 2.8 本章小结
    • 速查表:C → Rust 概念对照(见附录 A)
    • 后续章节中会遇到的 Rust 特性预告
    • 推荐深入学习资源

第 3 章:开始上路——第一个裸机工程#

本章要回答的问题:Rust 裸机工程长什么样?每个文件的作用是什么?怎么编译、烧录、调试?

  • 3.1 从 C 到 Rust:工程结构的映射
    • C 工程:main.c + startup.s + linker.ld + Makefile
    • Rust 工程:main.rs + memory.x + Cargo.toml + .cargo/config.toml
    • 逐项对照表
  • 3.2 创建项目与配置依赖
    • cargo new 与项目模板
    • Cargo.toml 中的关键依赖:cortex-m-rtpanic-haltdefmt
    • Feature flag 的概念(类比 C 的 #ifdef
  • 3.3 交叉编译与 target triple
    • 什么是 target triple?(thumbv7em-none-eabihf 的含义)
    • 与 C 的交叉编译工具链对比(arm-none-eabi-gcc
    • rustup target add.cargo/config.toml 配置
  • 3.4 配置工程文件
    • .cargo/config.toml:默认 target、runner、rustflags
    • memory.x:简要说明(详细内容见第 12 章)
    • build.rs:构建脚本的作用
  • 3.5 cortex-m-rt 的简要说明
    • 它做了什么:设置向量表、定义入口点 Reset_Handler、初始化 .bss
    • 与 C 的 startup.s 的对应关系
    • 深度解析留到第 12 章
  • 3.6 异常与中断的简要说明
    • #[exception]#[interrupt]
    • 与 C 的中断服务函数对比
    • 优先级配置的基本概念
  • 3.7 查看编译产物
    • cargo build --release
    • cargo size:查看 Flash 和 RAM 占用
    • cargo objdump:反汇编查看
    • 与 C 的 arm-none-eabi-size / objdump 对比
  • 3.8 烧录与 RTT 输出
    • probe-rs:新一代调试探针工具
    • cargo run 一键编译 + 烧录 + 日志
    • RTT(Real-Time Transfer)原理
    • 与 C 的 OpenOCD + GDB 流程对比
  • 3.9 工具链层次全景图
    • 从源码到芯片的完整链路概览
    • 各层工具的职责(详细展开在第 12 章)
  • 3.10 Rust 库生态与使用方式
    • crates.io:Rust 的包管理器
    • 与 C 的”手动下载源码 + 加入工程”对比
    • 版本管理与 Cargo.lock
  • 3.11 本章小结

第 4 章:零成本抽象——当类型系统遇见寄存器#

本章要回答的问题:Rust 的高级语法会不会让程序变慢?类型状态模式是什么?unsafe 在嵌入式中的角色是什么?

  • 4.1 一个 C 工程师的合理疑虑
    • “这么多抽象层,编译出来不会比 C 慢吧?”
    • 用数据说话:同一功能的 C 代码 vs Rust 代码的反汇编对比
  • 4.2 GPIO 的类型状态抽象
    • C 的做法:直接操作寄存器地址
    • Rust 的做法:Pin<Output<PushPull>> 类型状态
    • 类型状态模式:用类型编码硬件状态,编译期阻止非法操作
    • 代码对比:C 的”忘记配置 GPIO 模式”vs Rust 的”编译不通过”
  • 4.3 零成本抽象的编译结果
    • 反汇编对比:类型状态 Rust 代码 vs 直接寄存器操作 C 代码
    • 结论:生成的机器码完全相同
    • 与 C 的 inline 函数和 #define 宏的对比
  • 4.4 单例模式
    • 为什么外设是单例?(一个芯片只有一个 GPIOA)
    • C 的做法:全局变量 + 约定
    • Rust 的做法:take() / Peripherals 单例
    • 编译期保证:不可能同时获取两个 GPIOA
  • 4.5 unsafe 在嵌入式中的角色
    • 什么时候必须用 unsafe?(直接寄存器操作、DMA 缓冲区、FFI)
    • unsafe 不是”关闭检查”,而是”我向编译器保证”
    • 最佳实践:将 unsafe 封装在安全 API 内部
    • 与 C 的对比:C 中”所有代码都是 unsafe 的”
  • 4.6 本章小结

第 5 章:并发基础——从轮询到抢占#

本章要回答的问题:嵌入式并发是什么?抢占式和协作式有什么区别?C 和 Rust 各自怎么处理并发?

本章定位:严格限定在概念层面,不涉及 Rust/Embassy 的具体实现。为第 9 章(Embassy 运行时)做理论准备。

  • 5.1 并发与并行的概念
    • 并发:多个任务”交替执行”(单核 MCU 的常态)
    • 并行:多个任务”同时执行”(多核 MCU)
    • 为什么单核 MCU 也需要并发?(响应性 + 吞吐量)
  • 5.2 嵌入式并发的三种经典做法
    • 超级循环(Super Loop):最简单,但响应性差
    • 中断驱动:响应性好,但逻辑碎片化
    • RTOS:功能完整,但引入复杂性和资源开销
    • 各方案的适用场景与代价
  • 5.3 抢占式调度与协作式调度
    • 抢占式:调度器强制切换(RTOS 的典型做法)
    • 协作式:任务主动让出(状态机的本质)
    • 各自的优缺点
  • 5.4 临界区与原子操作
    • 什么是竞态条件?(用 C 代码举例)
    • 临界区:关中断保护共享资源
    • 原子操作:无锁的并发原语
    • C 的做法:__disable_irq() / __enable_irq()
    • Rust 的对应:critical-section crate / core::sync::atomic
  • 5.5 中断的简要介绍
    • 中断的本质:硬件触发的函数调用
    • 中断优先级与嵌套
    • 中断中的限制:不能阻塞、不能分配内存
    • 与后续 Embassy 中断处理的关联预告
  • 5.6 本章小结

第 6 章:可移植性与生态层次#

本章要回答的问题embedded-hal 是什么?Rust 嵌入式生态的层次结构是怎样的?有哪些并发框架可选?

  • 6.1 问题:不同芯片的外设 API 不同,驱动怎么复用?
    • C 的困境:STM32 HAL 和 nRF SDK 的 API 完全不同
    • 驱动开发者的痛苦:每换一个平台就要重写
  • 6.2 embedded-hal 的设计哲学
    • 核心思想:定义 trait(接口),不定义实现
    • embedded-hal 1.0 的关键变化:引入 async trait
    • 与 C 的”函数指针表”类比
    • 实际例子:一个 embedded-hal 兼容的传感器驱动
  • 6.3 抽象层次结构
    • 完整层次图:芯片 → PAC → HAL → embedded-hal → 驱动 → 应用
    • 各层的职责与边界
    • 与 C 生态的对应:CMSIS → 厂商 HAL → 第三方驱动 → 应用
  • 6.5 并发框架选型:Embassy vs RTIC vs 传统 RTOS
    • Embassy:异步协作式,适合 I/O 密集型
    • RTIC:中断驱动抢占式,适合硬实时场景
    • 传统 RTOS 绑定(FreeRTOS-rs 等):适合已有 RTOS 经验迁移
    • 三者对比表:调度模型、实时性、学习曲线、生态成熟度
    • 本书选择 Embassy 的理由
  • 6.6 本章小结与 Part 1 总结
    • Part 1 知识图谱回顾
    • 从 Part 1 到 Part 2 的桥梁:为什么 Embassy 是”下一步”

Part 2:Embassy 核心编程#

Part 2 定位:从 Embassy 的核心思想开始,逐步深入到实践、原理和生态。这是全书的核心部分,读者将完整掌握 Embassy 框架。

学习目标:理解 Embassy 的范式转变及其代价;掌握 Embassy 工程的创建、HAL 使用、运行时调度、任务间通信等核心技能;对 Embassy 生态(USB、网络、蓝牙、Bootloader)有完整认知。

第 7 章:Embassy 入门——思想、对比与代价#

本章要回答的问题:Embassy 是什么?它和传统裸机开发有什么不同?用 Embassy 需要付出什么代价?

  • 7.1 回顾:传统裸机并发的三种做法及其代价
    • 超级循环:简单但无法高效等待
    • 中断驱动:响应快但逻辑碎片化
    • RTOS:功能全但资源开销大
    • 共同痛点:C 语言缺乏安全的并发抽象
  • 7.2 Embassy 的核心思想
    • 异步/等待(async/await):用同步的写法实现并发
    • 零开销:没有 RTOS 内核,没有上下文切换
    • 编译期安全:Rust 类型系统保证并发正确性
    • 与 C 状态机的对比:Embassy 是”编译器帮你写状态机”
  • 7.3 采用 Embassy 的代价
    • 学习曲线:async/await + Future 的心智模型
    • 编译时间:Rust 编译比 C 慢
    • 生态限制:并非所有 C 库都有 Rust 等价物
    • 调试复杂度:异步调用栈比同步更难追踪
    • 硬实时限制:协作式调度不适合严格截止时间的场景
  • 7.4 本章小结

第 8 章:第一个 Embassy 工程#

本章要回答的问题:Embassy 工程和裸机工程有什么不同?#[embassy_executor::main] 是什么?怎么使用 HAL 和定时器?

  • 8.1 创建 Embassy 工程与配置 Cargo.toml
    • 与裸机工程的依赖差异
    • 关键依赖:embassy-executorembassy-timeembassy-stm32
    • Feature flag 配置:芯片型号、时钟源、外设使能
  • 8.2 Embassy 工程的独特结构
    • #[embassy_executor::main] 宏做了什么?
    • Spawner:任务生成器
    • 与裸机 #[cortex_m_rt::entry] 的对比
  • 8.3 Embassy HAL 的使用
    • GPIO:OutputInput 的异步版本
    • UART:异步读写
    • SPI / I2C:异步传输
    • 与裸机 HAL 的 API 对比
  • 8.4 DMA 与异步传输
    • DMA 的本质:让外设自己搬数据,CPU 去做别的事
    • C 的 DMA:配置 + 中断回调
    • Embassy 的 DMA:await 一个传输完成
    • 实际例子:UART DMA 接收
    • 为什么 DMA 是 Embassy 异步模型的最佳搭档
  • 8.5 embassy-time:异步定时器
    • Timer::after_millis():非阻塞延时
    • 与 C 的 HAL_Delay() 对比:不阻塞 CPU
    • Ticker:周期性任务
    • 时间驱动源配置
  • 8.6 错误处理与 Panic 行为
    • Embassy 中的 Result 处理
    • panic 在嵌入式中意味着什么?
    • defmt::panic 配置
    • 看门狗与故障恢复策略
  • 8.7 编译、烧录与 defmt 日志
    • cargo run 一键流程
    • defmt 日志级别与过滤
    • 与 C 的 printf + 串口对比
  • 8.8 本章小结

第 9 章:Embassy 运行时——协作与抢占#

本章要回答的问题:Embassy 的任务是怎么调度的?Future 和 Waker 是什么?协作式和抢占式有什么区别?怎么配置?

  • 9.1 Future 与 Waker:异步任务的基础
    • Future 是什么?(一个”尚未完成的计算”)
    • 与 C 状态机的类比:Future = 状态机的编译期版本
    • Waker:谁来唤醒一个等待中的任务?
    • poll 模型:调度器如何驱动 Future
  • 9.2 Embassy 的 Executor 架构
    • Executor 的职责:轮询所有就绪的 Future
    • 任务(Task):#[embassy_executor::task]
    • 任务栈:静态分配,编译期确定大小
    • 与 RTOS 调度器的对比:没有上下文切换
  • 9.3 协作式调度
    • 工作原理:任务在 .await 点主动让出
    • 优点:零开销、确定性
    • 缺点:一个任务不让出,其他任务饿死
    • 适用场景:I/O 密集型、大多数嵌入式应用
  • 9.4 抢占式调度
    • Embassy 的抢占式:基于中断优先级
    • 配置方法:InterruptExecutor
    • 与 RTOS 抢占式的区别:仍然没有上下文切换
    • 适用场景:需要硬实时响应的关键任务
  • 9.5 实战选择
    • 决策树:什么时候用协作式?什么时候用抢占式?
    • 混合使用:高优先级任务抢占 + 低优先级任务协作
    • 常见误区:不要为了”实时性”盲目使用抢占式
  • 9.6 本章小结

第 10 章:任务间通信——embassy-sync#

本章要回答的问题:Embassy 的任务之间怎么安全通信?SignalChannelMutex 各自适合什么场景?

  • 10.1 为什么需要任务间通信?
    • 任务隔离:每个任务有自己的栈和状态
    • 共享数据的需求:传感器数据 → 处理任务 → 通信任务
    • 与 C 的全局变量 + 中断回调对比
  • 10.2 Signal——单生产者单消费者信号
    • 语义:最新的值覆盖旧值
    • 与 C 的 volatile 标志位对比
    • 适用场景:状态通知、最新值传递
  • 10.3 Watch——多消费者信号
    • 语义:多个读者观察同一个值的变化
    • 与 C 的”多个中断读取同一个全局变量”对比
    • 适用场景:配置变更通知、传感器数据广播
  • 10.4 Channel——MPMC 队列
    • 语义:生产者-消费者队列
    • 与 FreeRTOS 的 xQueueSend / xQueueReceive 对比
    • 适用场景:数据流处理、命令队列
  • 10.5 PriorityChannel——优先级通道
    • 语义:高优先级消息插队
    • 适用场景:紧急命令、报警信号
  • 10.6 PubSubChannel——发布-订阅通道
    • 语义:一对多广播,每个订阅者独立消费
    • 与 C 的回调函数列表对比
    • 适用场景:事件广播、日志分发
  • 10.7 Mutex——异步互斥锁
    • 与 C 的 pthread_mutex / FreeRTOS xSemaphore 对比
    • 异步 Mutex 的特殊性:持有锁时不能 .await(死锁风险)
    • RefCell 替代方案:单线程场景
  • 10.8 与 FreeRTOS 通信原语的完整对比表
    • Signal ↔ Task Notification
    • Channel ↔ Queue
    • Mutex ↔ Mutex Semaphore
    • PubSub ↔ Event Group(部分对应)
  • 10.9 常见死锁与饥饿问题
    • 异步 Mutex 的死锁模式(与 C 不同)
    • Channel 满/空时的阻塞行为
    • 优先级反转问题
    • 最佳实践与规避策略
  • 10.10 选型指南
    • 决策表:根据场景选择通信原语
    • 性能对比:各原语的 RAM 开销和延迟
  • 10.11 本章小结

第 11 章:Embassy 生态与视野拓展#

本章要回答的问题:除了 embassy-sync,Embassy 生态还有哪些强大的库?我能用 Embassy 做什么?后续怎么深入学习?

本章定位:概览性质。每个主题只介绍”是什么 + 一个最小示例 + 去哪里深入”,不展开完整教程。

  • 11.1 Embassy 生态全景
    • 生态架构图:executor + time + sync + hal + 协议栈
    • 各组件的成熟度评估
  • 11.2 embassy-usb:USB 设备栈
    • 支持的设备类:CDC(串口)、HID(键鼠)、MSC(存储)
    • 最小示例:USB CDC 回显
    • 与 C 的 USB 库(TinyUSB、STM32 USB 库)对比
  • 11.3 embassy-net:网络协议栈
    • 支持的协议:TCP/UDP、DHCP、DNS、mDNS
    • 底层驱动:以太网、WiFi(通过 cyw43 等)
    • 最小示例:TCP echo server
    • 与 LwIP 的对比
  • 11.4 embassy-boot:安全 Bootloader
    • OTA 更新的基本流程
    • embassy-boot 的 A/B 分区方案
    • 与 C 的 MCUboot 对比
  • 11.5 蓝牙生态:troublenrf-softdevice
    • trouble:Embassy 官方的 BLE 协议栈
    • nrf-softdevice:Nordic 芯片的 SoftDevice 绑定
    • 当前成熟度与限制
  • 11.6 ESP32 与 esp-rs 生态
    • 乐鑫官方将 Embassy 作为默认异步框架
    • esp-hal + esp-wifi + esp-ble 的组合
    • 与 STM32 生态的成熟度对比
  • 11.7 真实世界项目案例
    • 开源项目推荐与分析
    • 从原型到产品的考量
  • 11.8 社区资源与学习路径
    • 官方文档、Matrix 聊天室、GitHub Discussions
    • 推荐的进阶学习顺序
    • 中文社区资源
  • 11.9 Part 2 总结
    • Part 2 知识图谱回顾
    • 从”会用 Embassy”到”理解 Embassy”的桥梁

Part 3:工程实践与生态全景#

Part 3 定位:从理论学习转向工程实践。帮助读者理解工具链的每一层、学会跨平台移植、掌握性能优化方法、了解生态全貌。

学习目标:理解从源码到芯片运行的完整链路;了解各厂商 HAL 的成熟度差异,掌握移植的基本思路;掌握性能与体积优化方法;对 Rust 嵌入式生态有完整认知,知道后续学习和使用的方向。

第 12 章:工具链深度——从链接脚本到调试链路#

本章要回答的问题memory.x 里面每一行是什么意思?从 cargo build 到芯片运行之间发生了什么?调试链路是怎么构成的?

  • 12.1 链接脚本是什么?
    • C 工程师熟悉的 linker.ld
    • Rust 中链接脚本的角色
    • memory.x 与主链接脚本的关系
  • 12.2 memory.x 详解
    • MEMORY 段:FLASH 和 RAM 的地址与大小
    • 如何从芯片 datasheet 中获取这些信息
    • 多 Bank Flash 的处理
    • 实际例子:STM32F407 的 memory.x
  • 12.3 cortex-m-rt 深度解析
    • 向量表的生成
    • Reset_Handler 的完整流程:.data 初始化、.bss 清零、调用 main
    • 与 C 的 startup.s 逐行对比
    • 中断向量的注册机制
  • 12.4 调试链路:从 VSCode 到芯片
    • 完整链路:VSCode → probe-rs → SWD/JTAG → 芯片
    • probe-rs 的角色:替代 OpenOCD + GDB
    • 断点、单步、变量查看
    • 与 C 的 Keil / IAR 调试体验对比
  • 12.5 defmt:高效的嵌入式日志框架
    • 为什么不用 println!?(no_std 没有标准输出)
    • defmt 的原理:日志格式在主机端解析,固件只传索引
    • 与 C 的 printf + 串口对比:体积和速度优势
    • 日志级别与运行时过滤
  • 12.6 完整链路回顾
    • cargo build 到芯片运行的每一步
    • 全景图:rustc → LLVM → linker → probe-rs → 芯片
    • 各层可替换性说明
  • 12.7 本章小结

第 13 章:多平台移植与厂商生态#

本章要回答的问题:Embassy 支持哪些芯片?各厂商的支持程度如何?从一个平台移植到另一个平台需要改什么?

  • 13.1 Embassy 支持的芯片平台概览
    • 官方支持 vs 社区支持
    • 各平台的成熟度评级
  • 13.2 STM32:最成熟的 Embassy HAL
    • 支持的系列:F0/F1/F2/F3/F4/F7/H7/L0/L1/L4/L5/G0/G4/U5/WB/WL
    • 外设覆盖度
    • 已知限制与 workaround
    • 为什么推荐 C 工程师从 STM32 开始
  • 13.3 nRF:无线功能的旗舰支持
    • nRF52 / nRF53 / nRF54 系列
    • BLE、802.15.4、NFC 的支持
    • nrf-softdevicetrouble 的选择
  • 13.4 RP2040/RP2350:性价比之选
    • 双核 Cortex-M0+ / 双核 Cortex-M33 + RISC-V
    • PIO(Programmable I/O)的 Rust 支持
    • 社区活跃度与文档质量
  • 13.5 ESP32:官方一等支持的 Rust 生态
    • 乐鑫 esp-rs 生态:esp-hal + esp-wifi + esp-ble
    • Embassy 作为默认异步框架
    • 支持的芯片:ESP32 / S2 / S3 / C3 / C6 / H2
    • 与 STM32 生态的差异(Xtensa vs RISC-V 工具链)
  • 13.6 RISC-V 平台的新机遇
    • Rust 1.94 稳定了 29 项 RISC-V 特性
    • 支持的 RISC-V 芯片:ESP32-C3/C6/H2、CH32V、GD32V 等
    • RISC-V 对 Rust 嵌入式的战略意义
  • 13.7 平台移植指南
    • 移植清单:需要修改的文件和配置
    • HAL API 差异的处理
    • 时钟配置的差异
    • 实际案例:从 STM32F4 移植到 nRF52
  • 13.8 本章小结

第 14 章:性能与体积优化#

本章要回答的问题:如何控制固件体积?如何优化性能?异步运行时的开销有多大?常见的陷阱和解决方案是什么?

  • 14.1 编译优化配置
    • [profile.release] 关键配置:opt-levelltocodegen-units
    • panic = "abort":移除 unwind 代码
    • stripdebug 配置
    • 与 C 的 -Os / -O2 / -flto 对比
  • 14.2 代码体积分析
    • cargo sizecargo bloat
    • 各部分的体积占比:应用代码 vs HAL vs 运行时
    • 与同等功能 C 代码的体积对比(实际数据)
    • 减小体积的实用技巧
  • 14.3 异步运行时的开销分析
    • Embassy Executor 的 RAM 开销
    • 每个任务的栈开销
    • .await 的运行时成本(答案:几乎为零)
    • 与 RTOS 的资源开销对比
    • 与裸机轮询的性能对比
  • 14.4 运行时性能优化
    • 关键路径的优化策略
    • #[inline]#[inline(always)]
    • DMA 减少 CPU 负载
    • 中断优先级调优
  • 14.5 常见陷阱与解决方案
    • 陷阱 1:在 .await 循环中忘记 yield
    • 陷阱 2:任务栈溢出(静态分配的栈没有保护)
    • 陷阱 3:defmt 日志在 Release 模式下的体积影响
    • 陷阱 4:泛型单态化导致的代码膨胀
    • 陷阱 5:Mutex 持有时间过长
  • 14.6 本章小结

第 15 章:生态全景与库推荐#

本章要回答的问题:除了 Embassy,Rust 嵌入式生态还有哪些重要的库?不同场景下怎么选型?安全关键领域怎么用 Rust?全书如何总结?

  • 15.1 静态存储与延迟初始化
    • static mut 的问题与替代方案
    • once_cell / lazy_staticno_std 中的用法
    • portable-atomic:在无原子指令的 MCU 上使用原子操作
    • critical-section:跨平台的临界区抽象
  • 15.2 无堆分配的数据结构
    • heapless:固定容量的 VecStringQueue
    • arrayvec:栈上的数组向量
    • 与 C 的固定数组 + 手动管理对比
    • 选型建议:什么时候用哪个
  • 15.3 测试与质量保证
    • 单元测试:#[cfg(test)]no_std 下的用法
    • 硬件在环测试(HIL):probe-rs 的测试集成
    • Embassy 项目的 CI/CD 配置
    • 静态分析:clippymiri
    • 与 C 的 Unity / Ceedling 测试框架对比
  • 15.4 安全关键与功能认证
    • Ferrocene:通过 ISO 26262 ASIL D 认证的 Rust 工具链
    • Eclipse S-CORE:面向汽车的安全 Rust 运行时
    • Rust 官方安全关键路线图
    • 对 C 工程师的启示:Rust 在安全关键领域的未来
    • 当前限制:不是所有场景都适合
  • 15.5 从 C 项目迁移到 Rust 的策略
    • 渐进式迁移:FFI 桥接,逐模块替换
    • 全新开发:从头用 Rust 重写
    • 混合编程:C 库的 Rust 绑定(bindgen
    • 决策框架:什么时候迁移?什么时候不迁移?
  • 15.6 选型建议
    • 按场景推荐:IoT 传感器 / 电机控制 / 通信网关 / 安全关键
    • 按团队推荐:个人项目 / 小团队 / 企业级
    • 按平台推荐:STM32 / nRF / ESP32 / RP2040
  • 15.7 给 C 工程师的最后建议
    • 不要试图写”C 风格的 Rust”
    • 拥抱编译器:错误信息是你的朋友
    • 从小项目开始:LED → UART → 传感器 → 完整产品
    • 加入社区:Rust 嵌入式社区非常友好
  • 15.8 全书总结
    • 知识体系回顾
    • 从第 1 章到第 15 章的成长路径
    • 嵌入式 Rust 的未来展望

附录#

附录 A:C → Rust 语法速查表#

  • 数据类型对照
  • 控制流对照
  • 指针/引用对照
  • 结构体/枚举对照
  • 函数/宏对照
  • 内存管理对照
  • 并发原语对照

附录 B:常用 Cargo 配置与 Feature Flag 速查#

  • .cargo/config.toml 模板
  • 常用 Cargo.toml 配置
  • Embassy 各 crate 的 Feature Flag 说明
  • 编译优化配置模板

附录 C:Embassy 常见编译错误与解决方案#

  • 生命周期错误
  • Send / Sync 约束错误
  • Feature flag 冲突
  • 链接错误
  • 各错误的含义与修复方法

附录 D:推荐硬件与调试器清单#

  • 开发板推荐(按平台分类)
  • 调试探针推荐(ST-Link、J-Link、DAPLink)
  • 必备配件
  • 购买建议