use bcm2837::mini_uart::{MiniUart, MiniUartInterruptId}; use lazy_static::lazy_static; use core::fmt; use spin::Mutex; use once::*; /// Struct to get a global SerialPort interface pub struct SerialPort { mu: MiniUart, } pub trait SerialRead { fn receive(&mut self) -> u8; } impl SerialPort { /// Creates a new instance of `SerialPort`. fn new() -> SerialPort { SerialPort { mu: MiniUart::new(), } } /// Init a newly created SerialPort, can only be called once. fn init(&mut self) { assert_has_not_been_called!("SerialPort::init must be called only once"); self.mu.init(); super::irq::register_irq(super::irq::Interrupt::Aux, handle_serial_irq); } /// Writes the byte `byte` to the UART device. fn write_byte(&mut self, byte: u8) { self.mu.write_byte(byte) } /// Reads a byte from the UART device, blocking until a byte is available. fn read_byte(&self) -> u8 { self.mu.read_byte() } // Whether the interrupt `id` is pending. fn interrupt_is_pending(&self, id: MiniUartInterruptId) -> bool { self.mu.interrupt_is_pending(id) } } impl SerialRead for SerialPort { fn receive(&mut self) -> u8 { self.read_byte() } } impl fmt::Write for SerialPort { fn write_str(&mut self, s: &str) -> fmt::Result { for byte in s.bytes() { match byte { // Backspace b'\x7f' => { self.write_byte(b'\x08'); self.write_byte(b' '); self.write_byte(b'\x08'); } // Return b'\n' => { self.write_byte(b'\r'); self.write_byte(b'\n'); } // Others _ => self.write_byte(byte), } } Ok(()) } } fn handle_serial_irq() { let serial = SERIAL_PORT.lock(); if serial.interrupt_is_pending(MiniUartInterruptId::Recive) { crate::trap::serial(serial.read_byte() as char) } } lazy_static! { pub static ref SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); } pub fn init() { SERIAL_PORT.lock().init(); }