tg_rcore_tutorial_uart1/
uart.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum UartError {
9 InitFailed,
11 TxTimeout,
13 RxTimeout,
15}
16
17pub type Result<T> = core::result::Result<T, UartError>;
19
20const UART0: usize = 0x1000_0000;
22
23const RHR: usize = 0; const THR: usize = 0; const IER: usize = 1; const FCR: usize = 2; #[allow(dead_code)]
29const ISR: usize = 2; const LCR: usize = 3; const LSR: usize = 5; mod ier {
35 #[allow(dead_code)]
36 pub const RX_ENABLE: u8 = 1 << 0;
37 #[allow(dead_code)]
38 pub const TX_ENABLE: u8 = 1 << 1;
39}
40
41mod fcr {
43 pub const FIFO_ENABLE: u8 = 1 << 0;
44 pub const RX_FIFO_CLEAR: u8 = 1 << 1;
45 pub const TX_FIFO_CLEAR: u8 = 1 << 2;
46 pub const FIFO_CLEAR: u8 = RX_FIFO_CLEAR | TX_FIFO_CLEAR;
47}
48
49mod lcr {
51 pub const EIGHT_BITS: u8 = 3 << 0;
52 pub const BAUD_LATCH: u8 = 1 << 7;
53}
54
55mod lsr {
57 pub const RX_READY: u8 = 1 << 0;
58 pub const TX_IDLE: u8 = 1 << 5;
59}
60
61#[derive(Debug, Clone, Copy)]
63pub struct Uart;
64
65impl Uart {
66 #[inline]
68 pub const fn new() -> Self {
69 Self
70 }
71
72 pub fn init() -> Result<()> {
77 unsafe { write_reg(IER, 0) };
78 unsafe { write_reg(LCR, lcr::BAUD_LATCH) };
79 unsafe { write_reg(0, 0x03) };
80 unsafe { write_reg(1, 0x00) };
81 unsafe { write_reg(LCR, lcr::EIGHT_BITS) };
82 unsafe { write_reg(FCR, fcr::FIFO_ENABLE | fcr::FIFO_CLEAR) };
83 Ok(())
84 }
85
86 #[inline(never)]
91 pub fn put_char_sync(c: u8) -> Result<()> {
92 let mut timeout = 100_000;
93 while unsafe { read_reg(LSR) } & lsr::TX_IDLE == 0 {
94 timeout -= 1;
95 if timeout == 0 {
96 return Err(UartError::TxTimeout);
97 }
98 }
99 unsafe { write_reg(THR, c) };
100 Ok(())
101 }
102
103 #[inline]
107 pub fn put_char(c: u8) {
108 while unsafe { read_reg(LSR) } & lsr::TX_IDLE == 0 {}
109 unsafe { write_reg(THR, c) };
110 }
111
112 #[inline]
114 pub fn put_str(s: &str) {
115 for c in s.bytes() {
116 Self::put_char(c);
117 }
118 }
119
120 #[inline]
124 pub fn try_get_char() -> Option<u8> {
125 if unsafe { read_reg(LSR) } & lsr::RX_READY != 0 {
126 Some(unsafe { read_reg(RHR) })
127 } else {
128 None
129 }
130 }
131}
132
133#[inline]
135unsafe fn read_reg(offset: usize) -> u8 {
136 let addr = UART0 + offset;
137 unsafe { (addr as *const u8).read_volatile() }
138}
139
140#[inline]
142unsafe fn write_reg(offset: usize, value: u8) {
143 let addr = UART0 + offset;
144 unsafe { (addr as *mut u8).write_volatile(value) }
145}