Skip to content

Improvements to new MMIO support #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ pre-release-replacements = [
{ file="Changelog.md", search="# Unreleased", replace="# Unreleased\n\n# {{version}} – {{date}}", exactly=1 },
]
pre-release-commit-message = "Release version {{version}}"

[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]
19 changes: 13 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

[![Build Status](https://github.com/rust-osdev/uart_16550/workflows/Build/badge.svg)](https://github.com/rust-osdev/uart_16550/actions?query=workflow%3ABuild) [![Docs.rs Badge](https://docs.rs/uart_16550/badge.svg)](https://docs.rs/uart_16550/)

Minimal support for uart_16550 serial and memory mapped I/O.
Minimal support for [serial communication](https://en.wikipedia.org/wiki/Asynchronous_serial_communication) through [UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter) devices, which are compatible to the [16550 UART](https://en.wikipedia.org/wiki/16550_UART). This crate supports port-mapped and memory mapped UARTS.

## Usage

### With usual serial port
Depending on the system architecture, the UART can be either accessed through [port-mapped I/O](https://wiki.osdev.org/Port_IO) or [memory-mapped I/O](https://en.wikipedia.org/wiki/Memory-mapped_I/O).

### With port-mappd I/O

The UART is accessed through port-mapped I/O on architectures such as `x86_64`. On these architectures, the [`SerialPort`](https://docs.rs/uart_16550/~0.2/uart_16550/struct.SerialPort.html) type can be used:


```rust
use uart_16550::SerialPort;
Expand All @@ -25,6 +30,8 @@ let data = serial_port.receive();

### With memory mapped serial port

Most other architectures, such as [RISC-V](https://en.wikipedia.org/wiki/RISC-V), use memory-mapped I/O for accessing the UARTs. On these architectures, the [`MmioSerialPort`](https://docs.rs/uart_16550/~0.2/uart_16550/struct.MmioSerialPort.html) type can be used:

```rust
use uart_16550::MmioSerialPort;

Expand All @@ -40,10 +47,6 @@ serial_port.send(42);
let data = serial_port.receive();
```

## License

Licensed under the MIT license ([LICENSE](LICENSE) or <http://opensource.org/licenses/MIT>).

## Crate Feature Flags

* `nightly`: This is the default.
Expand All @@ -53,3 +56,7 @@ Licensed under the MIT license ([LICENSE](LICENSE) or <http://opensource.org/lic

This needs to have the [compile-time requirements](https://github.com/alexcrichton/cc-rs#compile-time-requirements) of the `cc` crate installed on your system.
It was currently only tested on Linux and MacOS.

## License

Licensed under the MIT license ([LICENSE](LICENSE) or <http://opensource.org/licenses/MIT>).
76 changes: 48 additions & 28 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,47 @@
//! Minimal support for uart_16550 serial I/O.
//! Minimal support for
//! [serial communication](https://en.wikipedia.org/wiki/Asynchronous_serial_communication)
//! through [UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter)
//! devices, which are compatible to the [16550 UART](https://en.wikipedia.org/wiki/16550_UART).
//!
//! # Usage

#![cfg_attr(
target_arch = "x86_64",
doc = "
## With usual serial port
```no_run
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();
```
"
)]

//! ## With memory mapped serial port
//! This crate supports port-mapped and memory mapped UARTS.
//!
//! ## Usage
//!
//! Depending on the system architecture, the UART can be either accessed through
//! [port-mapped I/O](https://wiki.osdev.org/Port_IO) or
//! [memory-mapped I/O](https://en.wikipedia.org/wiki/Memory-mapped_I/O).
//!
//! ### With port-mappd I/O
//!
//! The UART is accessed through port-mapped I/O on architectures such as `x86_64`.
//! On these architectures, the [`SerialPort`] type can be used:
//!
//!
//! ```no_run
//! # #[cfg(target_arch = "x86_64")]
//! # fn main() {
//! 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();
//! # }
//! # #[cfg(not(target_arch = "x86_64"))]
//! # fn main() {}
//! ```
//!
//! ### With memory mapped serial port
//!
//! Most other architectures, such as [RISC-V](https://en.wikipedia.org/wiki/RISC-V), use
//! memory-mapped I/O for accessing the UARTs. On these architectures, the [`MmioSerialPort`]
//! type can be used:
//!
//! ```no_run
//! use uart_16550::MmioSerialPort;
Expand All @@ -39,9 +57,11 @@ let data = serial_port.receive();
//! // To receive a byte:
//! let data = serial_port.receive();
//! ```

#![no_std]
#![warn(missing_docs)]
#![cfg_attr(feature = "nightly", feature(const_ptr_offset))]
#![cfg_attr(docsrs, feature(doc_cfg))]

#[cfg(not(any(feature = "stable", feature = "nightly")))]
compile_error!("Either the `stable` or `nightly` feature must be enabled");
Expand All @@ -57,14 +77,14 @@ macro_rules! wait_for {
}

/// Memory mapped implementation
pub mod mmio;
mod mmio;
#[cfg(target_arch = "x86_64")]
/// Port asm commands implementation
pub mod x86_64;
mod port;

pub use crate::mmio::MmioSerialPort;
#[cfg(target_arch = "x86_64")]
pub use crate::x86_64::SerialPort;
pub use crate::port::SerialPort;

bitflags! {
/// Interrupt enable flags
Expand Down
6 changes: 3 additions & 3 deletions src/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use core::{

use crate::LineStsFlags;

/// An interface to a serial port that allows sending out individual bytes.
/// A memory-mapped UART.
pub struct MmioSerialPort {
data: AtomicPtr<u8>,
int_en: AtomicPtr<u8>,
Expand All @@ -16,7 +16,7 @@ pub struct MmioSerialPort {
}

impl MmioSerialPort {
/// Creates a new serial port interface on the given memory mapped address.
/// Creates a new UART interface on the given memory mapped address.
///
/// This function is unsafe because the caller must ensure that the given base address
/// really points to a serial port device.
Expand Down Expand Up @@ -46,7 +46,7 @@ impl MmioSerialPort {
}
}

/// Initializes the serial port.
/// Initializes the memory-mapped UART.
///
/// The default configuration of [38400/8-N-1](https://en.wikipedia.org/wiki/8-N-1) is used.
pub fn init(&mut self) {
Expand Down
3 changes: 2 additions & 1 deletion src/x86_64.rs → src/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly};

use crate::LineStsFlags;

/// An interface to a serial port that allows sending out individual bytes.
/// A port-mapped UART.
#[cfg_attr(docsrs, doc(cfg(target_arch = "x86_64")))]
pub struct SerialPort {
data: Port<u8>,
int_en: PortWriteOnly<u8>,
Expand Down