Compare commits
2 commits
ca47faf168
...
c1d2723f7d
Author | SHA1 | Date | |
---|---|---|---|
c1d2723f7d | |||
719837d753 |
5 changed files with 33 additions and 125 deletions
|
@ -1,8 +1,6 @@
|
||||||
//! Board Support Package: module containing implementation
|
//! Board Support Package: module containing implementation
|
||||||
//! specific to a board.
|
//! specific to a board.
|
||||||
|
|
||||||
pub mod qemu;
|
|
||||||
|
|
||||||
#[cfg(feature = "target_rpi3")]
|
#[cfg(feature = "target_rpi3")]
|
||||||
pub mod rpi3;
|
pub mod rpi3;
|
||||||
|
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
//! Implement the Qemu magic UART.
|
|
||||||
|
|
||||||
use core::fmt;
|
|
||||||
|
|
||||||
use crate::traits::console::{Console, Read, Write};
|
|
||||||
use crate::traits::synchronization::{DummyMutex, Mutex};
|
|
||||||
|
|
||||||
/// The address for the magic qemu uart
|
|
||||||
const QEMU_MAGIC_UART_ADDR: *mut u8 = 0x3F20_1000 as *mut u8;
|
|
||||||
const QEMU_MAGIC_UART_ADDR_FR: *mut u8 = 0x3F20_1018 as *mut u8;
|
|
||||||
|
|
||||||
/// The unique QemuUart allowing access to the qemu uart.
|
|
||||||
static QEMU_UART: QemuUart = QemuUart::new();
|
|
||||||
|
|
||||||
/// A structure allowing access to the qemu magic uart.
|
|
||||||
struct QemuUart {
|
|
||||||
inner: DummyMutex<QemuUartInner>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Inner Qemu Uart.
|
|
||||||
struct QemuUartInner;
|
|
||||||
|
|
||||||
impl QemuUartInner {
|
|
||||||
/// Constructor for [`QemuUartInner`].
|
|
||||||
const fn new() -> Self {
|
|
||||||
Self {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write a character to the output.
|
|
||||||
fn write_char(&mut self, c: char) {
|
|
||||||
unsafe {
|
|
||||||
core::ptr::write_volatile(QEMU_MAGIC_UART_ADDR, c as u8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read a character from the uart.
|
|
||||||
fn read_char(&mut self) -> char {
|
|
||||||
loop {
|
|
||||||
let fr = unsafe { core::ptr::read_volatile(QEMU_MAGIC_UART_ADDR_FR) };
|
|
||||||
if fr & 0b1_0000 == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
core::ptr::read_volatile(QEMU_MAGIC_UART_ADDR) as u8 as char
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl QemuUart {
|
|
||||||
/// Constructor for [`QemuUart`].
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
inner: DummyMutex::new(QemuUartInner::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allow to use QemuUartInner for print! and formating macros.
|
|
||||||
/// `write_str` needs `&mut self` (mutable ref), so we can implement
|
|
||||||
/// it only on the inner type, the `QemuUart` need to be manipulable
|
|
||||||
/// using unmutable references (`&self`), so we will use a custom
|
|
||||||
/// interface for it.
|
|
||||||
impl fmt::Write for QemuUartInner {
|
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
||||||
for c in s.chars() {
|
|
||||||
// \n -> \r\n
|
|
||||||
if c == '\n' {
|
|
||||||
self.write_char('\r');
|
|
||||||
}
|
|
||||||
self.write_char(c);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Write for QemuUart {
|
|
||||||
fn write_char(&self, c: char) {
|
|
||||||
self.inner.lock(|q_out| q_out.write_char(c))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result {
|
|
||||||
self.inner.lock(|q_out| fmt::Write::write_fmt(q_out, args))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Empty function, the qemu uart has no buffering afaik
|
|
||||||
fn flush(&self) {
|
|
||||||
// self.inner.lock(|q_out| q_out.flush())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Read for QemuUart {
|
|
||||||
fn read_char(&self) -> char {
|
|
||||||
self.inner.lock(|q_in| q_in.read_char())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush_input(&self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Console for QemuUart {}
|
|
||||||
|
|
||||||
// TODO: move?
|
|
||||||
/// Return a reference to the Qemu Uart.
|
|
||||||
pub fn console() -> &'static dyn Console {
|
|
||||||
&QEMU_UART
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
//! Implement the features specific to code running inside qemu.
|
|
||||||
//!
|
|
||||||
//! # TODO
|
|
||||||
//!
|
|
||||||
//! Move this somewhere else?
|
|
||||||
|
|
||||||
pub mod console;
|
|
|
@ -29,7 +29,7 @@ impl<'a> UartInner<'a> {
|
||||||
|
|
||||||
self.flush();
|
self.flush();
|
||||||
|
|
||||||
// Stop UART
|
// Stop UART, see doc of CR register for the config process (P 185, doc BCM2835)
|
||||||
self.memory_map.cr_uarten.read_and_write(0);
|
self.memory_map.cr_uarten.read_and_write(0);
|
||||||
|
|
||||||
// Flush the FIFOs
|
// Flush the FIFOs
|
||||||
|
@ -54,7 +54,8 @@ impl<'a> UartInner<'a> {
|
||||||
self.memory_map.lcrh.write_without_read(lcrh_val);
|
self.memory_map.lcrh.write_without_read(lcrh_val);
|
||||||
|
|
||||||
let cr_val = self.memory_map.cr_txe.read_and_write_to_u32(1, 0);
|
let cr_val = self.memory_map.cr_txe.read_and_write_to_u32(1, 0);
|
||||||
// TODO: let cr_val = self.memory_map.cr_rxe.read_and_write_to_u32(1, 0); to enable read
|
let cr_val = self.memory_map.cr_rxe.read_and_write_to_u32(1, cr_val);
|
||||||
|
// Again, see doc of CR register for the config process (P 185, doc BCM2835)
|
||||||
self.memory_map.cr.write_without_read(cr_val);
|
self.memory_map.cr.write_without_read(cr_val);
|
||||||
|
|
||||||
// Start the UART
|
// Start the UART
|
||||||
|
@ -67,11 +68,16 @@ impl<'a> UartInner<'a> {
|
||||||
self.memory_map.fr_busy.read() != 0
|
self.memory_map.fr_busy.read() != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test if the the TX FIFO is full.
|
/// Test if the TX FIFO is full.
|
||||||
fn is_tx_full(&self) -> bool {
|
fn is_tx_full(&self) -> bool {
|
||||||
self.memory_map.fr_txff.read() != 0
|
self.memory_map.fr_txff.read() != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test if the RX FIFO is empty
|
||||||
|
fn is_rx_empty(&self) -> bool {
|
||||||
|
self.memory_map.fr_rxfe.read() != 0
|
||||||
|
}
|
||||||
|
|
||||||
/// Write a character to the Uart
|
/// Write a character to the Uart
|
||||||
fn write_char(&self, c: char) {
|
fn write_char(&self, c: char) {
|
||||||
if !self.initialized {
|
if !self.initialized {
|
||||||
|
@ -85,12 +91,28 @@ impl<'a> UartInner<'a> {
|
||||||
self.memory_map.dr_data.write_without_read(c as u32);
|
self.memory_map.dr_data.write_without_read(c as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flush the uart
|
/// Read a character from the UART.
|
||||||
|
/// Blocking.
|
||||||
|
fn blocking_read_char(&self) -> char {
|
||||||
|
while self.is_rx_empty() {
|
||||||
|
unsafe { asm!("nop") };
|
||||||
|
}
|
||||||
|
self.memory_map.dr_data.read() as u8 as char
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Flush the output of the uart
|
||||||
fn flush(&self) {
|
fn flush(&self) {
|
||||||
while self.is_busy() {
|
while self.is_busy() {
|
||||||
unsafe { asm!("nop") };
|
unsafe { asm!("nop") };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flush the input of the uart
|
||||||
|
fn flush_input(&self) {
|
||||||
|
while !self.is_rx_empty() {
|
||||||
|
let _ = self.memory_map.dr_data.read() as u8 as char;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow the use of uart for fmt::Write::write_fmt.
|
// Allow the use of uart for fmt::Write::write_fmt.
|
||||||
|
@ -122,10 +144,12 @@ impl Write for Uart<'_> {
|
||||||
|
|
||||||
impl Read for Uart<'_> {
|
impl Read for Uart<'_> {
|
||||||
fn read_char(&self) -> char {
|
fn read_char(&self) -> char {
|
||||||
todo!()
|
self.inner.lock(|uart| uart.blocking_read_char())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush_input(&self) {}
|
fn flush_input(&self) {
|
||||||
|
self.inner.lock(|uart| uart.flush_input())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Uart<'a> {
|
impl<'a> Uart<'a> {
|
||||||
|
|
|
@ -27,9 +27,8 @@ use core::arch::global_asm;
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
|
|
||||||
// TODO: handle this with features
|
// TODO: handle this with features
|
||||||
use crate::bsp::qemu::console::console;
|
#[cfg(not(test))]
|
||||||
//#[cfg(not(test))]
|
use crate::bsp::rpi3::uart::console;
|
||||||
//use crate::bsp::rpi3::uart::console;
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use crate::bsp::rpi3::gpio;
|
use crate::bsp::rpi3::gpio;
|
||||||
|
|
||||||
|
@ -66,7 +65,7 @@ pub unsafe fn _start_rust() -> ! {
|
||||||
match gpio::set_pin_output_state(20, gpio::PinOutputState::Low) {
|
match gpio::set_pin_output_state(20, gpio::PinOutputState::Low) {
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
//bsp::rpi3::uart::init();
|
bsp::rpi3::uart::init();
|
||||||
println!("Hello there");
|
println!("Hello there");
|
||||||
|
|
||||||
let mut buffer = ['X'; 200];
|
let mut buffer = ['X'; 200];
|
||||||
|
|
Loading…
Reference in a new issue