- Rename
Uart16550::try_send_bytes()toUart16550::send_bytes() - Rename
Uart16550::try_receive_bytes()toUart16550::receive_bytes() - New public methods:
Uart16550::ready_to_receive()Uart16550::ready_to_send()
- Documentation improvements
- Internal safety fixes (there was no UB, just making the internal code more robust)
Uart16550::new_mmio()andUart16550Ttty::new_mmio()now accept aNonNull<u8>instead of a*mut u8. The recommended way to construct the MMIO address is to use:fn main() { // External MMIO address. let mmio_address = ptr::with_exposed_provenance_mut::<u8>(0x1000); let mmio_address = NonNull::new(mmio_address).unwrap(); let mut uart = unsafe { Uart16550::new_mmio(mmio_address, 4).unwrap() }; }
- Complete rewrite of the crate
- The crate is by no means "minimalist" anymore. Now,
uart_16550, is a simple yet highly configurable low-level driver for 16550 UART devices, typically known and used as serial ports or COM ports. Easy integration into Rust while providing fine-grained control where needed (e.g., for kernel drivers). - Changes were made to use this on real hardware
- Common API for x86 port I/O and MMIO
- 100% typed spec
We thank all past contributors. We've decided to completely rewrite the crate to clean up technical debt from the past, maintain the highest possible coding and API standards, and to make this crate ready for usage on real hardware, while keeping it easy to use in virtual machines.
Special Thanks to Philipp Oppermann (@phil-opp) and Martin Kröning (@mkroening) for their very valuable review on the new crate!
Old
use uart_16550::SerialPort;
const SERIAL_IO_PORT: u16 = 0x3F8;
let mut serial_port = unsafe { SerialPort::new(SERIAL_IO_PORT) };
serial_port.init();
// Now the serial port is ready to be used. To send a byte:
serial_port.send(42);
// To receive a byte:
let data = serial_port.receive();New (Minimalistic)
use uart_16550::{Config, Uart16550Tty};
use core::fmt::Write;
fn main() {
// SAFETY: The address is valid and we have exclusive access.
let mut uart = unsafe { Uart16550Tty::new_mmio(0x1000 as *mut _, 4, Config::default()).expect("should initialize device") };
// ^ or `new_port(0x3f8, Config::default())`
uart.write_str("hello world\nhow's it going?");
}New (More low-level control)
use uart_16550::{Config, Uart16550};
fn main() {
// SAFETY: The address is valid and we have exclusive access.
let mut uart = unsafe { Uart16550::new_mmio(0x1000 as *mut _, 4).expect("should be valid port") };
// ^ or `new_port(0x3f8)`
uart.init(Config::default()).expect("should init device successfully");
uart.test_loopback().expect("should have working loopback mode");
uart.check_connected().expect("should have physically connected receiver");
uart.send_bytes_exact(b"hello world!");
}- Add
MmioSerialPort::new_with_stridefunction (#36)
- Internal rewrite of port operations to work on both
x86andx86_64(#29)
- Make crate usable for 32-bit
x86(#28)
- Remove use of
stableandnightlyfeatures (#24)
- Remove stabilized nightly feature 'const_ptr_offset' (#22)
- Add
send_raw()function to allow sending arbitrary binary data using the serial port (#21)
SerialPort::new()no longer requiresnightlyfeature (#16)
- Update x86_64 dependency and make it more robust (#14)
- Fix build on nightly by updating to x86_64 v0.13.2 (#12)
- Use stabilized
hint::spin_loopinstead of deprecatedatomic::spin_loop_hint
- Fix default feature breakage (#11)
- Update
x86_64dependency to version0.12.2
- Update
x86_64dependency to version0.12.1
- Update
x86_64dependency to version0.11.0
- Use
spin_loop_hintwhile waiting for data (#9) - Update
x86_64dependency to version0.10.2
- Support receiving bytes from serial ports (#8)
- Enable usage with non-nightly rust (#7)
- Update internal x86_64 dependency to version 0.8.3 (#4)