some_serial/lib.rs
1#![no_std]
2
3//! # Some Serial - 嵌入式串口驱动集合
4//!
5//! 本库提供统一的串口驱动接口,支持多种硬件平台:
6//! - ARM PL011 UART
7//! - NS16550/16450 UART(IO Port、MMIO 和 DesignWare APB 版本)
8//!
9//! ## 特性
10//!
11//! - 🏗️ 统一抽象接口 - 驱动层只提供 UART 寄存器语义,运行期队列由 OS runtime 提供
12//! - 🛡️ 无标准库设计 (`no_std`) - 适用于裸机和嵌入式系统
13//! - 📦 模块化架构 - 每个驱动独立模块,按需选择
14//! - 🔒 类型安全 - 使用 Rust 类型系统确保内存安全
15//! - ⚡ 高性能 - 零拷贝数据传输,直接硬件访问
16//!
17//! ## 支持的驱动
18//!
19//! ### ARM PL011 UART
20//! - 广泛用于 ARM Cortex-A、Cortex-M、Cortex-R 系列
21//! - 支持 FIFO、中断、回环等完整功能
22//!
23//! ### NS16550/16450 UART
24//! - 经典 PC 串口控制器,广泛兼容
25//! - 支持 IO Port(x86_64)、MMIO(通用)和 DesignWare APB 访问方式
26//! - 支持 16 字节 FIFO 缓冲
27//!
28//! ## 快速开始
29//!
30//! ```rust,no_run
31//! use core::ptr::NonNull;
32//!
33//! use some_serial::{Config, PollingUart as _, UartPort as _, ns16550::Ns16550, pl011::Pl011};
34//!
35//! // 选择合适的驱动
36//! #[cfg(target_arch = "aarch64")]
37//! let mut uart = Pl011::new(NonNull::new(0x9000000 as *mut u8).unwrap(), 24_000_000);
38//!
39//! #[cfg(not(target_arch = "aarch64"))]
40//! let mut uart = Ns16550::new_mmio(NonNull::new(0x9000000 as *mut u8).unwrap(), 1_843_200, 1);
41//!
42//! // 配置串口
43//! let config = Config::new()
44//! .baudrate(115200)
45//! .data_bits(some_serial::DataBits::Eight)
46//! .stop_bits(some_serial::StopBits::One)
47//! .parity(some_serial::Parity::None);
48//!
49//! uart.startup(&config).unwrap();
50//!
51//! while !uart.poll_status().tx_ready() {
52//! core::hint::spin_loop();
53//! }
54//! uart.write_byte(b'h');
55//! ```
56
57pub mod ns16550;
58pub mod pl011;
59
60use bitflags::bitflags;
61
62/// Allocation-free polling interface used by early consoles.
63pub trait PollingUart {
64 fn poll_status(&mut self) -> PollingEvent;
65
66 fn write_byte(&mut self, byte: u8);
67
68 fn read_byte(&mut self, status: PollingEvent) -> Option<Result<u8, TransferError>>;
69}
70
71bitflags! {
72 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
73 pub struct PollingEvent: u32 {
74 const RX_READY = 0x01;
75 const TX_READY = 0x02;
76 const RX_ERROR = 0x04;
77 const TX_ERROR = 0x08;
78 const OVERRUN = 0x10;
79 const MODEM_STATUS = 0x20;
80 }
81}
82
83impl PollingEvent {
84 pub const fn rx_ready(self) -> bool {
85 self.contains(Self::RX_READY)
86 }
87
88 pub const fn tx_ready(self) -> bool {
89 self.contains(Self::TX_READY)
90 }
91
92 pub const fn rx_error(self) -> bool {
93 self.intersects(Self::RX_ERROR.union(Self::OVERRUN))
94 }
95}
96
97pub type SerialEvent = PollingEvent;
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
100pub enum SerialDirection {
101 Input,
102 Output,
103}
104
105#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)]
106pub enum TransferError {
107 #[error("data overrun by `{0:#x}`")]
108 Overrun(u8),
109 #[error("parity error")]
110 Parity,
111 #[error("framing error")]
112 Framing,
113 #[error("break condition")]
114 Break,
115 #[error("serial closed")]
116 Closed,
117}
118
119#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)]
120#[error("transfer error after transferring {bytes_transferred} bytes: {kind}")]
121pub struct TransBytesError {
122 pub bytes_transferred: usize,
123 #[source]
124 pub kind: TransferError,
125}
126
127// Runtime capability types are re-exported for concrete driver consumers.
128pub use rdif_serial::*;