哈哈那个毕业帽Rust我刷到的时候脑子就一个念头:这哥们儿是把学位帽当开发板使了吧?我当年毕业典礼要是有这手艺,高低得在帽子上跑个RTIC调度灯带,让校长讲话的时候我的帽子能随音节闪 Morse code 发 “LET ME GRADUATE ALREADY”。
不过楼主观点的确戳到一个很少被展开聊的东西——Rust在嵌入式上真正性感的点,不是它没有GC,而是它的所有权模型把“硬件资源”抽象成了编译器能验证的契约。你想想,C里面操作GPIO,一不小心就搞出个dangling pointer指向某个已经被关掉的时钟域,debug全靠运气和示波器。Rust呢?太!一个 Pin 类型加 gpio::Output<PushPull> 这种带状态的类型参数,直接让“引脚配置错误”在编译期就炸出来,连上电的机会都不给你。突然想到这不是浪漫是啥?是编译器帮你写单元测试了属于是。
而且 embedded-hal 这套生态现在真的有点意思。之前我用 STM32F103 搞了个极小项目,想驱动一个 SPI 屏幕,只需要 embedded-graphics + st7789 两个 crate 一湊,加上 cortex-m-rt 和 panic-halt,几行代码就能画个圆。底层是 stm32f1xx-hal 提供的 Spi 结构体,实现了 embedded-hal 的 SpiBus trait,屏幕库根本不知道你用的是哪家芯片,完全是类型体操搭积木。这种解耦程度以前在 C 里得靠宏和 void 指针硬怼,现在 Rust 用 trait 和泛型零成本抽象直接优雅掉。
但说温柔,我觉得更准确说是“克制”。Rust 在 MCU 上强制你思考资源生命周期:这块内存谁拥有、谁借用、何时释放。你写的不再是“先配置再祈祷”的代码,而是“编译器替硬件审阅过的设计文档”。毕业帽那个项目能跑起来,其实背后是作者跟 borrow checker 达成了某种哲学共识:所有外设寄存器都是 &'static mut 单例,通过 cortex_m::Peripherals::take() 获取所有权,然后转移给各个驱动结构体。一旦你接受了这种世界观,硬件编程就从“和硬件斗智斗勇”变成“和类型系统对话”,对话失败还能收获一堆漂亮的错误提示,而不是随机重启。
不过得补一刀:生态虽好,但离“开箱即用”还有距离。比如我上次想接个便宜的 nRF24L01 无线模块,发现 HAL 库里对 SPI 的 CS 引脚管理方式千奇百怪,有的用 OutputPin trait,有的用 ChipSelect 新 trait,结果驱动库不兼容,最后自己 wrap 了一层 unsafe 才搞定。这种时候你就会怀念 C 的“我直接写寄存器你管我”的快意恩仇。卧槽但反过来想,正是这种社区还在快速试错的阶段,才让这些“小玩具”项目显得珍贵——它们不只是在展示技术,更是在给生态踩坑、填坑。哈哈
卧槽
说到底,Rust 在嵌入式上的浪漫不是“优雅”本身,而是它拒绝用“反正资源少随便造”当借口,坚持用类型系统为你兜底。毕业帽跑 Rust,跑的不是代码,是一种态度:哪怕只有 64KB flash,也要内存安全,也要抽象清晰,也要让硬件在编译器眼里透明得像玻璃。6这比什么高并发后端都更贴合 Rust 的初心。嘛
所以,大家最近有没有用 Rust 搞过那种“明明可以用 Arduino 十分钟解决,但偏要用 Rust 折腾一周”的神奇项目?我赌五毛,绝对有人用 Embassy 写过智能喂猫器,结果猫都饿死了项目还没编译过(笑)