lifeblood_os/src/uart.rs

107 lines
No EOL
2.3 KiB
Rust

use core::fmt::Write;
// todo: this should probably be in the dev module
pub trait Serial {
fn put(&self, c: u8);
fn putstr(&self, s: &str);
fn put_bytes(&self, s: &[u8]);
fn get(&self) -> Option<u8>;
}
pub struct UART {
offset: usize,
}
impl UART {
pub fn init(&self) {
let offset = self.offset as *mut u8;
unsafe {
// word length
let lcr = (1 << 0) | (1 << 1);
offset.add(3).write_volatile(lcr);
// enable fifo
offset.add(2).write_volatile(1 << 0);
// receiver buffer interrupts
offset.add(1).write_volatile(1 << 0);
// divisor boilerplate code, maybe check this later if we want custom baud rate
let divisor: u16 = 592;
let dlo: u8 = (divisor & 0xff) as u8;
let dhi: u8 = (divisor >> 8) as u8;
offset.add(3).write_volatile(lcr | 1 << 7);
offset.add(0).write_volatile(dlo);
offset.add(1).write_volatile(dhi);
offset.add(3).write_volatile(lcr);
}
}
pub fn new_and_init(offset: usize) -> UART {
let uart = UART { offset: offset };
uart.init();
uart
}
pub const fn new(offset: usize) -> UART {
let uart = UART { offset: offset };
uart
}
pub fn get(&self) -> Option<u8> {
unsafe {
if (self.offset as *mut u8).add(5).read_volatile() & 1 == 0 {
None
} else {
Some((self.offset as *mut u8).add(0).read_volatile())
}
}
}
pub fn put(&self, c: u8) {
unsafe {
(self.offset as *mut u8).add(0).write_volatile(c);
}
}
pub fn putstr(&self, s: &str) {
for c in s.bytes() {
self.put(c);
}
}
pub fn put_bytes(&self, s: &[u8]) {
for c in s {
self.put(*c);
}
}
}
impl Write for UART {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
for c in s.bytes() {
self.put(c);
}
Ok(())
}
}
impl Serial for UART {
fn put(&self, c: u8) {
self.put(c);
}
fn putstr(&self, s: &str) {
self.putstr(s);
}
fn put_bytes(&self, s: &[u8]) {
self.put_bytes(s);
}
fn get(&self) -> Option<u8> {
self.get()
}
}