Skip to main content

some_serial/pl011/
runtime.rs

1use super::*;
2
3#[derive(Clone, Copy)]
4struct Pl011ConfigSnapshot {
5    ilpr: u32,
6    ibrd: u32,
7    fbrd: u32,
8    lcr_h: u32,
9    cr: u32,
10    ifls: u32,
11    imsc: u32,
12    dmacr: u32,
13}
14
15impl Pl011ConfigSnapshot {
16    fn capture(registers: &Pl011Registers) -> Self {
17        Self {
18            ilpr: registers.uartilpr.get(),
19            ibrd: registers.uartibrd.get(),
20            fbrd: registers.uartfbrd.get(),
21            lcr_h: registers.uartlcr_h.get(),
22            cr: registers.uartcr.get(),
23            ifls: registers.uartifls.get(),
24            imsc: registers.uartimsc.get(),
25            dmacr: registers.uartdmacr.get(),
26        }
27    }
28
29    fn restore(self, registers: &Pl011Registers) {
30        registers.uartilpr.set(self.ilpr);
31        registers.uartibrd.set(self.ibrd);
32        registers.uartfbrd.set(self.fbrd);
33        registers.uartlcr_h.set(self.lcr_h);
34        registers.uartifls.set(self.ifls);
35        registers.uartimsc.set(self.imsc);
36        registers.uartdmacr.set(self.dmacr);
37        // Restore CR last so the original enable state is not published until
38        // every dependent configuration register is back in place.
39        registers.uartcr.set(self.cr);
40    }
41}
42
43impl UartPort for Pl011 {
44    fn startup(&mut self, config: &Config) -> Result<(), ConfigError> {
45        let snapshot = Pl011ConfigSnapshot::capture(self.registers());
46        if let Err(error) = self.open().and_then(|()| self.set_config(config)) {
47            snapshot.restore(self.registers());
48            return Err(error);
49        }
50        self.mask_all();
51        Ok(())
52    }
53
54    fn shutdown(&mut self) {
55        self.registers().uartimsc.set(0);
56        self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
57    }
58
59    fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
60        let snapshot = Pl011ConfigSnapshot::capture(self.registers());
61        let result = (|| {
62            self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
63            self.wait_until_not_busy()?;
64
65            self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
66            if let Some(baudrate) = config.baudrate {
67                self.set_baudrate_internal(baudrate)?;
68            }
69            if let Some(data_bits) = config.data_bits {
70                self.set_data_bits_internal(data_bits)?;
71            }
72            if let Some(stop_bits) = config.stop_bits {
73                self.set_stop_bits_internal(stop_bits)?;
74            }
75            if let Some(parity) = config.parity {
76                self.set_parity_internal(parity)?;
77            }
78            self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
79            self.registers().uartcr.set(snapshot.cr);
80            Ok(())
81        })();
82
83        if result.is_err() {
84            snapshot.restore(self.registers());
85        }
86        result
87    }
88
89    fn read_rx(&mut self) -> Option<RxSample> {
90        Pl011::read_rx(self)
91    }
92
93    fn discard_rx(&mut self) {
94        // PL011 has no independent RX FIFO reset bit. The hardware FIFO holds
95        // at most 32 bytes, so consume one fixed-capacity snapshot without
96        // perturbing the TX path or disabling the whole UART.
97        for _ in 0..32 {
98            if self.registers().uartfr.is_set(UARTFR::RXFE) {
99                break;
100            }
101            let _ = self.registers().uartdr.get();
102        }
103        self.registers().uartrsr_ecr.set(0);
104        self.saved_rx_status = Pl011RxStatus::empty();
105        self.registers()
106            .uarticr
107            .set(imsc_for_events(SerialEventSet::RX));
108    }
109
110    fn discard_tx(&mut self) -> bool {
111        // Clearing FEN or UARTEN would also disturb RX. PL011 cannot flush the
112        // TX FIFO independently, so report the unsupported operation without
113        // changing shared UART state.
114        false
115    }
116
117    fn write_tx(&mut self, bytes: &[u8]) -> usize {
118        let mut written = 0;
119        for &byte in bytes {
120            if self.registers().uartfr.is_set(UARTFR::TXFF) {
121                break;
122            }
123            self.registers().uartdr.set(byte as u32);
124            written += 1;
125        }
126        written
127    }
128
129    fn tx_idle(&mut self) -> bool {
130        let fr = self.registers().uartfr.extract();
131        !fr.is_set(UARTFR::BUSY) && !fr.is_set(UARTFR::TXFF)
132    }
133
134    fn mask(&mut self, sources: SerialEventSet) {
135        let enabled = self.registers().uartimsc.get();
136        self.registers()
137            .uartimsc
138            .set(enabled & !imsc_for_events(sources));
139    }
140
141    fn mask_all(&mut self) {
142        self.registers().uartimsc.set(0);
143    }
144
145    fn rearm(&mut self, sources: SerialEventSet) -> SerialEventSet {
146        let enabled = self.registers().uartimsc.get() | imsc_for_events(sources);
147        self.registers().uartimsc.set(enabled);
148
149        let fr = self.registers().uartfr.extract();
150        let rsr = self.registers().uartrsr_ecr.extract();
151        let mut ready = SerialEventSet::empty();
152        if sources.intersects(SerialEventSet::RX) && !fr.is_set(UARTFR::RXFE) {
153            ready |= SerialEventSet::RX_DATA;
154        }
155        if sources.contains(SerialEventSet::RX_STATUS) && !Pl011RxStatus::from_rsr(rsr).is_empty() {
156            ready |= SerialEventSet::RX_STATUS;
157        }
158        if sources.contains(SerialEventSet::TX_SPACE) && !fr.is_set(UARTFR::TXFF) {
159            ready |= SerialEventSet::TX_SPACE;
160        }
161        if !ready.is_empty() {
162            self.registers()
163                .uartimsc
164                .set(enabled & !imsc_for_events(ready));
165        }
166        ready
167    }
168}
169
170impl SplitUart for Pl011 {
171    type Control = Self;
172    type Irq = Pl011Irq;
173    type EmergencyTx = Pl011EmergencyTx;
174
175    fn runtime_info(&self) -> UartInfo {
176        UartInfo {
177            name: "PL011 UART",
178            register_base: self.base.0.as_ptr() as usize,
179            initial_baudrate: self.current_baudrate(),
180        }
181    }
182
183    fn split(self) -> SerialParts<Self::Control, Self::Irq, Self::EmergencyTx> {
184        let irq = Pl011Irq {
185            base: self.base,
186            saved_rx_status: Pl011RxStatus::empty(),
187        };
188        let emergency_tx = Pl011EmergencyTx { base: self.base };
189        SerialParts::new(self, irq, emergency_tx)
190    }
191}
192
193impl PollingUart for Pl011 {
194    fn poll_status(&mut self) -> SerialEvent {
195        Pl011::poll_status(self)
196    }
197
198    fn write_byte(&mut self, byte: u8) {
199        Pl011::write_byte(self, byte);
200    }
201
202    fn read_byte(&mut self, status: SerialEvent) -> Option<Result<u8, TransferError>> {
203        Pl011::read_byte(self, status)
204    }
205}