18 releases (6 breaking)
Uses new Rust 2024
| new 0.7.2 | Aug 3, 2026 |
|---|---|
| 0.7.1 | Jul 24, 2026 |
| 0.7.0 | Jun 27, 2026 |
| 0.3.1 | Nov 8, 2025 |
#47 in Embedded development
1,417 downloads per month
Used in 46 crates
(6 directly)
160KB
3.5K
SLoC
Some Serial - 嵌入式串口驱动集合
一个为嵌入式和裸机环境设计的 统一串口驱动集合,提供多种常见串口硬件的高性能、可靠驱动实现。
🎯 项目定位
Some Serial 旨在为嵌入式开发者提供统一的串口通信解决方案,支持多种硬件平台:
- 🔌 统一接口 - 所有驱动使用相同的 API 接口
- 🚀 高性能 - 针对裸机环境优化的零拷贝设计
- 🛡️ 内存安全 - 基于 Rust 类型系统的内存安全保证
- 🔧 易于扩展 - 模块化设计,轻松添加新的驱动支持
🚀 核心特性
通用架构特性
- 🏗️ 统一抽象接口 - 基于
rdif-serial的统一串口抽象 - 🛡️ 无标准库设计 (
no_std) - 适用于裸机和嵌入式系统 - 📦 模块化架构 - 每个驱动独立模块,按需选择
- 🔒 类型安全 - 使用 Rust 类型系统确保内存安全
- 🧪 全面测试 - 包含完整的测试套件,覆盖各种使用场景
驱动功能特性
- ⚡ 中断驱动 - 支持 TX/RX 中断,提供高效异步通信
- 📊 FIFO 支持 - 硬件 FIFO 缓冲,可配置触发级别
- 🎛️ 灵活配置 - 支持波特率、数据位、停止位、奇偶校验配置
- 🔄 回环测试 - 内置回环模式支持,便于测试和调试
- 📈 性能优化 - 零拷贝数据传输,直接硬件访问
🔌 支持的驱动类型
当前支持
-
✅ ARM PL011 UART - ARM PrimeCell UART (PL011)
- 广泛用于 ARM Cortex-A、Cortex-M、Cortex-R 系列
- 支持 FIFO、中断、回环等完整功能
- 适用于树莓派、STM32 等 ARM 平台
-
✅ NS16550/16450 UART - 经典串口控制器系列
- NS16550Mmio - 内存映射 I/O 版本(通用嵌入式平台)
- NS16550Pio - 端口 I/O 版本(x86_64 架构)
- 支持 16 字节 FIFO 缓冲和中断驱动
- 广泛兼容 PC 兼容串口设备和嵌入式系统
计划支持
- 🚧 更多 ARM UART 驱动 - 扩展 ARM 平台支持
- 🚧 RISC-V 平台适配 - 支持 RISC-V 嵌入式系统
🚀 快速开始
添加依赖
在你的 Cargo.toml 中添加:
[dependencies]
some-serial = "0.1.0"
单对象 polling 使用
concrete 驱动直接持有寄存器和状态;allocator 初始化前的 early console 通过
PollingUart 轮询收发,不需要 Box、trait object、软件队列或内部锁。
use core::ptr::NonNull;
use some_serial::{
Config, DataBits, Parity, PollingUart as _, StopBits, UartPort as _,
ns16550::Ns16550,
};
let base_addr = NonNull::new(0x9000000 as *mut u8).unwrap();
let mut uart = Ns16550::new_mmio(base_addr, 1_843_200, 1);
let config = Config::new()
.baudrate(115200)
.data_bits(DataBits::Eight)
.stop_bits(StopBits::One)
.parity(Parity::None);
uart.startup(&config).expect("Failed to configure UART");
uart.enable_loopback();
let test_data = b"Hello, Serial!";
let mut sent = 0;
while sent < test_data.len() {
let status = uart.poll_status();
if !status.tx_ready() {
core::hint::spin_loop();
continue;
}
uart.write_byte(test_data[sent]);
sent += 1;
}
println!("Sent {} bytes", sent);
let mut buffer = [0u8; 64];
let mut received = 0;
while received < buffer.len() {
let status = uart.poll_status();
let Some(result) = uart.read_byte(status) else {
break;
};
buffer[received] = result.expect("Failed to receive");
received += 1;
}
println!("Received {} bytes: {:?}", received, &buffer[..received]);
驱动选择示例
根据硬件平台和访问方式选择合适的驱动:
use core::ptr::NonNull;
#[cfg(target_arch = "x86_64")]
let mut uart = some_serial::ns16550::Ns16550::new_port(0x3f8, 1_843_200);
#[cfg(target_arch = "aarch64")]
let mut uart = some_serial::pl011::Pl011::new(
NonNull::new(0x9000000 as *mut u8).unwrap(),
24_000_000,
);
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))]
let mut uart = some_serial::ns16550::Ns16550::new_mmio(
NonNull::new(0x40000000 as *mut u8).unwrap(),
16_000_000,
1,
);
高级功能
中断驱动通信
use rdif_serial::{Config, SplitUart as _, UartIrq as _, UartPort as _};
use some_serial::pl011::Pl011;
// 运行时取得两个不可克隆、职责互斥的端点。
let uart = Pl011::new(base_addr, clock_freq);
let parts = uart.split();
let mut port = parts.port;
let mut irq = parts.irq;
port.startup(&Config::new().baudrate(115200)).unwrap();
// IRQ callback 只 ACK/mask 并发布事件,不读写 FIFO。
if let Some(event) = irq.handle() {
// 维护线程根据 event 通过 port 处理数据,完成后调用 port.rearm(event.rearm)。
}
平台检测与适配
需要运行时动态分发的 rdrive/Starry 路径应在驱动探测层调用 SplitUart::split(),并且
仅在那里把两个端点分别擦除为 Box<dyn UartPort> 与 Box<dyn UartIrq>。软件队列、
维护线程、IRQ 注册、wait queue 和 poll source 均由 OS runtime 提供;some-serial
不包含这些调度策略。
use core::ptr::NonNull;
use rdif_serial::{Config, SplitUart as _, UartPort as _};
use some_serial::ns16550::Ns16550;
let uart = Ns16550::new_mmio(
NonNull::new(0x40000000 as *mut u8).unwrap(),
16_000_000,
1,
);
let parts = uart.split();
let mut port = parts.port;
port.startup(&Config::new().baudrate(115200)).unwrap();
let accepted = port.write_tx(b"runtime serial\n");
assert!(accepted <= b"runtime serial\n".len());
平台特定配置获取
fn get_platform_uart_config() -> Result<(*mut u8, u32), &'static str> {
#[cfg(target_arch = "aarch64")]
{
// ARM 平台常见配置
Ok((0x9000000 as *mut u8, 24_000_000))
}
#[cfg(target_arch = "x86_64")]
{
// x86 平台常见配置
Ok((0x3F8 as *mut u8, 1_843_200))
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))]
{
// 默认嵌入式配置
Ok((0x40000000 as *mut u8, 16_000_000))
}
}
API 文档
配置选项
use some_serial::{Config, DataBits, StopBits, Parity};
let config = Config::new()
.baudrate(115200) // 波特率
.data_bits(DataBits::Eight) // 数据位:5/6/7/8
.stop_bits(StopBits::One) // 停止位:1/2
.parity(Parity::None); // 校验位:None/Odd/Even/Mark/Space
状态查询
// 查询当前控制配置
let current_baudrate = uart.baudrate();
let data_bits = uart.data_bits();
let stop_bits = uart.stop_bits();
let parity = uart.parity();
// 查询 I/O 就绪事件
let event = uart.poll_status();
let can_write = event.tx_ready();
测试
这个库包含了一个全面的测试套件,使用 bare-test 框架在裸机环境中运行。
运行测试
# 安装 ostool 用于裸机测试
cargo install ostool
# 运行测试
cargo test --test test -- --show-output
# 真机测试
cargo test --test test -- --show-output --uboot
测试覆盖
- 基础回环测试 - 验证基本的发送/接收功能
- 资源管理测试 - 验证 RAII 和资源生命周期
- 配置测试 - 验证各种配置选项
- 中断测试 - 验证中断功能和掩码控制
- 压力测试 - 高频数据传输测试
- 多模式测试 - 不同数据模式的测试
性能特性
- 低延迟 - 直接硬件寄存器访问
- 高吞吐量 - FIFO 支持提高传输效率
- 内存效率 - 零拷贝数据传输
- 中断优化 - 最小化中断处理开销
许可证
本项目采用以下许可证:
你可以选择其中任何一个许可证使用本项目。
🤝 贡献指南
我们欢迎社区贡献!以下是贡献方式:
添加新驱动支持
- 创建驱动模块:在
src/目录下创建新的驱动文件 - 拆分运行时端点:驱动实现
SplitUart,数据面实现UartPort,中断面实现UartIrq - 添加测试:为新驱动编写完整的测试套件
- 更新文档:在 README 中添加驱动说明和使用示例
- 提交 PR:详细描述新驱动的功能和使用方法
参考实现
可以参考现有的 src/pl011.rs 作为新驱动的实现模板:
// 新驱动的基本结构示例
pub struct NewDriver {
// 驱动寄存器句柄、时钟和配置状态
}
impl SplitUart for NewDriver {
// 将共享寄存器 core 拆成 task-owned port 与 IRQ-owned endpoint。
}
📚 相关资源
技术文档
- ARM PL011 Technical Reference Manual - PL011 硬件规格
- rdif-serial - 统一串口接口抽象
- bare-test - 裸机测试框架
硬件参考
- 16550/16450 UART 数据手册 - 经典串口控制器
致谢
感谢所有为嵌入式串口通信生态系统做出贡献的开发者和项目!
更新日志
v0.1.0 (2024-01-XX)
- ✨ 初始发布 - 嵌入式串口驱动集合
- ✅ 完整的 ARM PL011 UART 支持
- ✅ 新增 NS16550/16450 UART 驱动支持
- ✅ NS16550Mmio - 内存映射 I/O 版本
- ✅ NS16550Pio - 端口 I/O 版本(x86_64)
- ✅ 支持 FIFO、中断、回环等完整功能
- ✅ 基于 rdif-serial 的统一接口抽象
- ✅ 中断驱动通信和 FIFO 功能
- ✅ 全面测试套件和文档
- ✅ 性能优化和类型安全改进
- 🏗️ 模块化架构,支持多平台驱动选择
未来计划
- 🎯 扩展更多 ARM UART 驱动支持
- 🎯 RISC-V 平台适配
- 🎯 更多性能优化和功能特性
Dependencies
~5MB
~67K SLoC