You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-06-29 03:51:35 +02:00
QEMU virt machine uses PL011 UART not 16550.
This commit is contained in:
@ -16,14 +16,22 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
mod exceptions;
|
mod exceptions;
|
||||||
mod uart;
|
mod pl011;
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
use crate::pl011::Uart;
|
||||||
|
use core::{fmt::Write, panic::PanicInfo};
|
||||||
use log::error;
|
use log::error;
|
||||||
use psci::system_off;
|
use psci::system_off;
|
||||||
|
|
||||||
|
/// Base address of the primary PL011 UART.
|
||||||
|
pub const PL011_BASE_ADDRESS: usize = 0x900_0000;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
|
extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
|
||||||
|
// Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,
|
||||||
|
// and nothing else accesses that address range.
|
||||||
|
let mut uart = unsafe { Uart::new(PL011_BASE_ADDRESS) };
|
||||||
|
writeln!(uart, "main({:#x}, {:#x}, {:#x}, {:#x})", x0, x1, x2, x3).unwrap();
|
||||||
system_off().unwrap();
|
system_off().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,24 +13,25 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// ANCHOR: Example
|
// ANCHOR: Example
|
||||||
use core::ptr::write_volatile;
|
const FLAG_REGISTER_OFFSET: usize = 0x18;
|
||||||
|
const FR_BUSY: u8 = 1 << 3;
|
||||||
|
const FR_TXFF: u8 = 1 << 5;
|
||||||
|
|
||||||
/// Minimal driver for an 8250 UART. This only implements enough to work with
|
/// Minimal driver for a PL011 UART.
|
||||||
/// the emulated 8250 provided by crosvm, and won't work with real hardware.
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Uart {
|
pub struct Uart {
|
||||||
base_address: *mut u8,
|
base_address: *mut u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Uart {
|
impl Uart {
|
||||||
/// Constructs a new instance of the UART driver for a device at the given
|
/// Constructs a new instance of the UART driver for a PL011 device at the
|
||||||
/// base address.
|
/// given base address.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The given base address must point to the 8 MMIO control registers of an
|
/// The given base address must point to the 8 MMIO control registers of a
|
||||||
/// appropriate UART device, which must be mapped into the address space of
|
/// PL011 device, which must be mapped into the address space of the process
|
||||||
/// the process as device memory and not have any other aliases.
|
/// as device memory and not have any other aliases.
|
||||||
pub unsafe fn new(base_address: usize) -> Self {
|
pub unsafe fn new(base_address: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
base_address: base_address as *mut u8,
|
base_address: base_address as *mut u8,
|
||||||
@ -39,11 +40,24 @@ impl Uart {
|
|||||||
|
|
||||||
/// Writes a single byte to the UART.
|
/// Writes a single byte to the UART.
|
||||||
pub fn write_byte(&self, byte: u8) {
|
pub fn write_byte(&self, byte: u8) {
|
||||||
|
// Wait until there is room in the TX buffer.
|
||||||
|
while self.read_flag_register() & FR_TXFF != 0 {}
|
||||||
|
|
||||||
// Safe because we know that the base address points to the control
|
// Safe because we know that the base address points to the control
|
||||||
// registers of a UART device which is appropriately mapped.
|
// registers of a PL011 device which is appropriately mapped.
|
||||||
unsafe {
|
unsafe {
|
||||||
write_volatile(self.base_address, byte);
|
// Write to the TX buffer.
|
||||||
|
self.base_address.write_volatile(byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait until the UART is no longer busy.
|
||||||
|
while self.read_flag_register() & FR_BUSY != 0 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_flag_register(&self) -> u8 {
|
||||||
|
// Safe because we know that the base address points to the control
|
||||||
|
// registers of a PL011 device which is appropriately mapped.
|
||||||
|
unsafe { self.base_address.add(FLAG_REGISTER_OFFSET).read_volatile() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ANCHOR_END: Example
|
// ANCHOR_END: Example
|
@ -1,5 +1,5 @@
|
|||||||
# Let's write a UART driver
|
# Let's write a UART driver
|
||||||
|
|
||||||
```rust,editable,compile_fail
|
```rust,editable,compile_fail
|
||||||
{{#include examples/src/uart.rs:Example}}
|
{{#include examples/src/pl011.rs:Example}}
|
||||||
```
|
```
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# More traits
|
# More traits
|
||||||
|
|
||||||
```rust,editable,compile_fail
|
```rust,editable,compile_fail
|
||||||
{{#include ../examples/src/uart.rs:Traits}}
|
{{#include ../examples/src/pl011.rs:Traits}}
|
||||||
```
|
```
|
||||||
|
Reference in New Issue
Block a user