能存一辈子?自制FeRam铁电存储U盘!

提到U盘,大多数人想到的是 NAND Flash,一种靠浮栅晶体管捕获电荷来存储数据的半导体存储器。

然而,NAND Flash 并非没有短板:写入速度受限于擦除块大小、读写寿命通常在 $10^4$ ~ $10^5$ 次量级,更重要的是,数据保存年限随着制程微缩而逐年下降。我们以为能存很久的数据,可能十年后就悄然消失。

那么是否存在一种存储介质,能够拥有近乎无限的读写寿命?

答案是肯定的,这便是铁电随机存取存储器(FeRAM)。

本文介绍的项目 FeRamDisk,正是基于 FeRAM 介质实现的一款专用U盘,同时记录了笔者第一次体验 Rust 语言进行嵌入式开发的完整实践。

铁电存储

铁电存储器的核心在于铁电材料,这类材料具有钙钛矿晶体结构,其中位于中心的钛离子可以在外加电场的作用下发生位移,并停留在两个稳定位置之一。当电场撤去后,钛离子不会回到原位,而是保持偏移后的状态,从而形成剩余极化,这两个不同的极化方向正好对应二进制中的0和1

1950 年代,贝尔实验室的研究人员率先在罗息盐中发现了铁电效应,随后 PZT 等陶瓷材料的问世才使这一技术具备了实用价值。然而真正商业化的 FeRAM 直到 1990 年代才由 Ramtron 公司推向市场,此后富士通、英飞凌、赛普拉斯等厂商陆续跟进,但容量和成本始终无法与 NAND Flash 抗衡,FeRAM 并没有进入大众视野。

Ramtron FM18L08-70-SG

FeRAM 的优势是显著的:写入操作无需升压电荷泵,只需施加普通工作电压即可翻转极化状态,因此写入功耗极低,写入时间通常在纳秒级别,且不需要擦除步骤。

更重要的是,铁电极化几乎不产生疲劳效应,理论读写寿命可达 $10^{14}$ 次以上,是 NAND Flash 的十亿倍,在常温存储条件下,几乎能达到 150 年以上的寿命。

不过缺点同样明显:存储密度低、制程难以微缩、且读出操作是破坏性的(读取后需重新写入)。不过对于专用场景,比如工业日志记录、金融交易存证、航天数据存储,这些特性恰好契合了高耐久、高可靠的需求。

FeRamDisk项目概述

FeRamDisk 是一款基于 STM32G431CBU6 主控与 MB85RS2MTA 存储介质的专用闪存盘。

FeRamDisk PCB 渲染图

MB85RS2MTA 是富士通出品的 SPI 接口 FeRAM 芯片,容量为 2Mbit(即 256KB),支持 40MHz 时钟频率。本项目使用了四片 MB85RS2MTA,总计达到的存储空间为 1MB。

主控选用意法半导体的 STM32G431,这是一颗 Cortex-M4F 内核的 MCU,主频可达 170MHz,内置 USB 2.0 全速控制器,适合实现 USB 大容量存储设备。

程序的运作逻辑并不复杂:通过 USB 连接主机,枚举为大容量存储设备(MSC类);主机下发 SCSI 命令,STM32G431 解析后通过 SPI 总线对 FeRAM 进行相应操作。由于 FeRAM 本身按字节随机读写且无擦除等待,整个U盘在主机侧表现为一个无需磨损均衡、写入延迟极低的块设备。

PCB 采用四层板设计,主控与 FeRAM 之间仅需数根 SPI 信号线外加片选。全部硬件资料(KiCad 工程)与固件代码均已在 GitHub 仓库开源,链接附于文末。

Rust嵌入式体验

本次开发的所有固件均使用 Rust 语言编写,依赖 Embassy 异步框架。笔者此前主要在 PC 端使用 Rust 进行 windows 平台上的应用开发,从 Cargo 到 crates.io 的生态让人印象深刻。

当转向嵌入式开发时,这种体验得以延续:无需安装庞大的 IDE(如 Keil 或 IAR),只需一条 cargo run 命令,配合同样基于 Rust开发的 probe-rs 调试器,即可完成编译、烧录、日志输出全流程。

具体而言,从零开始搭建 Rust 嵌入式环境只需几条命令,首先确保已安装 Rust 工具链,然后添加 thumbv7em-none-eabihf 目标(对应 Cortex-M4F 内核):

1
rustup target add thumbv7em-none-eabihf

接着安装 probe-rs 工具集,它集成了烧录、调试和日志输出功能,作用类似于 OpenOCD :

1
cargo install probe-rs-tools

随后在项目根目录 .cargo/config.toml 里设置编译的目标平台,就可以开始愉快的开发嵌入式了:

1
2
[build]
target = "thumbv7em-none-eabihf"

Rust 具有十分成熟的库生态,覆盖了从底层寄存器定义到高层异步框架的各个抽象层级。开发者无需关心中断向量表如何摆放,也不用手动操作外设寄存器,这些细节都被封装在精心设计的 crate 中。

例如 stm32g4xx-hal 提供了基于类型安全的外设接口,调用 I2c::new() 时会自动检查时钟是否已使能,编译阶段就能杜绝常见的配置错误。

Embassy架构

中断处理是嵌入式编程的痛点之一,像 RTOS 这类的程序框架一直在想方设法地简化开发的流程,让大型项目变得更加简单。这种方式虽然有效,却引入了任务切换开销以及复杂的同步逻辑,开发者仍需在中断上下文与任务上下文之间谨慎设计。

Embassy 框架则另辟蹊径,在 Rust 语言设计的基础上,提出了一种基于异步编程的全新嵌入式编程模型:将中断作为 Future 的唤醒源,利用执行器(Executor)在多个任务间进行协作式调度。

在 RTOS 中,中断服务函数通常需要向任务发送通知(如释放信号量),再由调度器决定何时运行接收任务,这一过程涉及两次上下文切换和至少一次队列操作。

而 Embassy 将每个中断直接绑定为一个 Future 的唤醒器:当外设触发中断时,中断处理函数仅做最轻量的事情——将对应的 Waker 唤醒,随后执行器便会恢复等待该 Future 的任务。

整个过程没有优先级抢占、没有任务状态链表、也不存在信号量等同步原语,任务切换完全发生在 await 点,由编译器生成的异步状态机自动完成。

这样使得中断处理变得非常优雅,异步代码如同线性般流畅,例如下方的 Embassy 官方例程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
use defmt::info;
use embassy_executor::Spawner;
use embassy_time::{Duration, Timer};
use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pin, Pull};
use embassy_nrf::{Peri, Peripherals};

// 声明异步任务
#[embassy_executor::task]
async fn blink(pin: Peri<'static, AnyPin>) {
let mut led = Output::new(pin, Level::Low, OutputDrive::Standard);

loop {
// 每隔 150ms 就翻转电平
led.set_high();
Timer::after_millis(150).await;
led.set_low();
Timer::after_millis(150).await;
}
}

// main 函数也需要被声明为异步
#[embassy_executor::main]
async fn main(spawner: Spawner) {
let p = embassy_nrf::init(Default::default());

// 生成一个异步执行的函数,在后台执行
spawner.spawn(blink(p.P0_13.into()).unwrap());

let mut button = Input::new(p.P0_11, Pull::Up);
loop {
// 等待按钮被按下,等效于hal库中的中断
// 否则就执行其他代码
button.wait_for_low().await;
info!("Button pressed!");
button.wait_for_high().await;
info!("Button released!");
}
}

对于 USB 协议栈这种状态机密集、等待点众多的场景,异步编程反而比 RTOS 任务更加清晰:每个端点处理函数都是一个 async fn,遇到需要等待的事件就 .await 交出控制权。

这样就以优雅的编程模型解决了前后通信过程中复杂的状态切换以及任务响应。

目前固件仍在开发过程中,存在少量问题和瑕疵,待逐步完善后再尝试复刻也不迟,还请耐心等待。

最后说点

FeRamDisk 与其说是一款实用的U盘,不如说是一次有趣的实验。

1MB 的容量在当今动辄 TB 级别的存储设备面前显得微不足道,但它充满了趣味,如果交给你一个能无限保留的U盘,你会拿它来储存些什么数据呢?

从个人技术成长的角度,这次项目让笔者品尝到了 Rust 开发的优越性。Cargo 的统一构建工具、probe-rs 的快捷调试、Embassy 的异步框架,这些工具链的组合正在重新定义嵌入式开发的体验。

当然,Rust 嵌入式并非没有代价。编译检查较为严格,而且编译时间相比 C 项目明显更长,学习难度曲线也远高于传统语言。此外,这些嵌入式代码库也尚未覆盖全部芯片型号,而且还可能隐藏 Bug,只能等待相关代码库陆续更新完善。


项目开源地址:https://github.com/Marisa9961/FeRamDisk


能存一辈子?自制FeRam铁电存储U盘!
https://marisa9961.github.io/2026/04/10/260408-FeRamDisk/
作者
Marisa9961
发布于
2026年4月10日
许可协议