uart_xilinx/uart_16550/
uart.rs

1#[cfg(feature = "fmt")]
2use core::fmt;
3
4use super::registers::Registers;
5
6bitflags! {
7    /// Interrupt Enable Register (bitflags)
8    pub struct IER: u8 {
9        /// Enable Received Data Available Interrupt
10        const RDAI  = 0b0000_0001;
11        /// Enable Transmitter Holding Register Empty Interrupt
12        const THREI = 0b0000_0010;
13        /// Enable Receiver Line Status Interrupt
14        const RLSI  = 0b0000_0100;
15        /// Enable Modem Status Interrupt
16        const MSI   = 0b0000_1000;
17    }
18}
19
20bitflags! {
21    /// Line Status Register (bitflags)
22    pub struct LSR: u8 {
23        /// Data Ready
24        const DR   = 0b0000_0001;
25        /// Overrun Error
26        const OE   = 0b0000_0010;
27        /// Parity Error
28        const PE   = 0b0000_0100;
29        /// Framing Error
30        const FE   = 0b0000_1000;
31        /// Break Interrupt
32        const BI   = 0b0001_0000;
33        /// Transmitter Holding Register Empty
34        const THRE = 0b0010_0000;
35        /// Data Holding Regiters Empty
36        const DHRE = 0b0100_0000;
37        /// Error in Received FIFO
38        const RFE  = 0b1000_0000;
39    }
40}
41
42bitflags! {
43    /// Modem Status Register (bitflags)
44    pub struct MSR: u8 {
45        /// Delta Clear To Send
46        const DCTS = 0b0000_0001;
47        ///Delta Data Set Ready
48        const DDSR = 0b0000_0010;
49        ///Trailing Edge Ring Indicator
50        const TERI = 0b0000_0100;
51        ///Delta Data Carrier Detect
52        const DDCD = 0b0000_1000;
53        ///Clear To Send
54        const CTS  = 0b0001_0000;
55        ///Data Set Ready
56        const DSR  = 0b0010_0000;
57        ///Ring Indicator
58        const RI   = 0b0100_0000;
59        ///Carrier Detect
60        const CD   = 0b1000_0000;
61    }
62}
63
64#[derive(Debug, Clone, PartialEq)]
65pub enum InterruptType {
66    ModemStatus,
67    TransmitterHoldingRegisterEmpty,
68    ReceivedDataAvailable,
69    ReceiverLineStatus,
70    Timeout,
71    Reserved,
72}
73
74#[derive(Debug, Clone, PartialEq)]
75pub enum Parity {
76    No,
77    Odd,
78    Even,
79    Mark,
80    Space,
81}
82
83/// # MMIO version of AXI UART 16550
84///
85/// **Noticed** This hasn't been tested.
86pub struct MmioUartAxi16550<'a> {
87    reg: &'a mut Registers,
88}
89
90impl<'a> MmioUartAxi16550<'a> {
91    /// New a uart
92    pub fn new(base_address: usize) -> Self {
93        Self {
94            reg: cast!(base_address),
95        }
96    }
97
98    /// A basic way to init the uart with interrupt enable
99    ///
100    /// Other way to init can be done by using other methods below
101    pub fn init(&self, clock: usize, baud_rate: usize) {
102        // Enable DLAB and Set divisor
103        self.set_divisor(clock, baud_rate);
104
105        // Disable DLAB and set word length 8 bits, no parity, 1 stop bit
106        self.write_lcr(3);
107        // Enable FIFO
108        self.write_fcr(1);
109        // No modem control
110        self.write_mcr(0);
111        // Enable received_data_available_interrupt
112        self.enable_received_data_available_interrupt();
113        // Enable transmitter_holding_register_empty_interrupt
114        // self.enable_transmitter_holding_register_empty_interrupt();
115    }
116
117    /// Set a new base_address
118    pub fn set_base_address(&mut self, base_address: usize) {
119        self.reg = cast!(base_address);
120    }
121
122    /// Read a byte from uart
123    ///
124    /// Return `None` when data is not ready (RBR\[0\] != 1)
125    pub fn read_byte(&self) -> Option<u8> {
126        if self.is_data_ready() {
127            Some(self.read_rbr() as u8)
128        } else {
129            None
130        }
131    }
132
133    /// Write a byte to uart
134    ///
135    /// Error are not concerned now **MAYBE TODO**
136    pub fn write_byte(&self, byte: u8) {
137        self.write_thr(byte as u32);
138    }
139
140    /// write THR (offset + 0x0)
141    ///
142    /// Write Transmitter Holding Buffer to send data
143    #[inline]
144    pub fn write_thr(&self, value: u32) {
145        unsafe { self.reg.rw[0].write(value) }
146    }
147
148    /// read RBR (offset + 0x0)
149    ///
150    /// Read Receiver Buffer to get data
151    #[inline]
152    pub fn read_rbr(&self) -> u32 {
153        self.reg.rw[0].read()
154    }
155
156    /// read DLL (offset + 0x0)
157    ///
158    /// get divisor latch low byte in the register
159    #[inline]
160    pub fn read_dll(&self) -> u32 {
161        self.reg.rw[0].read()
162    }
163
164    /// write DLL (offset + 0x0)
165    ///
166    /// set divisor latch low byte in the register
167    #[inline]
168    pub fn write_dll(&self, value: u32) {
169        unsafe { self.reg.rw[0].write(value) }
170    }
171
172    /// read DLH (offset + 0x4)
173    ///
174    /// get divisor latch high byte in the register
175    #[inline]
176    pub fn read_dlh(&self) -> u32 {
177        self.reg.rw[1].read()
178    }
179
180    /// write DLH (offset + 0x4)
181    ///
182    /// set divisor latch high byte in the register
183    #[inline]
184    pub fn write_dlh(&self, value: u32) {
185        unsafe { self.reg.rw[1].write(value) }
186    }
187
188    /// Set divisor latch according to clock and baud_rate, then set DLAB to false
189    #[inline]
190    pub fn set_divisor(&self, clock: usize, baud_rate: usize) {
191        self.enable_divisor_latch_accessible();
192        let divisor = clock / (16 * baud_rate);
193        self.write_dll((divisor & 0b1111_1111) as u32);
194        self.write_dlh(((divisor >> 8) & 0b1111_1111) as u32);
195        self.disable_divisor_latch_accessible();
196    }
197
198    /// Read IER (offset + 0x4)
199    ///
200    /// Read IER to get what interrupts are enabled
201    #[inline]
202    pub fn read_ier(&self) -> u32 {
203        self.reg.rw[1].read()
204    }
205
206    /// Write IER (offset + 0x4)
207    ///
208    /// Write Interrupt Enable Register to turn on/off interrupts
209    #[inline]
210    pub fn write_ier(&self, value: u32) {
211        unsafe { self.reg.rw[1].write(value) }
212    }
213
214    /// Get IER bitflags
215    #[inline]
216    pub fn ier(&self) -> IER {
217        IER::from_bits_truncate(self.read_ier() as u8)
218    }
219
220    /// Set IER via bitflags
221    #[inline]
222    pub fn set_ier(&self, flag: IER) {
223        self.write_ier(flag.bits() as u32)
224    }
225
226    /// get whether modem status interrupt is enabled (IER\[3\])
227    pub fn is_modem_status_interrupt_enabled(&self) -> bool {
228        self.ier().contains(IER::MSI)
229    }
230
231    /// toggle modem status interrupt (IER\[3\])
232    pub fn toggle_modem_status_interrupt(&self) {
233        self.set_ier(self.ier() ^ IER::MSI)
234    }
235
236    /// enable modem status interrupt (IER\[3\])
237    pub fn enable_modem_status_interrupt(&self) {
238        self.set_ier(self.ier() | IER::MSI)
239    }
240
241    /// disable modem status interrupt (IER\[3\])
242    pub fn disable_modem_status_interrupt(&self) {
243        self.set_ier(self.ier() & !IER::MSI)
244    }
245
246    /// get whether receiver line status interrupt is enabled (IER\[2\])
247    pub fn is_receiver_line_status_interrupt_enabled(&self) -> bool {
248        self.ier().contains(IER::RLSI)
249    }
250
251    /// toggle receiver line status interrupt (IER\[2\])
252    pub fn toggle_receiver_line_status_interrupt(&self) {
253        self.set_ier(self.ier() ^ IER::RLSI)
254    }
255
256    /// enable receiver line status interrupt (IER\[2\])
257    pub fn enable_receiver_line_status_interrupt(&self) {
258        self.set_ier(self.ier() | IER::RLSI)
259    }
260
261    /// disable receiver line status interrupt (IER\[2\])
262    pub fn disable_receiver_line_status_interrupt(&self) {
263        self.set_ier(self.ier() & !IER::RLSI)
264    }
265
266    /// get whether transmitter holding register empty interrupt is enabled (IER\[1\])
267    pub fn is_transmitter_holding_register_empty_interrupt_enabled(&self) -> bool {
268        self.ier().contains(IER::THREI)
269    }
270
271    /// toggle transmitter holding register empty interrupt (IER\[1\])
272    pub fn toggle_transmitter_holding_register_empty_interrupt(&self) {
273        self.set_ier(self.ier() ^ IER::THREI)
274    }
275
276    /// enable transmitter holding register empty interrupt (IER\[1\])
277    pub fn enable_transmitter_holding_register_empty_interrupt(&self) {
278        self.set_ier(self.ier() | IER::THREI)
279    }
280
281    /// disable transmitter holding register empty interrupt (IER\[1\])
282    pub fn disable_transmitter_holding_register_empty_interrupt(&self) {
283        self.set_ier(self.ier() & !IER::THREI)
284    }
285
286    /// get whether received data available is enabled (IER\[0\])
287    pub fn is_received_data_available_interrupt_enabled(&self) -> bool {
288        self.ier().contains(IER::RDAI)
289    }
290
291    /// toggle received data available (IER\[0\])
292    pub fn toggle_received_data_available_interrupt(&self) {
293        self.set_ier(self.ier() ^ IER::RDAI)
294    }
295
296    /// enable received data available (IER\[0\])
297    pub fn enable_received_data_available_interrupt(&self) {
298        self.set_ier(self.ier() | IER::RDAI)
299    }
300
301    /// disable received data available (IER\[0\])
302    pub fn disable_received_data_available_interrupt(&self) {
303        self.set_ier(self.ier() & !IER::RDAI)
304    }
305
306    /// Read IIR (offset + 0x8)
307    #[inline]
308    pub fn read_iir(&self) -> u32 {
309        self.reg.rw[2].read()
310    }
311
312    /// Read IIR\[7:6\] to get whether FIFO is enabled
313    pub fn is_fifo_enabled(&self) -> bool {
314        self.reg.rw[2].read() & 0b1100_0000 != 0
315    }
316
317    /// Read IIR\[3:1\] to get interrupt type
318    pub fn read_interrupt_type(&self) -> Option<InterruptType> {
319        let irq = self.reg.rw[2].read() & 0b0000_1111;
320        if irq & 1 != 0 {
321            None
322        } else {
323            match irq {
324                0b0000 => Some(InterruptType::ModemStatus),
325                0b0010 => Some(InterruptType::TransmitterHoldingRegisterEmpty),
326                0b0100 => Some(InterruptType::ReceivedDataAvailable),
327                0b0110 => Some(InterruptType::ReceiverLineStatus),
328                0b1100 => Some(InterruptType::Timeout),
329                0b1000 | 0b1010 | 0b1110 => Some(InterruptType::Reserved),
330                _ => panic!("Can't reached"),
331            }
332        }
333    }
334
335    /// get whether interrupt is pending (IIR\[0\])
336    ///
337    /// # Safety
338    ///
339    /// read iir will reset THREI, so use read_interrupt_type may be better
340    pub unsafe fn is_interrupt_pending(&self) -> bool {
341        self.reg.rw[2].read() & 1 == 0
342    }
343
344    /// Read FCR (offset + 0x8)
345    ///
346    /// # Safety
347    ///
348    /// In Xilinx doc, FCR can be read when DLAB == 1.
349    /// Please make sure DLAB is 1 when using this method.
350    #[inline]
351    pub unsafe fn read_fcr(&self) -> u32 {
352        self.reg.rw[2].read()
353    }
354
355    /// Write FCR (offset + 0x8) to control FIFO buffers
356    #[inline]
357    pub fn write_fcr(&self, value: u32) {
358        unsafe { self.reg.rw[2].write(value) }
359    }
360
361    /// Read LCR (offset + 0xc)
362    ///
363    /// Read Line Control Register to get the data protocol and DLAB
364    #[inline]
365    pub fn read_lcr(&self) -> u32 {
366        self.reg.rw[3].read()
367    }
368
369    /// Write LCR (offset + 0xc)
370    ///
371    /// Write Line Control Register to set DLAB and the serial data protocol
372    #[inline]
373    pub fn write_lcr(&self, value: u32) {
374        unsafe { self.reg.rw[3].write(value) }
375    }
376
377    /// get whether DLAB is enabled
378    pub fn is_divisor_latch_accessible(&self) -> bool {
379        self.reg.rw[3].read() & 0b1000_0000 != 0
380    }
381
382    /// toggle DLAB
383    pub fn toggle_divisor_latch_accessible(&self) {
384        unsafe { self.reg.rw[3].modify(|v| v ^ 0b1000_0000) }
385    }
386
387    /// enable DLAB
388    #[inline]
389    pub fn enable_divisor_latch_accessible(&self) {
390        unsafe { self.reg.rw[3].modify(|v| v | 0b1000_0000) }
391    }
392
393    /// disable DLAB
394    #[inline]
395    pub fn disable_divisor_latch_accessible(&self) {
396        unsafe { self.reg.rw[3].modify(|v| v & !0b1000_0000) }
397    }
398
399    /// get parity of used data protocol
400    pub fn get_parity(&self) -> Parity {
401        match self.reg.rw[3].read() & 0b0011_1000 {
402            0b0000_0000 => Parity::No,
403            0b0000_1000 => Parity::Odd,
404            0b0001_1000 => Parity::Even,
405            0b0010_1000 => Parity::Mark,
406            0b0011_1000 => Parity::Space,
407            _ => panic!("Invalid Parity! Please check your uart"),
408        }
409    }
410
411    /// set parity
412    pub fn set_parity(&self, parity: Parity) {
413        match parity {
414            Parity::No => unsafe { self.reg.rw[3].modify(|v| (v & 0b1100_0111)) },
415            Parity::Odd => unsafe { self.reg.rw[3].modify(|v| (v & 0b1100_0111) | 0b0000_1000) },
416            Parity::Even => unsafe { self.reg.rw[3].modify(|v| (v & 0b1100_0111) | 0b0001_1000) },
417            Parity::Mark => unsafe { self.reg.rw[3].modify(|v| (v & 0b1100_0111) | 0b0010_1000) },
418            Parity::Space => unsafe { self.reg.rw[3].modify(|v| v | 0b0011_1000) },
419        }
420    }
421
422    /// get stop bit of used data protocol
423    ///
424    /// Simply return a u8 to indicate 1 or 1.5/2 bits
425    pub fn get_stop_bit(&self) -> u32 {
426        ((self.reg.rw[3].read() & 0b100) >> 2) + 1
427    }
428
429    /// set stop bit, only 1 and 2 can be used as `stop_bit`
430    pub fn set_stop_bit(&self, stop_bit: u32) {
431        match stop_bit {
432            1 => unsafe { self.reg.rw[3].modify(|v| v & 0b1111_1011) },
433            2 => unsafe { self.reg.rw[3].modify(|v| v | 0b0000_0100) },
434            _ => panic!("Invalid stop bit"),
435        }
436    }
437
438    /// get word length of used data protocol
439    pub fn get_word_length(&self) -> u32 {
440        (self.reg.rw[3].read() & 0b11) + 5
441    }
442
443    /// set word length, only 5..=8 can be used as `length`
444    pub fn set_word_length(&self, length: u32) {
445        if (5..=8).contains(&length) {
446            unsafe { self.reg.rw[3].modify(|v| v | (length - 5)) }
447        } else {
448            panic!("Invalid word length")
449        }
450    }
451
452    /// Read MCR (offset + 0x10)
453    ///
454    /// Read Modem Control Register to get how flow is controlled
455    #[inline]
456    pub fn read_mcr(&self) -> u32 {
457        self.reg.rw[4].read()
458    }
459
460    /// Write MCR (offset + 0x10)
461    ///
462    /// Write Modem Control Register to control flow
463    #[inline]
464    pub fn write_mcr(&self, value: u32) {
465        unsafe { self.reg.rw[4].write(value) }
466    }
467
468    /// Read LSR (offset + 0x14)
469    #[inline]
470    pub fn read_lsr(&self) -> u32 {
471        self.reg.ro[0].read()
472    }
473
474    /// Get LSR bitflags
475    #[inline]
476    pub fn lsr(&self) -> LSR {
477        LSR::from_bits_truncate(self.read_lsr() as u8)
478    }
479
480    /// get whether there is an error in received FIFO
481    pub fn is_received_fifo_error(&self) -> bool {
482        self.lsr().contains(LSR::RFE)
483    }
484
485    /// get whether data holding registers are empty
486    pub fn is_data_holding_registers_empty(&self) -> bool {
487        self.lsr().contains(LSR::DHRE)
488    }
489
490    /// get whether transmitter holding register is empty
491    pub fn is_transmitter_holding_register_empty(&self) -> bool {
492        self.lsr().contains(LSR::THRE)
493    }
494
495    pub fn is_break_interrupt(&self) -> bool {
496        self.lsr().contains(LSR::BI)
497    }
498
499    pub fn is_framing_error(&self) -> bool {
500        self.lsr().contains(LSR::FE)
501    }
502
503    pub fn is_parity_error(&self) -> bool {
504        self.lsr().contains(LSR::PE)
505    }
506
507    pub fn is_overrun_error(&self) -> bool {
508        self.lsr().contains(LSR::OE)
509    }
510
511    pub fn is_data_ready(&self) -> bool {
512        self.lsr().contains(LSR::DR)
513    }
514
515    /// Read MSR (offset + 0x18)
516    #[inline]
517    pub fn read_msr(&self) -> u32 {
518        self.reg.ro[1].read()
519    }
520
521    /// Get MSR bitflags
522    #[inline]
523    pub fn msr(&self) -> MSR {
524        MSR::from_bits_truncate(self.read_msr() as u8)
525    }
526
527    pub fn is_carrier_detect(&self) -> bool {
528        self.msr().contains(MSR::CD)
529    }
530
531    pub fn is_ring_indicator(&self) -> bool {
532        self.msr().contains(MSR::RI)
533    }
534
535    pub fn is_data_set_ready(&self) -> bool {
536        self.msr().contains(MSR::DSR)
537    }
538
539    pub fn is_clear_to_send(&self) -> bool {
540        self.msr().contains(MSR::CTS)
541    }
542
543    pub fn is_delta_data_carrier_detect(&self) -> bool {
544        self.msr().contains(MSR::DDCD)
545    }
546
547    pub fn is_trailing_edge_ring_indicator(&self) -> bool {
548        self.msr().contains(MSR::TERI)
549    }
550
551    pub fn is_delta_data_set_ready(&self) -> bool {
552        self.msr().contains(MSR::DDSR)
553    }
554
555    pub fn is_delta_clear_to_send(&self) -> bool {
556        self.msr().contains(MSR::DCTS)
557    }
558
559    #[inline]
560    pub fn read_sr(&self) -> u32 {
561        self.reg.scratch.read()
562    }
563
564    #[inline]
565    pub fn write_sr(&self, value: u32) {
566        unsafe { self.reg.scratch.write(value) }
567    }
568}
569
570/// ## fmt::Write
571///
572/// A simple implementation, may be changed in the future
573#[cfg(feature = "fmt")]
574impl<'a> fmt::Write for MmioUartAxi16550<'a> {
575    fn write_str(&mut self, s: &str) -> fmt::Result {
576        for c in s.as_bytes() {
577            self.write_thr((*c) as u32);
578        }
579        Ok(())
580    }
581}