some_serial/pl011/
control.rs1use super::*;
2
3pub struct Pl011 {
5 pub(super) base: Reg,
6 clock_freq: u32,
7 pub(super) saved_rx_status: Pl011RxStatus,
8}
9
10impl Pl011 {
11 pub fn new_no_clock(base: NonNull<u8>) -> Self {
16 let clock_freq = Self::detect_clock_frequency(base.as_ptr() as usize);
18 Self::new(base, clock_freq)
19 }
20
21 pub fn new(base: NonNull<u8>, clock_freq: u32) -> Self {
22 let base = Reg(base.cast());
23
24 Self {
25 base,
26 clock_freq,
27 saved_rx_status: Pl011RxStatus::empty(),
28 }
29 }
30
31 pub(super) fn registers(&self) -> &Pl011Registers {
32 unsafe { &*self.base.0.as_ptr() }
33 }
34
35 pub(super) fn current_baudrate(&self) -> u32 {
36 let ibrd = self.registers().uartibrd.read(UARTIBRD::BAUD_DIVINT);
37 let fbrd = self.registers().uartfbrd.read(UARTFBRD::BAUD_DIVFRAC);
38 let divisor = ibrd * 64 + fbrd;
39 if divisor == 0 {
40 0
41 } else {
42 self.clock_freq * 64 / (16 * divisor)
43 }
44 }
45
46 fn detect_clock_frequency(base: usize) -> u32 {
48 let registers = unsafe { &*(base as *const Pl011Registers) };
50
51 use tock_registers::interfaces::Readable;
52 let ibrd = registers.uartibrd.read(UARTIBRD::BAUD_DIVINT);
53
54 if ibrd > 0 && ibrd <= 0xFFFF {
56 let estimated_clock = 16 * ibrd * 115200;
59
60 if (1_000_000..=100_000_000).contains(&estimated_clock) {
62 return estimated_clock;
63 }
64 }
65
66 24_000_000
68 }
69
70 pub(super) fn set_baudrate_internal(&self, baudrate: u32) -> Result<(), ConfigError> {
72 let scaled_baudrate = baudrate
78 .checked_mul(16)
79 .filter(|scaled| *scaled != 0)
80 .ok_or(ConfigError::InvalidBaudrate)?;
81 let bauddiv = self.clock_freq / scaled_baudrate;
82 let remainder = self.clock_freq % scaled_baudrate;
83 let fbrd = (remainder * 64 + (scaled_baudrate / 2)) / scaled_baudrate;
84
85 if bauddiv == 0 || bauddiv > 0xFFFF {
86 return Err(ConfigError::InvalidBaudrate);
87 }
88
89 self.registers()
90 .uartibrd
91 .write(UARTIBRD::BAUD_DIVINT.val(bauddiv));
92 self.registers()
93 .uartfbrd
94 .write(UARTFBRD::BAUD_DIVFRAC.val(fbrd));
95
96 Ok(())
97 }
98
99 pub(super) fn wait_until_not_busy(&self) -> Result<(), ConfigError> {
100 for _ in 0..BUSY_POLL_BUDGET {
101 if !self.registers().uartfr.is_set(UARTFR::BUSY) {
102 return Ok(());
103 }
104 core::hint::spin_loop();
105 }
106 Err(ConfigError::Timeout)
107 }
108
109 pub(super) fn set_data_bits_internal(&self, bits: DataBits) -> Result<(), ConfigError> {
110 let wlen = match bits {
111 DataBits::Five => UARTLCR_H::WLEN::FiveBit,
112 DataBits::Six => UARTLCR_H::WLEN::SixBit,
113 DataBits::Seven => UARTLCR_H::WLEN::SevenBit,
114 DataBits::Eight => UARTLCR_H::WLEN::EightBit,
115 };
116
117 self.registers().uartlcr_h.modify(wlen);
118 Ok(())
119 }
120
121 pub(super) fn set_stop_bits_internal(&self, bits: StopBits) -> Result<(), ConfigError> {
122 match bits {
123 StopBits::One => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::CLEAR),
124 StopBits::Two => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::SET),
125 }
126
127 Ok(())
128 }
129
130 pub(super) fn set_parity_internal(&self, parity: Parity) -> Result<(), ConfigError> {
131 match parity {
132 Parity::None => {
133 self.registers().uartlcr_h.modify(UARTLCR_H::PEN::CLEAR);
135 }
136 Parity::Odd => {
137 self.registers()
139 .uartlcr_h
140 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::CLEAR);
141 }
142 Parity::Even => {
143 self.registers()
145 .uartlcr_h
146 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::CLEAR);
147 }
148 Parity::Mark => {
149 self.registers()
151 .uartlcr_h
152 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::SET);
153 }
154 Parity::Space => {
155 self.registers()
157 .uartlcr_h
158 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::SET);
159 }
160 }
161
162 Ok(())
163 }
164
165 pub fn open(&mut self) -> Result<(), ConfigError> {
167 let original_cr = self.registers().uartcr.get();
168
169 self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
171
172 if let Err(error) = self.wait_until_not_busy() {
174 self.registers().uartcr.set(original_cr);
175 return Err(error);
176 }
177
178 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
180
181 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
183
184 #[cfg(debug_assertions)]
186 {
187 let ifls = self.registers().uartifls.get();
188 let lcr_h = self.registers().uartlcr_h.get();
189 log::debug!("UART IFLS: 0x{:02x}, LCR_H: 0x{:02x}", ifls, lcr_h);
190 log::debug!(" FIFO enabled: {}", lcr_h & (1 << 4) != 0);
191 log::debug!(" RX trigger level: 1/8");
192 log::debug!(" TX trigger level: 1/2");
193 }
194 self.registers().uartimsc.set(0); self.registers()
197 .uartcr
198 .modify(UARTCR::UARTEN::SET + UARTCR::TXE::SET + UARTCR::RXE::SET);
199 Ok(())
200 }
201
202 pub fn set_irq_mask(&mut self, events: SerialEventSet) {
203 self.registers().uartimsc.set(imsc_for_events(events));
204 }
205
206 pub fn get_irq_mask(&self) -> SerialEventSet {
207 let imsc = self.registers().uartimsc.extract();
208 let mut events = SerialEventSet::empty();
209
210 if imsc.is_set(UARTIS::RX)
211 || imsc.is_set(UARTIS::RT)
212 || imsc.is_set(UARTIS::FE)
213 || imsc.is_set(UARTIS::PE)
214 || imsc.is_set(UARTIS::BE)
215 || imsc.is_set(UARTIS::OE)
216 {
217 events |= SerialEventSet::RX;
218 }
219 if imsc.is_set(UARTIS::TX) {
220 events |= SerialEventSet::TX_SPACE;
221 }
222
223 events
224 }
225
226 pub fn pending(&mut self, direction: SerialDirection) -> bool {
227 match direction {
228 SerialDirection::Input => !self.registers().uartfr.is_set(UARTFR::RXFE),
229 SerialDirection::Output => !self.registers().uartfr.is_set(UARTFR::TXFF),
230 }
231 }
232
233 pub fn poll_status(&mut self) -> SerialEvent {
234 let mut event = SerialEvent::empty();
235 let fr = self.registers().uartfr.extract();
236 if !fr.is_set(UARTFR::RXFE) {
237 event |= SerialEvent::RX_READY;
238 }
239 if !fr.is_set(UARTFR::TXFF) {
240 event |= SerialEvent::TX_READY;
241 }
242
243 let status =
244 self.saved_rx_status | Pl011RxStatus::from_rsr(self.registers().uartrsr_ecr.extract());
245 if status.intersects(Pl011RxStatus::FRAMING | Pl011RxStatus::PARITY | Pl011RxStatus::BREAK)
246 {
247 event |= SerialEvent::RX_ERROR;
248 }
249 if status.contains(Pl011RxStatus::OVERRUN) {
250 event |= SerialEvent::RX_ERROR | SerialEvent::OVERRUN;
251 }
252
253 event
254 }
255
256 pub fn try_write(&mut self, bytes: &[u8]) -> usize {
257 let mut written = 0;
258 for &byte in bytes {
259 let status = self.poll_status();
260 if !status.tx_ready() {
261 break;
262 }
263 self.write_byte(byte);
264 written += 1;
265 }
266 written
267 }
268
269 pub fn try_read(&mut self, bytes: &mut [u8]) -> Result<usize, TransBytesError> {
270 let mut count = 0;
271 for byte in bytes.iter_mut() {
272 let status = self.poll_status();
273 if !status.rx_ready() && !status.rx_error() {
274 break;
275 }
276 match self.read_byte(status) {
277 Some(Ok(b)) => {
278 *byte = b;
279 }
280 Some(Err(TransferError::Overrun(b))) => {
281 *byte = b;
282 count += 1;
283 return Err(TransBytesError {
284 bytes_transferred: count,
285 kind: TransferError::Overrun(b),
286 });
287 }
288 Some(Err(e)) => {
289 return Err(TransBytesError {
290 bytes_transferred: count,
291 kind: e,
292 });
293 }
294 None => break,
295 }
296 count += 1;
297 }
298 Ok(count)
299 }
300
301 pub fn write_byte(&mut self, byte: u8) {
302 self.registers().uartdr.set(byte as _);
303 }
304
305 pub fn read_byte(&mut self, status: SerialEvent) -> Option<Result<u8, TransferError>> {
306 if !status.rx_ready() && !status.rx_error() {
307 return None;
308 }
309
310 let sample = self.read_rx()?;
311 if sample.overrun {
312 return Some(Err(TransferError::Overrun(sample.byte.unwrap_or(0))));
313 }
314 match sample.flag {
315 RxFlag::Normal => sample.byte.map(Ok),
316 RxFlag::Break => Some(Err(TransferError::Break)),
317 RxFlag::Parity => Some(Err(TransferError::Parity)),
318 RxFlag::Framing => Some(Err(TransferError::Framing)),
319 }
320 }
321
322 pub fn read_rx(&mut self) -> Option<RxSample> {
323 let base = self.base;
324 let registers = unsafe { &*base.0.as_ptr() };
327 read_rx_sample(registers, &mut self.saved_rx_status)
328 }
329
330 pub fn enable_fifo(&self, enable: bool) {
332 if enable {
333 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
334 } else {
335 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
336 }
337 }
338
339 pub fn set_fifo_trigger_level(&self, rx_level: u8, tx_level: u8) {
341 let rx_iflsel = match rx_level {
349 0..=2 => 0b000, 3..=4 => 0b001, 5..=8 => 0b010, 9..=12 => 0b011, _ => 0b100, };
355
356 let tx_iflsel = match tx_level {
357 0..=2 => 0b000, 3..=4 => 0b001, 5..=8 => 0b010, 9..=12 => 0b011, _ => 0b100, };
363
364 self.registers()
365 .uartifls
366 .write(UARTIFLS::RXIFLSEL.val(rx_iflsel) + UARTIFLS::TXIFLSEL.val(tx_iflsel));
367 }
368}