mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-12 07:44:18 +00:00
there is still some mysterious problem involving a race condition of the raw hardware console UART Rx path deciding it doesn't want to report new characters anymore to the interrupt handler that is triggered when multi-byte sequences are shoved down the pipe. So long as you're typing simple commands it's fine, but escape sequences tend to lock things up. I don't think there's enough ROI to continue investigating this facility.
112 lines
3 KiB
Rust
112 lines
3 KiB
Rust
use core::fmt::{Error, Write};
|
|
|
|
use utralib::generated::*;
|
|
|
|
#[macro_export]
|
|
macro_rules! print
|
|
{
|
|
($($args:tt)+) => ({
|
|
use core::fmt::Write;
|
|
let _ = write!(crate::debug::Uart {}, $($args)+);
|
|
});
|
|
}
|
|
#[macro_export]
|
|
macro_rules! println
|
|
{
|
|
() => ({
|
|
print!("\r\n")
|
|
});
|
|
($fmt:expr) => ({
|
|
print!(concat!($fmt, "\r\n"))
|
|
});
|
|
($fmt:expr, $($args:tt)+) => ({
|
|
print!(concat!($fmt, "\r\n"), $($args)+)
|
|
});
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn handle_irq(irq_no: usize, arg: *mut usize) {
|
|
print!("Handling IRQ {} (arg: {:08x}): ", irq_no, arg as usize);
|
|
|
|
while let Some(c) = { crate::debug::Uart {} }.getc() {
|
|
print!("{}", c as char);
|
|
}
|
|
println!();
|
|
}
|
|
|
|
pub struct Uart {}
|
|
|
|
// this is a hack to bypass an explicit initialization/allocation step for the debug structure
|
|
pub static mut DEFAULT_UART_ADDR: *mut usize = 0x0000_0000 as *mut usize;
|
|
|
|
pub const DEFAULT: Uart = Uart {};
|
|
|
|
impl Uart {
|
|
fn map_uart(&self) {
|
|
/*
|
|
Note: the memory address and interrupt specified here needs to map to a unique hardware
|
|
UART resource. Modify in this function as necessary.
|
|
*/
|
|
let uart = xous::syscall::map_memory(
|
|
xous::MemoryAddress::new(utra::console::HW_CONSOLE_BASE),
|
|
None,
|
|
4096,
|
|
xous::MemoryFlags::R | xous::MemoryFlags::W,
|
|
)
|
|
.expect("couldn't map debug uart");
|
|
unsafe {
|
|
DEFAULT_UART_ADDR = uart.as_mut_ptr() as _;
|
|
}
|
|
println!("Mapped UART @ {:08x}", uart.as_ptr() as usize);
|
|
// core::mem::forget(uart);
|
|
|
|
println!("Allocating IRQ...");
|
|
/* xous::claim_interrupt(
|
|
utra::console::CONSOLE_IRQ,
|
|
handle_irq,
|
|
core::ptr::null_mut::<usize>(),
|
|
)
|
|
.expect("unable to allocate IRQ"); */
|
|
self.enable_rx();
|
|
}
|
|
|
|
pub fn putc(&self, c: u8) {
|
|
if unsafe { DEFAULT_UART_ADDR } as usize == 0 {
|
|
self.map_uart();
|
|
}
|
|
let mut uart_csr = CSR::new(unsafe { DEFAULT_UART_ADDR as *mut u32 });
|
|
|
|
// Wait until TXFULL is `0`
|
|
while uart_csr.r(utra::uart::TXFULL) != 0 {}
|
|
uart_csr.wo(utra::uart::RXTX, c as u32);
|
|
}
|
|
|
|
pub fn enable_rx(&self) {
|
|
let mut uart_csr = CSR::new(unsafe { DEFAULT_UART_ADDR as *mut u32 });
|
|
uart_csr.rmwf(utra::uart::EV_ENABLE_RX, 1);
|
|
}
|
|
#[allow(dead_code)]
|
|
pub fn getc(&self) -> Option<u8> {
|
|
if unsafe { DEFAULT_UART_ADDR } as usize == 0 {
|
|
self.map_uart();
|
|
}
|
|
let mut uart_csr = CSR::new(unsafe { DEFAULT_UART_ADDR as *mut u32 });
|
|
match uart_csr.rf(utra::uart::EV_PENDING_RX) {
|
|
0 => None,
|
|
ack => {
|
|
let c = Some(uart_csr.rf(utra::uart::RXTX_RXTX) as u8);
|
|
uart_csr.wfo(utra::uart::EV_PENDING_RX, ack);
|
|
c
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Write for Uart {
|
|
fn write_str(&mut self, s: &str) -> Result<(), Error> {
|
|
for c in s.bytes() {
|
|
self.putc(c);
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|