| Crates.io | some-serial |
| lib.rs | some-serial |
| version | 0.3.1 |
| created_at | 2025-10-16 06:17:05.231931+00 |
| updated_at | 2025-11-08 15:43:47.542267+00 |
| description | Unified serial driver collection for embedded and bare-metal environments |
| homepage | https://github.com/drivercraft/some-serial |
| repository | https://github.com/drivercraft/some-serial |
| max_upload_size | |
| id | 1885494 |
| size | 220,194 |
一个为嵌入式和裸机环境设计的 统一串口驱动集合,提供多种常见串口硬件的高性能、可靠驱动实现。
Some Serial 旨在为嵌入式开发者提供统一的串口通信解决方案,支持多种硬件平台:
rdif-serial 的统一串口抽象no_std) - 适用于裸机和嵌入式系统✅ ARM PL011 UART - ARM PrimeCell UART (PL011)
✅ NS16550/16450 UART - 经典串口控制器系列
在你的 Cargo.toml 中添加:
[dependencies]
some-serial = "0.1.0"
所有驱动都实现了统一的 Serial trait,提供一致的使用体验:
use core::ptr::NonNull;
use some_serial::{Serial, Config};
// 根据平台选择合适的驱动
#[cfg(target_arch = "aarch64")]
use some_serial::pl011::Pl011;
#[cfg(not(target_arch = "aarch64"))]
use some_serial::ns16550::Ns16550Mmio;
// 创建串口实例
let base_addr = 0x9000000 as *mut u8; // 你的 UART 基地址
let clock_freq = match target_arch {
"aarch64" => 24_000_000, // ARM PL011: 24MHz
_ => 1_843_200, // NS16550: 1.8432MHz
};
let mut uart = match target_arch {
"aarch64" => Pl011::new(
NonNull::new(base_addr).unwrap(),
clock_freq
),
_ => Ns16550Mmio::new(
NonNull::new(base_addr).unwrap(),
clock_freq
),
};
// 统一配置接口
let config = Config::new()
.baudrate(115200)
.data_bits(some_serial::DataBits::Eight)
.stop_bits(some_serial::StopBits::One)
.parity(some_serial::Parity::None);
uart.set_config(&config).expect("Failed to configure UART");
uart.open().expect("Failed to open UART");
// 启用回环模式进行测试(如果支持)
uart.enable_loopback();
// 获取 TX/RX 接口进行数据传输
let mut tx = uart.take_tx().unwrap();
let mut rx = uart.take_rx().unwrap();
// 发送和接收数据
let test_data = b"Hello, Serial!";
let sent = tx.send(test_data);
println!("Sent {} bytes", sent);
let mut buffer = [0u8; 64];
let received = rx.receive(&mut buffer).expect("Failed to receive");
println!("Received {} bytes: {:?}", received, &buffer[..received]);
根据硬件平台和访问方式选择合适的驱动:
// ARM 平台 - 使用 PL011
#[cfg(target_arch = "aarch64")]
use some_serial::pl011::Pl011;
// x86_64 平台 - 使用端口 I/O
#[cfg(target_arch = "x86_64")]
use some_serial::ns16550::Ns16550Pio;
// 其他嵌入式平台 - 使用内存映射 I/O
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))]
use some_serial::ns16550::Ns16550Mmio;
// 平台特定的创建函数
fn create_uart_for_platform(base_addr: *mut u8, clock_freq: u32) -> Box<dyn Serial> {
#[cfg(target_arch = "aarch64")]
{
Box::new(Pl011::new(
NonNull::new(base_addr).unwrap(),
clock_freq
))
}
#[cfg(target_arch = "x86_64")]
{
Box::new(Ns16550Pio::new(
NonNull::new(base_addr).unwrap(),
clock_freq
))
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))]
{
Box::new(Ns16550Mmio::new(
NonNull::new(base_addr).unwrap(),
clock_freq
))
}
}
// 统一的创建和使用方式
let mut uart = create_uart_for_platform(base_addr, clock_freq);
// ... 后续使用方式完全相同
use some_serial::{Serial, InterruptMask};
use some_serial::pl011::Pl011;
// 创建并配置 UART
let mut uart = Pl011::new(base_addr, clock_freq);
uart.set_config(&config).unwrap();
uart.open().unwrap();
// 启用中断
uart.enable_interrupts(InterruptMask::RX_AVAILABLE | InterruptMask::TX_EMPTY);
// 注册中断处理程序
let irq_handler = uart.irq_handler().unwrap();
// 在你的中断控制器中注册 irq_handler...
// 现在可以在中断处理中高效处理数据传输
// 运行时平台检测示例
fn create_serial_for_platform(base_addr: *mut u8, clock_freq: u32) -> Box<dyn Serial> {
#[cfg(target_arch = "aarch64")]
{
// ARM64 平台,使用 PL011
Box::new(Pl011::new(
NonNull::new(base_addr).unwrap(),
clock_freq
))
}
#[cfg(target_arch = "x86_64")]
{
// x86_64 平台,使用 NS16550 端口 I/O
Box::new(Ns16550Pio::new(
NonNull::new(base_addr).unwrap(),
clock_freq
))
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))]
{
// 其他嵌入式平台,使用 NS16550 内存映射 I/O
Box::new(Ns16550Mmio::new(
NonNull::new(base_addr).unwrap(),
clock_freq
))
}
}
// 系统集成示例
fn init_system_uart() -> Result<Box<dyn Serial>, &'static str> {
let (base_addr, clock_freq) = get_platform_uart_config()?;
let mut uart = create_serial_for_platform(base_addr, clock_freq);
// 标准配置
let config = Config::new()
.baudrate(115200)
.data_bits(DataBits::Eight)
.stop_bits(StopBits::One)
.parity(Parity::None);
uart.set_config(&config).map_err(|_| "Failed to configure UART")?;
uart.open().map_err(|_| "Failed to open UART")?;
Ok(uart)
}
// 平台特定配置获取
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))
}
}
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 status = uart.line_status();
if status.contains(some_serial::LineStatus::DATA_READY) {
// 有数据可读
}
if status.contains(some_serial::LineStatus::TX_HOLDING_EMPTY) {
// 可以发送数据
}
// 查询当前配置
let current_baudrate = uart.baudrate();
let data_bits = uart.data_bits();
let stop_bits = uart.stop_bits();
let parity = uart.parity();
这个库包含了一个全面的测试套件,使用 bare-test 框架在裸机环境中运行。
# 安装 ostool 用于裸机测试
cargo install ostool
# 运行测试
cargo test --test test -- --show-output
# 真机测试
cargo test --test test -- --show-output --uboot
本项目采用以下许可证:
你可以选择其中任何一个许可证使用本项目。
我们欢迎社区贡献!以下是贡献方式:
src/ 目录下创建新的驱动文件rdif-serial 接口可以参考现有的 src/pl011.rs 作为新驱动的实现模板:
// 新驱动的基本结构示例
pub struct NewDriver {
// 驱动特定的状态
}
impl Serial for NewDriver {
// 实现 Serial trait 的所有方法
}
impl NewDriver {
// 驱动特定的初始化和配置方法
}
感谢所有为嵌入式串口通信生态系统做出贡献的开发者和项目!