目标读者:熟悉 C 语言的嵌入式工程师,希望学习 Rust 嵌入式开发,特别是 Embassy 异步框架。
书籍定位:从 C 工程师的认知出发,通过类比、对比和实践,帮助读者建立 Rust 嵌入式的完整认知体系,掌握 Embassy 框架的核心用法。
全书结构:Part 1(6 章)建立 Rust 嵌入式基础认知 → Part 2(5 章)深入 Embassy 框架核心 → Part 3(4 章)工程落地与生态全景,共 15 章 + 4 个附录。
主力平台:全书代码示例以 STM32 为主力平台(C 工程师最熟悉),RP2040/RP2350 作为辅助对比平台。
Part 1:通用基础#
Part 1 定位:从零开始建立 Rust 嵌入式的核心认知。先帮 C 工程师跨越 Rust 语言障碍,再围绕 Rust 的优势和特点展开讲解,帮助读者理解”为什么 Rust 适合嵌入式开发”,并掌握裸机开发的基础工具和概念。
学习目标:掌握 C 工程师最需要的 Rust 核心概念(所有权、trait、枚举、泛型);理解 Rust 嵌入式的核心优势(内存安全、并发安全、零成本抽象);掌握裸机工程的完整结构和工具链使用;建立并发基础概念,为 Embassy 的学习做好理论准备;理解嵌入式 Rust 的生态层次划分。
第 1 章:为什么是 Rust?——嵌入式开发的新选择#
本章要回答的问题:Rust 在嵌入式领域解决什么问题?它相比 C 有什么优势?本书的讨论范围是什么?
- 1.1 一个 C 工程师的日常
- 1.2 嵌入式语言版图
- 1.3 Rust 的核心优势
- 1.4 两种 Rust:
std环境与no_std环境 - 1.5 Rust 在嵌入式领域的采用情况(2026 年现状)
- 1.6 本书的边界与阅读前提
- 1.7 本章小结与全书预览
第 2 章:Rust 速成——C 工程师最需要的 20% 语法#
本章要回答的问题:C 工程师需要掌握哪些 Rust 概念才能读懂后续章节?这些概念和 C 的什么机制对应?
- 2.1 所有权与借用:为什么没有
malloc/free - 2.2 Trait:Rust 的”接口”与 C 的函数指针表
- 2.3 枚举与模式匹配:替代
union + switch - 2.4 泛型与单态化:为什么”模板”不会膨胀
- 2.5 错误处理:
Result替代错误码 - 2.6 闭包与迭代器:嵌入式中的零成本用法
- 2.7 模块系统与
use:替代#include - 2.8 本章小结
第 3 章:开始上路——第一个裸机工程#
本章要回答的问题:Rust 裸机工程长什么样?每个文件的作用是什么?怎么编译、烧录、调试?
- 3.1 从 C 到 Rust:工程结构的映射
- 3.2 创建项目与配置依赖
- 3.3 交叉编译与 target triple
- 3.4 配置工程文件
- 3.5
cortex-m-rt的简要说明 - 3.6 异常与中断的简要说明
- 3.7 查看编译产物
- 3.8 烧录与 RTT 输出
- 3.9 工具链层次全景图
- 3.10 Rust 库生态与使用方式
- 3.11 本章小结
第 4 章:零成本抽象——当类型系统遇见寄存器#
本章要回答的问题:Rust 的高级语法会不会让程序变慢?类型状态模式是什么?unsafe 在嵌入式中的角色是什么?
- 4.1 一个 C 工程师的合理疑虑
- 4.2 GPIO 的类型状态抽象
- 4.3 零成本抽象的编译结果
- 4.4 单例模式
- 4.5
unsafe在嵌入式中的角色 - 4.6 本章小结
第 5 章:并发基础——从轮询到抢占#
本章要回答的问题:嵌入式并发是什么?抢占式和协作式有什么区别?C 和 Rust 各自怎么处理并发?
- 5.1 并发与并行的概念
- 5.2 嵌入式并发的三种经典做法
- 5.3 抢占式调度与协作式调度
- 5.4 临界区与原子操作
- 5.5 中断的简要介绍
- 5.6 本章小结
第 6 章:可移植性与生态层次#
本章要回答的问题:embedded-hal 是什么?Rust 嵌入式生态的层次结构是怎样的?有哪些并发框架可选?
- 6.1 问题:不同芯片的外设 API 不同,驱动怎么复用?
- 6.2
embedded-hal的设计哲学 - 6.3 抽象层次结构
- 6.4 并发框架选型:Embassy vs RTIC vs 传统 RTOS
- 6.5 各平台 HAL 的 API 差异速查 ← 【新增,吸收原 13.2 内容】
- 外设命名差异对照表(UART vs UARTE vs UART0)
- DMA 配置差异(手动分配 vs EasyDMA)
- 时钟配置差异
- 中断优先级位宽差异
- 引导语:“完整的移植实操见第 13 章”
- 6.6 本章小结与 Part 1 总结
Part 2:Embassy 核心编程#
Part 2 定位:从 Embassy 的核心思想开始,逐步深入到实践、原理和生态。这是全书的核心部分,读者将完整掌握 Embassy 框架。
第 7 章:Embassy 入门——思想、对比与代价#
本章要回答的问题:Embassy 是什么?它和传统裸机开发有什么不同?用 Embassy 需要付出什么代价?
- 7.1 回顾:传统裸机并发的三种做法及其代价
- 7.2 Embassy 的核心思想
- 7.3 采用 Embassy 的代价
- 7.4 本章小结
第 8 章:第一个 Embassy 工程#
本章要回答的问题:Embassy 工程和裸机工程有什么不同?#[embassy_executor::main] 是什么?怎么使用 HAL 和定时器?
- 8.1 创建 Embassy 工程与配置 Cargo.toml
- 8.2 Embassy 工程的独特结构
- 8.3 Embassy HAL 的使用
- 8.4 DMA 与异步传输
- 8.5
embassy-time:异步定时器 - 8.6 错误处理与 Panic 行为
- 8.7 编译、烧录与 defmt 日志
- 8.8 本章小结
第 9 章:Embassy 运行时——协作与抢占#
本章要回答的问题:Embassy 的任务是怎么调度的?Future 和 Waker 是什么?协作式和抢占式有什么区别?怎么配置?
- 9.1 Future 与 Waker:异步任务的基础
- 9.2 Embassy 的 Executor 架构
- 9.3 协作式调度
- 9.4 抢占式调度
- 9.5 实战选择
- 9.6 本章小结
第 10 章:任务间通信——embassy-sync 库#
本章要回答的问题:Embassy 的任务之间怎么安全通信?Signal、Channel、Mutex 各自适合什么场景?
- 10.1 为什么需要任务间通信?
- 10.2
Signal——单生产者单消费者信号 - 10.3
Watch——多消费者信号 - 10.4
Channel——MPMC 队列 - 10.5
PriorityChannel——优先级通道 - 10.6
PubSubChannel——发布-订阅通道 - 10.7
Mutex——异步互斥锁 - 10.8 与 FreeRTOS 通信原语的完整对比表
- 10.9 常见死锁与饥饿问题
- 10.10 选型指南
- 10.11 本章小结
第 11 章:Embassy 生态与视野拓展#
本章要回答的问题:除了 embassy-sync,Embassy 生态还有哪些强大的库?我能用 Embassy 做什么?
修订说明:本章只讲 Embassy 自身组件的使用方法,不介绍各芯片平台的基本信息。平台对比和移植实操见第 13 章。
- 11.1 Embassy 生态全景
- 11.2
embassy-usb:USB 设备栈 - 11.3
embassy-net:网络协议栈 - 11.4
embassy-boot:安全 Bootloader - 11.5 蓝牙协议栈:
trouble的使用方法 ← 【修订:删除 nRF 平台介绍,只讲 crate API】 - 11.6 WiFi 协议栈:
esp-wifi的使用方法 ← 【修订:删除乐鑫战略介绍,只讲 crate API】 - 11.7 真实世界项目案例
- 11.8 社区资源与学习路径
- 11.9 Part 2 总结
Part 3:工程实践与生态全景#
Part 3 定位:从理论学习转向工程实践。帮助读者掌握调试方法论、工程组织方式、性能优化方法,了解生态全貌。
Part 3 逻辑线:构建(第 12 章)→ 调试与组织(第 13 章)→ 优化(第 14 章)→ 选型与迁移(第 15 章)
第 12 章:工具链深度——从链接脚本到调试链路#
本章要回答的问题:memory.x 里面每一行是什么意思?从 cargo build 到芯片运行之间发生了什么?调试链路是怎么构成的?
- 12.1 链接脚本是什么?
- 12.2
memory.x详解 - 12.3
cortex-m-rt深度解析 - 12.4 调试链路:从 VSCode 到芯片
- 12.5
defmt:高效的嵌入式日志框架(原理篇) - 12.6 完整链路回顾
- 12.7 本章小结
第 13 章:调试、测试与工程架构 ← 【重写】#
本章要回答的问题:异步代码怎么调试?Embassy 项目怎么组织?怎么测试?从原型到产品的工程实践是什么?
本章定位:这是全书唯一一章讲”方法论”而非”知识点”的章节。C 工程师最缺的不是 API 知识,而是”面对一个异步嵌入式系统,我该怎么思考、怎么组织、怎么排错”。
-
13.1 调试异步代码:从 GDB 思维到 async 思维
- C 工程师的调试习惯:断点 → 单步 → 看调用栈
- 异步代码的调试困境:调用栈是”扁平”的
- 心智模型转换:从”谁在调用我”到”谁在等我完成”
- 为什么 async 调用栈和 C 的调用栈完全不同
-
13.2 defmt 实战:不只是 println
- 结构化日志:用
{=u8}代替格式化字符串 - 日志级别策略:开发用 TRACE,量产用 INFO
- 用 defmt 追踪任务调度:在
.await前后打点 - 条件编译:
#[cfg(feature = "defmt")]的用法 - 与 C 的
printf+ 串口对比:体积和速度优势(实际数据)
- 结构化日志:用
-
13.3 probe-rs 调试实战
- 断点调试:在
async fn中设断点的技巧 - 查看 Future 状态:任务是在 Poll 还是 Pending?
- 内存查看:检查任务栈使用情况
- Flash 算法与烧录配置
- 与 Keil / IAR 调试体验的对比
- 断点调试:在
-
13.4 常见运行时问题诊断
- 问题 1:任务”卡死”——忘记
.await或死循环不让出 - 问题 2:任务”饿死”——高优先级任务独占 CPU
- 问题 3:Channel 死锁——生产者等消费者,消费者等生产者
- 问题 4:栈溢出——静态栈没有保护,溢出即 HardFault
- 问题 5:Panic 后系统行为——看门狗复位 vs 停机
- 每个问题的诊断方法和修复方案
- 问题 1:任务”卡死”——忘记
-
13.5 Embassy 项目的工程架构
- C 工程的典型分层:main → app → hal → driver
- Rust 工程的推荐分层
- 模块间通信:用 Channel/Signal 代替全局变量
- 与 C 的”全局变量 + 回调”模式的对比
- 大型项目的 Workspace 组织
-
13.6 测试策略
- 单元测试:
#[cfg(test)]在no_std下的用法 - 驱动测试:Mock
embedded-haltrait - 硬件在环测试(HIL):probe-rs 的测试集成
- 集成测试:在真实硬件上跑
cargo test - 与 C 的 Unity / Ceedling 对比
- 单元测试:
-
13.7 从原型到产品的检查清单
- 看门狗配置
- 低功耗模式(Sleep / Stop / Standby)
- OTA 更新策略(引用第 11 章 embassy-boot)
- 日志与错误上报
- 版本管理与固件签名
- 生产烧录流程
-
13.8 本章小结
第 14 章:性能与体积优化#
本章要回答的问题:如何控制固件体积?如何优化性能?异步运行时的开销有多大?常见的陷阱和解决方案是什么?
- 14.1 编译优化配置
- 14.2 代码体积分析
- 14.3 异步运行时的开销分析
- 14.4 运行时性能优化
- 14.5 常见陷阱与解决方案
- 陷阱 1:在
.await循环中忘记yield - 陷阱 2:任务栈溢出(静态分配的栈没有保护)
- 陷阱 3:
defmt日志在 Release 模式下的体积影响 - 陷阱 4:泛型单态化导致的代码膨胀
- 陷阱 5:
Mutex持有时间过长 - 陷阱 6:跨平台移植中的时钟/DMA/GPIO 差异 ← 【新增,吸收原 13.7 内容】
- 陷阱 1:在
- 14.6 本章小结
第 15 章:生态全景与库推荐#
本章要回答的问题:除了 Embassy,Rust 嵌入式生态还有哪些重要的库?不同场景下怎么选型?安全关键领域怎么用 Rust?全书如何总结?
- 15.1 静态存储与延迟初始化
- 15.2 无堆分配的数据结构
- 15.3 测试与质量保证(引用第 13 章,此处讲 CI/CD 和静态分析)
- 15.4 安全关键与功能认证
- 15.5 从 C 项目迁移到 Rust 的策略
- 15.6 选型决策框架 ← 【修订:改为决策框架,吸收原 13.8 内容】
- 按应用场景的决策树
- 按团队经验的决策树
- 按平台特性的决策树
- 各平台生态对比总表
- 15.7 给 C 工程师的最后建议
- 15.8 全书总结