More idiomatic register-rs use

pull/37/head
Andre Richter 5 years ago
parent 1cc8152fa1
commit d31c17d914
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

@ -275,7 +275,7 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_gpio.rs 06_drivers_gpio_uar
diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
--- 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
+++ 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
@@ -0,0 +1,315 @@
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
@ -460,12 +460,8 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 06_drivers_gp
+
+ /// Send a character.
+ fn write_char(&mut self, c: char) {
+ // Wait until we can send.
+ loop {
+ if !self.FR.is_set(FR::TXFF) {
+ break;
+ }
+
+ // Spin while TX FIFO full is set, waiting for an empty slot.
+ while self.FR.matches_all(FR::TXFF::SET) {
+ arch::nop();
+ }
+
@ -563,12 +559,8 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 06_drivers_gp
+ fn read_char(&self) -> char {
+ let mut r = &self.inner;
+ r.lock(|inner| {
+ // Wait until buffer is filled.
+ loop {
+ if !inner.FR.is_set(FR::RXFE) {
+ break;
+ }
+
+ // Spin while RX FIFO empty is set.
+ while inner.FR.matches_all(FR::RXFE::SET) {
+ arch::nop();
+ }
+

Binary file not shown.

Binary file not shown.

@ -182,12 +182,8 @@ impl PL011UartInner {
/// Send a character.
fn write_char(&mut self, c: char) {
// Wait until we can send.
loop {
if !self.FR.is_set(FR::TXFF) {
break;
}
// Spin while TX FIFO full is set, waiting for an empty slot.
while self.FR.matches_all(FR::TXFF::SET) {
arch::nop();
}
@ -285,12 +281,8 @@ impl interface::console::Read for PL011Uart {
fn read_char(&self) -> char {
let mut r = &self.inner;
r.lock(|inner| {
// Wait until buffer is filled.
loop {
if !inner.FR.is_set(FR::RXFE) {
break;
}
// Spin while RX FIFO empty is set.
while inner.FR.matches_all(FR::RXFE::SET) {
arch::nop();
}

@ -162,26 +162,24 @@ diff -uNr 06_drivers_gpio_uart/src/arch/aarch64.rs 07_uart_chainloader/src/arch/
diff -uNr 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
--- 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
+++ 07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
@@ -279,6 +279,18 @@
@@ -275,6 +275,16 @@
let mut r = &self.inner;
r.lock(|inner| fmt::Write::write_fmt(inner, args))
}
+
+ fn flush(&self) {
+ let mut r = &self.inner;
+ // Spin until the TX FIFO empty flag is set.
+ r.lock(|inner| loop {
+ if inner.FR.is_set(FR::TXFE) {
+ break;
+ // Spin until TX FIFO empty is set.
+ r.lock(|inner| {
+ while !inner.FR.matches_all(FR::TXFE::SET) {
+ arch::nop();
+ }
+
+ arch::nop();
+ });
+ }
}
impl interface::console::Read for PL011Uart {
@@ -295,14 +307,19 @@
@@ -287,14 +297,17 @@
}
// Read one character.
@ -195,12 +193,10 @@ diff -uNr 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 07_uart_
- ret = '\n'
+ fn clear(&self) {
+ let mut r = &self.inner;
+ r.lock(|inner| loop {
+ // Read from the RX FIFO until the empty bit is '1'.
+ if !inner.FR.is_set(FR::RXFE) {
+ r.lock(|inner| {
+ // Read from the RX FIFO until it is indicating empty.
+ while !inner.FR.matches_all(FR::RXFE::SET) {
+ inner.DR.get();
+ } else {
+ break;
}
-
- ret

Binary file not shown.

Binary file not shown.

@ -182,12 +182,8 @@ impl PL011UartInner {
/// Send a character.
fn write_char(&mut self, c: char) {
// Wait until we can send.
loop {
if !self.FR.is_set(FR::TXFF) {
break;
}
// Spin while TX FIFO full is set, waiting for an empty slot.
while self.FR.matches_all(FR::TXFF::SET) {
arch::nop();
}
@ -282,13 +278,11 @@ impl interface::console::Write for PL011Uart {
fn flush(&self) {
let mut r = &self.inner;
// Spin until the TX FIFO empty flag is set.
r.lock(|inner| loop {
if inner.FR.is_set(FR::TXFE) {
break;
// Spin until TX FIFO empty is set.
r.lock(|inner| {
while !inner.FR.matches_all(FR::TXFE::SET) {
arch::nop();
}
arch::nop();
});
}
}
@ -297,12 +291,8 @@ impl interface::console::Read for PL011Uart {
fn read_char(&self) -> char {
let mut r = &self.inner;
r.lock(|inner| {
// Wait until buffer is filled.
loop {
if !inner.FR.is_set(FR::RXFE) {
break;
}
// Spin while RX FIFO empty is set.
while inner.FR.matches_all(FR::RXFE::SET) {
arch::nop();
}
@ -313,12 +303,10 @@ impl interface::console::Read for PL011Uart {
fn clear(&self) {
let mut r = &self.inner;
r.lock(|inner| loop {
// Read from the RX FIFO until the empty bit is '1'.
if !inner.FR.is_set(FR::RXFE) {
r.lock(|inner| {
// Read from the RX FIFO until it is indicating empty.
while !inner.FR.matches_all(FR::RXFE::SET) {
inner.DR.get();
} else {
break;
}
})
}

@ -100,7 +100,7 @@ diff -uNr 07_uart_chainloader/Makefile 08_timestamps/Makefile
diff -uNr 07_uart_chainloader/src/arch/aarch64/time.rs 08_timestamps/src/arch/aarch64/time.rs
--- 07_uart_chainloader/src/arch/aarch64/time.rs
+++ 08_timestamps/src/arch/aarch64/time.rs
@@ -0,0 +1,85 @@
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
@ -175,12 +175,8 @@ diff -uNr 07_uart_chainloader/src/arch/aarch64/time.rs 08_timestamps/src/arch/aa
+ // Kick off the counting. // Disable timer interrupt.
+ CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET);
+
+ loop {
+ // ISTATUS will be '1' when cval ticks have passed. Busy-check it.
+ if CNTP_CTL_EL0.is_set(CNTP_CTL_EL0::ISTATUS) {
+ break;
+ }
+ }
+ // ISTATUS will be '1' when cval ticks have passed. Busy-check it.
+ while !CNTP_CTL_EL0.matches_all(CNTP_CTL_EL0::ISTATUS::SET) {}
+
+ // Disable counting again.
+ CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::CLEAR);
@ -239,7 +235,7 @@ diff -uNr 07_uart_chainloader/src/arch/aarch64.rs 08_timestamps/src/arch/aarch64
diff -uNr 07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 08_timestamps/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
--- 07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
+++ 08_timestamps/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
@@ -307,7 +307,14 @@
@@ -297,7 +297,14 @@
}
// Read one character.

Binary file not shown.

Binary file not shown.

@ -72,12 +72,8 @@ impl interface::time::Timer for Timer {
// Kick off the counting. // Disable timer interrupt.
CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET);
loop {
// ISTATUS will be '1' when cval ticks have passed. Busy-check it.
if CNTP_CTL_EL0.is_set(CNTP_CTL_EL0::ISTATUS) {
break;
}
}
// ISTATUS will be '1' when cval ticks have passed. Busy-check it.
while !CNTP_CTL_EL0.matches_all(CNTP_CTL_EL0::ISTATUS::SET) {}
// Disable counting again.
CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::CLEAR);

@ -182,12 +182,8 @@ impl PL011UartInner {
/// Send a character.
fn write_char(&mut self, c: char) {
// Wait until we can send.
loop {
if !self.FR.is_set(FR::TXFF) {
break;
}
// Spin while TX FIFO full is set, waiting for an empty slot.
while self.FR.matches_all(FR::TXFF::SET) {
arch::nop();
}
@ -282,13 +278,11 @@ impl interface::console::Write for PL011Uart {
fn flush(&self) {
let mut r = &self.inner;
// Spin until the TX FIFO empty flag is set.
r.lock(|inner| loop {
if inner.FR.is_set(FR::TXFE) {
break;
// Spin until TX FIFO empty is set.
r.lock(|inner| {
while !inner.FR.matches_all(FR::TXFE::SET) {
arch::nop();
}
arch::nop();
});
}
}
@ -297,12 +291,8 @@ impl interface::console::Read for PL011Uart {
fn read_char(&self) -> char {
let mut r = &self.inner;
r.lock(|inner| {
// Wait until buffer is filled.
loop {
if !inner.FR.is_set(FR::RXFE) {
break;
}
// Spin while RX FIFO empty is set.
while inner.FR.matches_all(FR::RXFE::SET) {
arch::nop();
}
@ -320,12 +310,10 @@ impl interface::console::Read for PL011Uart {
fn clear(&self) {
let mut r = &self.inner;
r.lock(|inner| loop {
// Read from the RX FIFO until the empty bit is '1'.
if !inner.FR.is_set(FR::RXFE) {
r.lock(|inner| {
// Read from the RX FIFO until it is indicating empty.
while !inner.FR.matches_all(FR::RXFE::SET) {
inner.DR.get();
} else {
break;
}
})
}

Binary file not shown.

Binary file not shown.

@ -72,12 +72,8 @@ impl interface::time::Timer for Timer {
// Kick off the counting. // Disable timer interrupt.
CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET);
loop {
// ISTATUS will be '1' when cval ticks have passed. Busy-check it.
if CNTP_CTL_EL0.is_set(CNTP_CTL_EL0::ISTATUS) {
break;
}
}
// ISTATUS will be '1' when cval ticks have passed. Busy-check it.
while !CNTP_CTL_EL0.matches_all(CNTP_CTL_EL0::ISTATUS::SET) {}
// Disable counting again.
CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::CLEAR);

@ -182,12 +182,8 @@ impl PL011UartInner {
/// Send a character.
fn write_char(&mut self, c: char) {
// Wait until we can send.
loop {
if !self.FR.is_set(FR::TXFF) {
break;
}
// Spin while TX FIFO full is set, waiting for an empty slot.
while self.FR.matches_all(FR::TXFF::SET) {
arch::nop();
}
@ -282,13 +278,11 @@ impl interface::console::Write for PL011Uart {
fn flush(&self) {
let mut r = &self.inner;
// Spin until the TX FIFO empty flag is set.
r.lock(|inner| loop {
if inner.FR.is_set(FR::TXFE) {
break;
// Spin until TX FIFO empty is set.
r.lock(|inner| {
while !inner.FR.matches_all(FR::TXFE::SET) {
arch::nop();
}
arch::nop();
});
}
}
@ -297,12 +291,8 @@ impl interface::console::Read for PL011Uart {
fn read_char(&self) -> char {
let mut r = &self.inner;
r.lock(|inner| {
// Wait until buffer is filled.
loop {
if !inner.FR.is_set(FR::RXFE) {
break;
}
// Spin while RX FIFO empty is set.
while inner.FR.matches_all(FR::RXFE::SET) {
arch::nop();
}
@ -320,12 +310,10 @@ impl interface::console::Read for PL011Uart {
fn clear(&self) {
let mut r = &self.inner;
r.lock(|inner| loop {
// Read from the RX FIFO until the empty bit is '1'.
if !inner.FR.is_set(FR::RXFE) {
r.lock(|inner| {
// Read from the RX FIFO until it is indicating empty.
while !inner.FR.matches_all(FR::RXFE::SET) {
inner.DR.get();
} else {
break;
}
})
}

Binary file not shown.

Binary file not shown.

@ -72,12 +72,8 @@ impl interface::time::Timer for Timer {
// Kick off the counting. // Disable timer interrupt.
CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET);
loop {
// ISTATUS will be '1' when cval ticks have passed. Busy-check it.
if CNTP_CTL_EL0.is_set(CNTP_CTL_EL0::ISTATUS) {
break;
}
}
// ISTATUS will be '1' when cval ticks have passed. Busy-check it.
while !CNTP_CTL_EL0.matches_all(CNTP_CTL_EL0::ISTATUS::SET) {}
// Disable counting again.
CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::CLEAR);

@ -182,12 +182,8 @@ impl PL011UartInner {
/// Send a character.
fn write_char(&mut self, c: char) {
// Wait until we can send.
loop {
if !self.FR.is_set(FR::TXFF) {
break;
}
// Spin while TX FIFO full is set, waiting for an empty slot.
while self.FR.matches_all(FR::TXFF::SET) {
arch::nop();
}
@ -282,13 +278,11 @@ impl interface::console::Write for PL011Uart {
fn flush(&self) {
let mut r = &self.inner;
// Spin until the TX FIFO empty flag is set.
r.lock(|inner| loop {
if inner.FR.is_set(FR::TXFE) {
break;
// Spin until TX FIFO empty is set.
r.lock(|inner| {
while !inner.FR.matches_all(FR::TXFE::SET) {
arch::nop();
}
arch::nop();
});
}
}
@ -297,12 +291,8 @@ impl interface::console::Read for PL011Uart {
fn read_char(&self) -> char {
let mut r = &self.inner;
r.lock(|inner| {
// Wait until buffer is filled.
loop {
if !inner.FR.is_set(FR::RXFE) {
break;
}
// Spin while RX FIFO empty is set.
while inner.FR.matches_all(FR::RXFE::SET) {
arch::nop();
}
@ -320,12 +310,10 @@ impl interface::console::Read for PL011Uart {
fn clear(&self) {
let mut r = &self.inner;
r.lock(|inner| loop {
// Read from the RX FIFO until the empty bit is '1'.
if !inner.FR.is_set(FR::RXFE) {
r.lock(|inner| {
// Read from the RX FIFO until it is indicating empty.
while !inner.FR.matches_all(FR::RXFE::SET) {
inner.DR.get();
} else {
break;
}
})
}

Binary file not shown.

Binary file not shown.

@ -72,12 +72,8 @@ impl interface::time::Timer for Timer {
// Kick off the counting. // Disable timer interrupt.
CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET);
loop {
// ISTATUS will be '1' when cval ticks have passed. Busy-check it.
if CNTP_CTL_EL0.is_set(CNTP_CTL_EL0::ISTATUS) {
break;
}
}
// ISTATUS will be '1' when cval ticks have passed. Busy-check it.
while !CNTP_CTL_EL0.matches_all(CNTP_CTL_EL0::ISTATUS::SET) {}
// Disable counting again.
CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::CLEAR);

@ -182,12 +182,8 @@ impl PL011UartInner {
/// Send a character.
fn write_char(&mut self, c: char) {
// Wait until we can send.
loop {
if !self.FR.is_set(FR::TXFF) {
break;
}
// Spin while TX FIFO full is set, waiting for an empty slot.
while self.FR.matches_all(FR::TXFF::SET) {
arch::nop();
}
@ -282,13 +278,11 @@ impl interface::console::Write for PL011Uart {
fn flush(&self) {
let mut r = &self.inner;
// Spin until the TX FIFO empty flag is set.
r.lock(|inner| loop {
if inner.FR.is_set(FR::TXFE) {
break;
// Spin until TX FIFO empty is set.
r.lock(|inner| {
while !inner.FR.matches_all(FR::TXFE::SET) {
arch::nop();
}
arch::nop();
});
}
}
@ -297,12 +291,8 @@ impl interface::console::Read for PL011Uart {
fn read_char(&self) -> char {
let mut r = &self.inner;
r.lock(|inner| {
// Wait until buffer is filled.
loop {
if !inner.FR.is_set(FR::RXFE) {
break;
}
// Spin while RX FIFO empty is set.
while inner.FR.matches_all(FR::RXFE::SET) {
arch::nop();
}
@ -320,12 +310,10 @@ impl interface::console::Read for PL011Uart {
fn clear(&self) {
let mut r = &self.inner;
r.lock(|inner| loop {
// Read from the RX FIFO until the empty bit is '1'.
if !inner.FR.is_set(FR::RXFE) {
r.lock(|inner| {
// Read from the RX FIFO until it is indicating empty.
while !inner.FR.matches_all(FR::RXFE::SET) {
inner.DR.get();
} else {
break;
}
})
}

Binary file not shown.

Binary file not shown.

@ -7,6 +7,10 @@
use crate::interface;
use core::cell::UnsafeCell;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
/// A pseudo-lock for teaching purposes.
///
/// Used to introduce [interior mutability].
@ -33,6 +37,10 @@ impl<T> NullLock<T> {
}
}
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl<T> interface::sync::Mutex for &NullLock<T> {
type Data = T;

@ -10,8 +10,16 @@ use cortex_a::regs::*;
const NS_PER_S: u64 = 1_000_000_000;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
pub struct Timer;
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl interface::time::Timer for Timer {
fn resolution(&self) -> Duration {
Duration::from_nanos(NS_PER_S / (CNTFRQ_EL0.get() as u64))
@ -64,12 +72,8 @@ impl interface::time::Timer for Timer {
// Kick off the counting. // Disable timer interrupt.
CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET);
loop {
// ISTATUS will be '1' when cval ticks have passed. Busy-check it.
if CNTP_CTL_EL0.is_set(CNTP_CTL_EL0::ISTATUS) {
break;
}
}
// ISTATUS will be '1' when cval ticks have passed. Busy-check it.
while !CNTP_CTL_EL0.matches_all(CNTP_CTL_EL0::ISTATUS::SET) {}
// Disable counting again.
CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::CLEAR);

@ -8,4 +8,4 @@ mod bcm2xxx_gpio;
mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO;
pub use bcm2xxx_pl011_uart::PL011Uart;
pub use bcm2xxx_pl011_uart::{PL011Uart, PanicUart};

@ -127,7 +127,7 @@ register_structs! {
}
/// The driver's mutex protected part.
struct PL011UartInner {
pub struct PL011UartInner {
base_addr: usize,
chars_written: usize,
}
@ -151,13 +151,30 @@ impl ops::Deref for PL011UartInner {
}
impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner {
pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner {
base_addr,
chars_written: 0,
}
}
/// Set up baud rate and characteristics.
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
pub fn init(&self) {
// Turn it off temporarily.
self.CR.set(0);
self.ICR.write(ICR::ALL::CLEAR);
self.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
self.FBRD.write(FBRD::FBRD.val(3));
self.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
self.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
}
/// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _
@ -165,12 +182,8 @@ impl PL011UartInner {
/// Send a character.
fn write_char(&mut self, c: char) {
// Wait until we can send.
loop {
if !self.FR.is_set(FR::TXFF) {
break;
}
// Spin while TX FIFO full is set, waiting for an empty slot.
while self.FR.matches_all(FR::TXFF::SET) {
arch::nop();
}
@ -205,6 +218,11 @@ impl fmt::Write for PL011UartInner {
}
}
//--------------------------------------------------------------------------------------------------
// Export the inner struct so that BSPs can use it for the panic handler
//--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart;
//--------------------------------------------------------------------------------------------------
// BSP-public
//--------------------------------------------------------------------------------------------------
@ -235,26 +253,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"PL011Uart"
}
/// Set up baud rate and characteristics
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
fn init(&self) -> interface::driver::Result {
let mut r = &self.inner;
r.lock(|inner| {
// Turn it off temporarily.
inner.CR.set(0);
inner.ICR.write(ICR::ALL::CLEAR);
inner.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
inner.FBRD.write(FBRD::FBRD.val(3));
inner
.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
inner
.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
});
r.lock(|inner| inner.init());
Ok(())
}
@ -277,13 +278,11 @@ impl interface::console::Write for PL011Uart {
fn flush(&self) {
let mut r = &self.inner;
// Spin until the TX FIFO empty flag is set.
r.lock(|inner| loop {
if inner.FR.is_set(FR::TXFE) {
break;
// Spin until TX FIFO empty is set.
r.lock(|inner| {
while !inner.FR.matches_all(FR::TXFE::SET) {
arch::nop();
}
arch::nop();
});
}
}
@ -292,12 +291,8 @@ impl interface::console::Read for PL011Uart {
fn read_char(&self) -> char {
let mut r = &self.inner;
r.lock(|inner| {
// Wait until buffer is filled.
loop {
if !inner.FR.is_set(FR::RXFE) {
break;
}
// Spin while RX FIFO empty is set.
while inner.FR.matches_all(FR::RXFE::SET) {
arch::nop();
}
@ -315,12 +310,10 @@ impl interface::console::Read for PL011Uart {
fn clear(&self) {
let mut r = &self.inner;
r.lock(|inner| loop {
// Read from the RX FIFO until the empty bit is '1'.
if !inner.FR.is_set(FR::RXFE) {
r.lock(|inner| {
// Read from the RX FIFO until it is indicating empty.
while !inner.FR.matches_all(FR::RXFE::SET) {
inner.DR.get();
} else {
break;
}
})
}

@ -8,6 +8,7 @@ mod memory_map;
use super::driver;
use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -42,6 +43,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART
}
/// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted.
///
/// # Safety
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let uart = driver::PanicUart::new(memory_map::mmio::PL011_UART_BASE);
uart.init();
uart
}
/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
///
/// # Safety

@ -50,13 +50,11 @@ mod print;
unsafe fn kernel_init() -> ! {
for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() {
// This message will only be readable if, at the time of failure, the return value of
// `bsp::console()` is already in functioning state.
panic!("Error loading driver: {}", i.compatible())
}
}
bsp::post_driver_init();
// println! is usable from here on.
// Transition from unsafe to safe.
kernel_main()
@ -64,7 +62,7 @@ unsafe fn kernel_init() -> ! {
/// The main function running after the early init.
fn kernel_main() -> ! {
println!("Parking CPU core. Please connect over JTAG now.");
info!("Parking CPU core. Please connect over JTAG now.");
arch::wait_forever()
}

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits.
use crate::{arch, println};
use core::panic::PanicInfo;
use crate::{arch, bsp};
use core::{fmt, panic::PanicInfo};
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() {
println!("Kernel panic: {}", args);
panic_println!("Kernel panic: {}", args);
} else {
println!("Kernel panic!");
panic_println!("Kernel panic!");
}
arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface};
use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
@ -16,9 +22,19 @@ macro_rules! print {
}
/// Prints with a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
#[macro_export]
macro_rules! println {
() => ($crate::print!("\n"));
($($arg:tt)*) => ({
$crate::print::_print(format_args_nl!($($arg)*));
})
}
/// Prints am info, with newline.
#[macro_export]
macro_rules! info {
($string:expr) => ({
#[allow(unused_imports)]
use crate::interface::time::Timer;
@ -83,9 +99,3 @@ macro_rules! warn {
));
})
}
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}

Loading…
Cancel
Save