some_serial/ns16550/
mmio.rs

1//! NS16550 MMIO 版本实现
2//!
3//! 适用于嵌入式平台的内存映射 IO 版本
4
5use rdif_serial::{BSerial, SerialDyn};
6
7use crate::ns16550::{Ns16550IrqHandler, Ns16550Reciever, Ns16550Sender};
8
9use super::{Kind, Ns16550};
10use core::ptr::NonNull;
11
12#[derive(Clone)]
13pub struct Mmio {
14    base: usize,
15    width: usize,
16}
17
18impl Kind for Mmio {
19    fn read_reg(&self, reg: u8) -> u8 {
20        unsafe {
21            let addr = self.base + (reg as usize) * self.width;
22            (addr as *const u8).read_volatile()
23        }
24    }
25
26    fn write_reg(&self, reg: u8, val: u8) {
27        unsafe {
28            let addr = self.base + (reg as usize) * self.width;
29            (addr as *mut u8).write_volatile(val);
30        }
31    }
32
33    fn get_base(&self) -> usize {
34        self.base
35    }
36}
37
38impl Ns16550<Mmio> {
39    pub fn new_mmio(base: NonNull<u8>, clock_freq: u32, reg_width: usize) -> Ns16550<Mmio> {
40        let base = Mmio {
41            base: base.as_ptr() as usize,
42            width: reg_width,
43        };
44
45        Ns16550 {
46            base: base.clone(),
47            clock_freq,
48            irq: Some(Ns16550IrqHandler { base: base.clone() }),
49            tx: Some(crate::Sender::Ns16550MmioSender(Ns16550Sender {
50                base: base.clone(),
51            })),
52            rx: Some(crate::Reciever::Ns16550MmioReciever(Ns16550Reciever {
53                base,
54            })),
55        }
56    }
57
58    pub fn new_mmio_boxed(base: NonNull<u8>, clock_freq: u32, reg_width: usize) -> BSerial {
59        SerialDyn::new_boxed(Ns16550::new_mmio(base, clock_freq, reg_width))
60    }
61
62    pub fn take_tx(&mut self) -> Option<crate::Sender> {
63        self.tx.take()
64    }
65
66    pub fn take_rx(&mut self) -> Option<crate::Reciever> {
67        self.rx.take()
68    }
69}