1use core::{num::NonZeroU32, ptr::NonNull};
2
3use rdif_serial::{
4 InterruptMask, IrqSnapshot, IrqSource, RawUart, RxFlag, RxSample, SerialDirection, SerialEvent,
5 TransBytesError, TransferError,
6};
7use tock_registers::{
8 LocalRegisterCopy, interfaces::*, register_bitfields, register_structs, registers::*,
9};
10
11use crate::{Config, ConfigError, DataBits, Parity, StopBits};
12
13register_bitfields! [
14 u32,
15
16 UARTDR [
18 DATA OFFSET(0) NUMBITS(8) [],
19 FE OFFSET(8) NUMBITS(1) [],
20 PE OFFSET(9) NUMBITS(1) [],
21 BE OFFSET(10) NUMBITS(1) [],
22 OE OFFSET(11) NUMBITS(1) []
23 ],
24
25 UARTRSR_ECR [
27 FE OFFSET(0) NUMBITS(1) [],
28 PE OFFSET(1) NUMBITS(1) [],
29 BE OFFSET(2) NUMBITS(1) [],
30 OE OFFSET(3) NUMBITS(1) []
31 ],
32
33 UARTFR [
35 CTS OFFSET(0) NUMBITS(1) [],
36 DSR OFFSET(1) NUMBITS(1) [],
37 DCD OFFSET(2) NUMBITS(1) [],
38 BUSY OFFSET(3) NUMBITS(1) [],
39 RXFE OFFSET(4) NUMBITS(1) [],
40 TXFF OFFSET(5) NUMBITS(1) [],
41 RXFF OFFSET(6) NUMBITS(1) [],
42 TXFE OFFSET(7) NUMBITS(1) [],
43 RI OFFSET(8) NUMBITS(1) []
44 ],
45
46 UARTIBRD [
48 BAUD_DIVINT OFFSET(0) NUMBITS(16) []
49 ],
50
51 UARTFBRD [
53 BAUD_DIVFRAC OFFSET(0) NUMBITS(6) []
54 ],
55
56 UARTLCR_H [
58 BRK OFFSET(0) NUMBITS(1) [],
59 PEN OFFSET(1) NUMBITS(1) [],
60 EPS OFFSET(2) NUMBITS(1) [],
61 STP2 OFFSET(3) NUMBITS(1) [],
62 FEN OFFSET(4) NUMBITS(1) [],
63 WLEN OFFSET(5) NUMBITS(2) [
64 FiveBit = 0,
65 SixBit = 1,
66 SevenBit = 2,
67 EightBit = 3
68 ],
69 SPS OFFSET(7) NUMBITS(1) []
70 ],
71
72 UARTCR [
74 UARTEN OFFSET(0) NUMBITS(1) [],
75 SIREN OFFSET(1) NUMBITS(1) [],
76 SIRLP OFFSET(2) NUMBITS(1) [],
77 LBE OFFSET(7) NUMBITS(1) [],
78 TXE OFFSET(8) NUMBITS(1) [],
79 RXE OFFSET(9) NUMBITS(1) [],
80 DTR OFFSET(10) NUMBITS(1) [],
81 RTS OFFSET(11) NUMBITS(1) [],
82 OUT1 OFFSET(12) NUMBITS(1) [],
83 OUT2 OFFSET(13) NUMBITS(1) [],
84 RTSEN OFFSET(14) NUMBITS(1) [],
85 CTSEN OFFSET(15) NUMBITS(1) []
86 ],
87
88 UARTIFLS [
90 TXIFLSEL OFFSET(0) NUMBITS(3) [],
91 RXIFLSEL OFFSET(3) NUMBITS(3) []
92 ],
93
94 UARTIS [
96 RIM OFFSET(0) NUMBITS(1) [],
97 CTSM OFFSET(1) NUMBITS(1) [],
98 DCDM OFFSET(2) NUMBITS(1) [],
99 DSRM OFFSET(3) NUMBITS(1) [],
100 RX OFFSET(4) NUMBITS(1) [],
101 TX OFFSET(5) NUMBITS(1) [],
102 RT OFFSET(6) NUMBITS(1) [],
103 FE OFFSET(7) NUMBITS(1) [],
104 PE OFFSET(8) NUMBITS(1) [],
105 BE OFFSET(9) NUMBITS(1) [],
106 OE OFFSET(10) NUMBITS(1) []
107 ],
108
109 UARTDMACR [
111 RXDMAE OFFSET(0) NUMBITS(1) [],
112 TXDMAE OFFSET(1) NUMBITS(1) [],
113 DMAONERR OFFSET(2) NUMBITS(1) []
114 ]
115];
116
117register_structs! {
118 pub Pl011Registers {
119 (0x000 => uartdr: ReadWrite<u32, UARTDR::Register>), (0x004 => uartrsr_ecr: ReadWrite<u32, UARTRSR_ECR::Register>), (0x008 => _reserved1), (0x018 => uartfr: ReadOnly<u32, UARTFR::Register>), (0x01c => _reserved2), (0x020 => uartilpr: ReadWrite<u32>), (0x024 => uartibrd: ReadWrite<u32, UARTIBRD::Register>), (0x028 => uartfbrd: ReadWrite<u32, UARTFBRD::Register>), (0x02c => uartlcr_h: ReadWrite<u32, UARTLCR_H::Register>), (0x030 => uartcr: ReadWrite<u32, UARTCR::Register>), (0x034 => uartifls: ReadWrite<u32, UARTIFLS::Register>), (0x038 => uartimsc: ReadWrite<u32, UARTIS::Register>), (0x03c => uartris: ReadOnly<u32, UARTIS::Register>), (0x040 => uartmis: ReadOnly<u32, UARTIS::Register>), (0x044 => uarticr: WriteOnly<u32, UARTIS::Register>), (0x048 => uartdmacr: ReadWrite<u32, UARTDMACR::Register>), (0x04c => _reserved3), (0x1000 => @END),
137 }
138}
139
140unsafe impl Sync for Pl011Registers {}
142
143pub struct Pl011 {
145 base: Reg,
146 clock_freq: u32,
147 saved_rx_status: Pl011RxStatus,
148}
149
150impl Pl011 {
151 pub fn new_no_clock(base: NonNull<u8>) -> Self {
156 let clock_freq = Self::detect_clock_frequency(base.as_ptr() as usize);
158 Self::new(base, clock_freq)
159 }
160
161 pub fn new(base: NonNull<u8>, clock_freq: u32) -> Self {
162 let base = Reg(base.cast());
163
164 Self {
165 base,
166 clock_freq,
167 saved_rx_status: Pl011RxStatus::empty(),
168 }
169 }
170
171 fn registers(&self) -> &Pl011Registers {
172 unsafe { &*self.base.0.as_ptr() }
173 }
174
175 fn detect_clock_frequency(base: usize) -> u32 {
177 let registers = unsafe { &*(base as *const Pl011Registers) };
179
180 use tock_registers::interfaces::Readable;
181 let ibrd = registers.uartibrd.read(UARTIBRD::BAUD_DIVINT);
182
183 if ibrd > 0 && ibrd <= 0xFFFF {
185 let estimated_clock = 16 * ibrd * 115200;
188
189 if (1_000_000..=100_000_000).contains(&estimated_clock) {
191 return estimated_clock;
192 }
193 }
194
195 24_000_000
197 }
198
199 fn set_baudrate_internal(&self, baudrate: u32) -> Result<(), ConfigError> {
201 let bauddiv = self.clock_freq / (16 * baudrate);
207 let remainder = self.clock_freq % (16 * baudrate);
208 let fbrd = (remainder * 64 + (16 * baudrate / 2)) / (16 * baudrate);
209
210 if bauddiv == 0 || bauddiv > 0xFFFF {
211 return Err(ConfigError::InvalidBaudrate);
212 }
213
214 self.registers()
215 .uartibrd
216 .write(UARTIBRD::BAUD_DIVINT.val(bauddiv));
217 self.registers()
218 .uartfbrd
219 .write(UARTFBRD::BAUD_DIVFRAC.val(fbrd));
220
221 Ok(())
222 }
223
224 fn set_data_bits_internal(&self, bits: DataBits) -> Result<(), ConfigError> {
225 let wlen = match bits {
226 DataBits::Five => UARTLCR_H::WLEN::FiveBit,
227 DataBits::Six => UARTLCR_H::WLEN::SixBit,
228 DataBits::Seven => UARTLCR_H::WLEN::SevenBit,
229 DataBits::Eight => UARTLCR_H::WLEN::EightBit,
230 };
231
232 self.registers().uartlcr_h.modify(wlen);
233 Ok(())
234 }
235
236 fn set_stop_bits_internal(&self, bits: StopBits) -> Result<(), ConfigError> {
237 match bits {
238 StopBits::One => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::CLEAR),
239 StopBits::Two => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::SET),
240 }
241
242 Ok(())
243 }
244
245 fn set_parity_internal(&self, parity: Parity) -> Result<(), ConfigError> {
246 match parity {
247 Parity::None => {
248 self.registers().uartlcr_h.modify(UARTLCR_H::PEN::CLEAR);
250 }
251 Parity::Odd => {
252 self.registers()
254 .uartlcr_h
255 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::CLEAR);
256 }
257 Parity::Even => {
258 self.registers()
260 .uartlcr_h
261 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::CLEAR);
262 }
263 Parity::Mark => {
264 self.registers()
266 .uartlcr_h
267 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::SET);
268 }
269 Parity::Space => {
270 self.registers()
272 .uartlcr_h
273 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::SET);
274 }
275 }
276
277 Ok(())
278 }
279
280 pub fn open(&mut self) {
282 self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
284
285 while self.registers().uartfr.is_set(UARTFR::BUSY) {
287 core::hint::spin_loop();
288 }
289
290 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
292
293 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
295
296 #[cfg(debug_assertions)]
298 {
299 let ifls = self.registers().uartifls.get();
300 let lcr_h = self.registers().uartlcr_h.get();
301 log::debug!("UART IFLS: 0x{:02x}, LCR_H: 0x{:02x}", ifls, lcr_h);
302 log::debug!(" FIFO enabled: {}", lcr_h & (1 << 4) != 0);
303 log::debug!(" RX trigger level: 1/8");
304 log::debug!(" TX trigger level: 1/2");
305 }
306 self.registers().uartimsc.set(0); self.registers()
309 .uartcr
310 .modify(UARTCR::UARTEN::SET + UARTCR::TXE::SET + UARTCR::RXE::SET);
311 }
312
313 pub fn set_irq_mask(&mut self, mask: InterruptMask) {
314 let mut imsc = 0;
315 if mask.intersects(InterruptMask::RX) {
316 imsc |= UARTIS::RX::SET.value
317 | UARTIS::RT::SET.value
318 | UARTIS::FE::SET.value
319 | UARTIS::PE::SET.value
320 | UARTIS::BE::SET.value
321 | UARTIS::OE::SET.value;
322 }
323 if mask.contains(InterruptMask::TX_SPACE) {
324 imsc |= UARTIS::TX::SET.value;
325 }
326
327 self.registers().uartimsc.set(imsc);
328 }
329
330 pub fn get_irq_mask(&self) -> InterruptMask {
331 let imsc = self.registers().uartimsc.extract();
332 let mut mask = InterruptMask::empty();
333
334 if imsc.is_set(UARTIS::RX)
335 || imsc.is_set(UARTIS::RT)
336 || imsc.is_set(UARTIS::FE)
337 || imsc.is_set(UARTIS::PE)
338 || imsc.is_set(UARTIS::BE)
339 || imsc.is_set(UARTIS::OE)
340 {
341 mask |= InterruptMask::RX;
342 }
343 if imsc.is_set(UARTIS::TX) {
344 mask |= InterruptMask::TX_SPACE;
345 }
346
347 mask
348 }
349
350 pub fn pending(&mut self, direction: SerialDirection) -> bool {
351 match direction {
352 SerialDirection::Input => !self.registers().uartfr.is_set(UARTFR::RXFE),
353 SerialDirection::Output => !self.registers().uartfr.is_set(UARTFR::TXFF),
354 }
355 }
356
357 pub fn poll_status(&mut self) -> SerialEvent {
358 let mut event = SerialEvent::empty();
359 let fr = self.registers().uartfr.extract();
360 if !fr.is_set(UARTFR::RXFE) {
361 event |= SerialEvent::RX_READY;
362 }
363 if !fr.is_set(UARTFR::TXFF) {
364 event |= SerialEvent::TX_READY;
365 }
366
367 let status =
368 self.saved_rx_status | Pl011RxStatus::from_rsr(self.registers().uartrsr_ecr.extract());
369 if status.intersects(Pl011RxStatus::FRAMING | Pl011RxStatus::PARITY | Pl011RxStatus::BREAK)
370 {
371 event |= SerialEvent::RX_ERROR;
372 }
373 if status.contains(Pl011RxStatus::OVERRUN) {
374 event |= SerialEvent::RX_ERROR | SerialEvent::OVERRUN;
375 }
376
377 event
378 }
379
380 pub fn try_write(&mut self, bytes: &[u8]) -> usize {
381 let mut written = 0;
382 for &byte in bytes {
383 let status = self.poll_status();
384 if !status.tx_ready() {
385 break;
386 }
387 self.write_byte(byte);
388 written += 1;
389 }
390 written
391 }
392
393 pub fn try_read(&mut self, bytes: &mut [u8]) -> Result<usize, TransBytesError> {
394 let mut count = 0;
395 for byte in bytes.iter_mut() {
396 let status = self.poll_status();
397 if !status.rx_ready() && !status.rx_error() {
398 break;
399 }
400 match self.read_byte(status) {
401 Some(Ok(b)) => {
402 *byte = b;
403 }
404 Some(Err(TransferError::Overrun(b))) => {
405 *byte = b;
406 count += 1;
407 return Err(TransBytesError {
408 bytes_transferred: count,
409 kind: TransferError::Overrun(b),
410 });
411 }
412 Some(Err(e)) => {
413 return Err(TransBytesError {
414 bytes_transferred: count,
415 kind: e,
416 });
417 }
418 None => break,
419 }
420 count += 1;
421 }
422 Ok(count)
423 }
424
425 pub fn handle_irq(&mut self) -> SerialEvent {
426 serial_event_from_snapshot(self.take_irq_snapshot())
427 }
428
429 pub fn write_byte(&mut self, byte: u8) {
430 self.registers().uartdr.set(byte as _);
431 }
432
433 pub fn read_byte(&mut self, status: SerialEvent) -> Option<Result<u8, TransferError>> {
434 if !status.rx_ready() && !status.rx_error() {
435 return None;
436 }
437
438 let sample = self.read_rx()?;
439 if sample.overrun {
440 return Some(Err(TransferError::Overrun(sample.byte.unwrap_or(0))));
441 }
442 match sample.flag {
443 RxFlag::Normal => sample.byte.map(Ok),
444 RxFlag::Break => Some(Err(TransferError::Break)),
445 RxFlag::Parity => Some(Err(TransferError::Parity)),
446 RxFlag::Framing => Some(Err(TransferError::Framing)),
447 }
448 }
449
450 pub fn take_irq_snapshot(&mut self) -> IrqSnapshot {
451 let mis = self.registers().uartmis.extract();
452 let active = mis.get();
453 if active == 0 {
454 return IrqSnapshot::default();
455 }
456
457 let mut sources = IrqSource::empty();
458 if mis.is_set(UARTIS::RX) {
459 sources |= IrqSource::RX_DATA;
460 }
461 if mis.is_set(UARTIS::RT) {
462 sources |= IrqSource::RX_TIMEOUT;
463 }
464 if mis.is_set(UARTIS::FE)
465 || mis.is_set(UARTIS::PE)
466 || mis.is_set(UARTIS::BE)
467 || mis.is_set(UARTIS::OE)
468 {
469 sources |= IrqSource::RX_STATUS;
470 self.saved_rx_status |= Pl011RxStatus::from_irq_status(mis);
471 }
472 if mis.is_set(UARTIS::TX) {
473 sources |= IrqSource::TX_SPACE;
474 }
475 if mis.is_set(UARTIS::CTSM)
476 || mis.is_set(UARTIS::DSRM)
477 || mis.is_set(UARTIS::DCDM)
478 || mis.is_set(UARTIS::RIM)
479 {
480 sources |= IrqSource::MODEM_STATUS;
481 }
482
483 self.registers()
484 .uarticr
485 .set(active & !(UARTIS::RX::SET.value | UARTIS::RT::SET.value));
486
487 IrqSnapshot {
488 claimed: true,
489 sources,
490 }
491 }
492
493 pub fn read_rx(&mut self) -> Option<RxSample> {
494 if self.registers().uartfr.is_set(UARTFR::RXFE) {
495 self.saved_rx_status |= Pl011RxStatus::from_rsr(self.registers().uartrsr_ecr.extract());
496 return self.saved_rx_status.take_status_sample();
497 }
498
499 let dr = self.registers().uartdr.extract();
500 let data = dr.read(UARTDR::DATA) as u8;
501 let status = Pl011RxStatus::from_data(dr);
502 if !status.is_empty() {
503 self.saved_rx_status.remove(status);
504 }
505
506 let flag = if status.contains(Pl011RxStatus::BREAK) {
507 RxFlag::Break
508 } else if status.contains(Pl011RxStatus::PARITY) {
509 RxFlag::Parity
510 } else if status.contains(Pl011RxStatus::FRAMING) {
511 RxFlag::Framing
512 } else {
513 RxFlag::Normal
514 };
515
516 Some(RxSample {
517 byte: Some(data),
518 flag,
519 overrun: status.contains(Pl011RxStatus::OVERRUN),
520 })
521 }
522}
523
524bitflags::bitflags! {
525 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
526 struct Pl011RxStatus: u32 {
527 const FRAMING = 1 << 0;
528 const PARITY = 1 << 1;
529 const BREAK = 1 << 2;
530 const OVERRUN = 1 << 3;
531 }
532}
533
534impl Pl011RxStatus {
535 fn from_data(dr: LocalRegisterCopy<u32, UARTDR::Register>) -> Self {
536 let mut status = Self::empty();
537 if dr.is_set(UARTDR::FE) {
538 status |= Self::FRAMING;
539 }
540 if dr.is_set(UARTDR::PE) {
541 status |= Self::PARITY;
542 }
543 if dr.is_set(UARTDR::BE) {
544 status |= Self::BREAK;
545 }
546 if dr.is_set(UARTDR::OE) {
547 status |= Self::OVERRUN;
548 }
549 status
550 }
551
552 fn from_irq_status(mis: LocalRegisterCopy<u32, UARTIS::Register>) -> Self {
553 let mut status = Self::empty();
554 if mis.is_set(UARTIS::FE) {
555 status |= Self::FRAMING;
556 }
557 if mis.is_set(UARTIS::PE) {
558 status |= Self::PARITY;
559 }
560 if mis.is_set(UARTIS::BE) {
561 status |= Self::BREAK;
562 }
563 if mis.is_set(UARTIS::OE) {
564 status |= Self::OVERRUN;
565 }
566 status
567 }
568
569 fn from_rsr(rsr: LocalRegisterCopy<u32, UARTRSR_ECR::Register>) -> Self {
570 let mut status = Self::empty();
571 if rsr.is_set(UARTRSR_ECR::FE) {
572 status |= Self::FRAMING;
573 }
574 if rsr.is_set(UARTRSR_ECR::PE) {
575 status |= Self::PARITY;
576 }
577 if rsr.is_set(UARTRSR_ECR::BE) {
578 status |= Self::BREAK;
579 }
580 if rsr.is_set(UARTRSR_ECR::OE) {
581 status |= Self::OVERRUN;
582 }
583 status
584 }
585
586 fn flag(self) -> RxFlag {
587 if self.contains(Self::BREAK) {
588 RxFlag::Break
589 } else if self.contains(Self::PARITY) {
590 RxFlag::Parity
591 } else if self.contains(Self::FRAMING) {
592 RxFlag::Framing
593 } else {
594 RxFlag::Normal
595 }
596 }
597
598 fn take_status_sample(&mut self) -> Option<RxSample> {
599 if self.is_empty() {
600 return None;
601 }
602
603 let status = *self;
604 *self = Self::empty();
605 Some(RxSample {
606 byte: None,
607 flag: status.flag(),
608 overrun: status.contains(Self::OVERRUN),
609 })
610 }
611}
612
613fn serial_event_from_snapshot(snapshot: IrqSnapshot) -> SerialEvent {
614 let mut event = SerialEvent::empty();
615 if !snapshot.claimed {
616 return event;
617 }
618 if snapshot
619 .sources
620 .intersects(IrqSource::RX_DATA | IrqSource::RX_TIMEOUT)
621 {
622 event |= SerialEvent::RX_READY;
623 }
624 if snapshot.sources.contains(IrqSource::RX_STATUS) {
625 event |= SerialEvent::RX_ERROR;
626 }
627 if snapshot.sources.contains(IrqSource::TX_SPACE) {
628 event |= SerialEvent::TX_READY;
629 }
630 if snapshot.sources.contains(IrqSource::MODEM_STATUS) {
631 event |= SerialEvent::MODEM_STATUS;
632 }
633 event
634}
635
636#[derive(Clone, Copy, PartialEq, Eq)]
637struct Reg(NonNull<Pl011Registers>);
638
639unsafe impl Send for Reg {}
640unsafe impl Sync for Reg {}
641
642impl RawUart for Pl011 {
643 fn name(&self) -> &'static str {
644 "PL011 UART"
645 }
646
647 fn base_addr(&self) -> usize {
648 self.base.0.as_ptr() as usize
649 }
650
651 fn clock_freq(&self) -> Option<NonZeroU32> {
652 self.clock_freq.try_into().ok()
653 }
654
655 fn startup(&mut self, config: &Config) -> Result<(), ConfigError> {
656 self.open();
657 self.set_config(config)?;
658 self.set_irq_mask(InterruptMask::empty());
659 Ok(())
660 }
661
662 fn shutdown(&mut self) {
663 self.registers().uartimsc.set(0);
664 self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
665 }
666
667 fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
668 use tock_registers::interfaces::Readable;
669
670 let original_cr = self.registers().uartcr.extract(); self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR); while self.registers().uartfr.is_set(UARTFR::BUSY) {
677 core::hint::spin_loop();
678 }
679
680 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
682
683 if let Some(baudrate) = config.baudrate {
685 self.set_baudrate_internal(baudrate)?;
686 }
687 if let Some(data_bits) = config.data_bits {
688 self.set_data_bits_internal(data_bits)?;
689 }
690 if let Some(stop_bits) = config.stop_bits {
691 self.set_stop_bits_internal(stop_bits)?;
692 }
693 if let Some(parity) = config.parity {
694 self.set_parity_internal(parity)?;
695 }
696
697 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
699
700 if original_cr.is_set(UARTCR::UARTEN) {
702 self.registers().uartcr.modify(
703 UARTCR::UARTEN.val(original_cr.read(UARTCR::UARTEN))
704 + UARTCR::TXE.val(original_cr.read(UARTCR::TXE))
705 + UARTCR::RXE.val(original_cr.read(UARTCR::RXE)),
706 );
707 }
708
709 Ok(())
710 }
711
712 fn baudrate(&self) -> u32 {
713 let ibrd = self.registers().uartibrd.read(UARTIBRD::BAUD_DIVINT);
714 let fbrd = self.registers().uartfbrd.read(UARTFBRD::BAUD_DIVFRAC);
715
716 let divisor = ibrd * 64 + fbrd;
719 if divisor == 0 {
720 return 0;
721 }
722
723 self.clock_freq * 64 / (16 * divisor)
724 }
725
726 fn data_bits(&self) -> DataBits {
727 let wlen = self.registers().uartlcr_h.read(UARTLCR_H::WLEN);
728
729 match wlen {
730 0 => DataBits::Five,
731 1 => DataBits::Six,
732 2 => DataBits::Seven,
733 3 => DataBits::Eight,
734 _ => DataBits::Eight, }
736 }
737
738 fn stop_bits(&self) -> StopBits {
739 if self.registers().uartlcr_h.is_set(UARTLCR_H::STP2) {
740 StopBits::Two
741 } else {
742 StopBits::One
743 }
744 }
745
746 fn parity(&self) -> Parity {
747 if !self.registers().uartlcr_h.is_set(UARTLCR_H::PEN) {
748 Parity::None
749 } else if self.registers().uartlcr_h.is_set(UARTLCR_H::SPS) {
750 if self.registers().uartlcr_h.is_set(UARTLCR_H::EPS) {
752 Parity::Space
753 } else {
754 Parity::Mark
755 }
756 } else {
757 if self.registers().uartlcr_h.is_set(UARTLCR_H::EPS) {
759 Parity::Even
760 } else {
761 Parity::Odd
762 }
763 }
764 }
765
766 fn enable_loopback(&mut self) {
767 self.registers().uartcr.modify(UARTCR::LBE::SET);
768 }
769
770 fn disable_loopback(&mut self) {
771 self.registers().uartcr.modify(UARTCR::LBE::CLEAR);
772 }
773
774 fn is_loopback_enabled(&self) -> bool {
775 self.registers().uartcr.is_set(UARTCR::LBE)
776 }
777
778 fn set_irq_mask(&mut self, mask: InterruptMask) {
779 Pl011::set_irq_mask(self, mask);
780 }
781
782 fn take_irq_snapshot(&mut self) -> IrqSnapshot {
783 Pl011::take_irq_snapshot(self)
784 }
785
786 fn read_rx(&mut self) -> Option<RxSample> {
787 Pl011::read_rx(self)
788 }
789
790 fn tx_ready(&mut self) -> bool {
791 !self.registers().uartfr.is_set(UARTFR::TXFF)
792 }
793
794 fn write_tx(&mut self, byte: u8) {
795 Pl011::write_byte(self, byte);
796 }
797
798 fn tx_load_size(&self) -> usize {
799 16
800 }
801
802 fn tx_idle(&mut self) -> bool {
803 let fr = self.registers().uartfr.extract();
804 !fr.is_set(UARTFR::BUSY) && !fr.is_set(UARTFR::TXFF)
805 }
806
807 fn poll_status(&mut self) -> SerialEvent {
808 Pl011::poll_status(self)
809 }
810
811 fn write_byte(&mut self, byte: u8) {
812 Pl011::write_byte(self, byte)
813 }
814
815 fn read_byte(&mut self, status: SerialEvent) -> Option<Result<u8, TransferError>> {
816 Pl011::read_byte(self, status)
817 }
818}
819
820impl Pl011 {
822 pub fn enable_fifo(&self, enable: bool) {
824 if enable {
825 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
826 } else {
827 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
828 }
829 }
830
831 pub fn set_fifo_trigger_level(&self, rx_level: u8, tx_level: u8) {
833 let rx_iflsel = match rx_level {
841 0..=2 => 0b000, 3..=4 => 0b001, 5..=8 => 0b010, 9..=12 => 0b011, _ => 0b100, };
847
848 let tx_iflsel = match tx_level {
849 0..=2 => 0b000, 3..=4 => 0b001, 5..=8 => 0b010, 9..=12 => 0b011, _ => 0b100, };
855
856 self.registers()
857 .uartifls
858 .write(UARTIFLS::RXIFLSEL.val(rx_iflsel) + UARTIFLS::TXIFLSEL.val(tx_iflsel));
859 }
860}
861
862#[cfg(test)]
865mod tests {
866 use core::ptr::NonNull;
867 use std::boxed::Box;
868
869 use rdif_serial::{OwnerId, OwnerLease, SerialParts, SerialPort};
870
871 use super::*;
872
873 fn pl011_with_registers() -> (Box<Pl011Registers>, Pl011) {
874 let mut regs = Box::new(unsafe { core::mem::zeroed::<Pl011Registers>() });
875 let ptr = NonNull::from(regs.as_mut()).cast::<u8>();
876 let uart = Pl011::new(ptr, 24_000_000);
877 (regs, uart)
878 }
879
880 fn pl011_with_overrun_data() -> (Box<Pl011Registers>, Pl011) {
881 let (regs, uart) = pl011_with_registers();
882 regs.uartdr
883 .set((UARTDR::DATA.val(0xab) + UARTDR::OE::SET).into());
884 (regs, uart)
885 }
886
887 fn write_test_reg(regs: &mut Pl011Registers, offset: usize, value: u32) {
888 unsafe {
889 (regs as *mut Pl011Registers)
890 .cast::<u32>()
891 .add(offset / core::mem::size_of::<u32>())
892 .write_volatile(value);
893 }
894 }
895
896 fn read_test_reg(regs: &Pl011Registers, offset: usize) -> u32 {
897 unsafe {
898 (regs as *const Pl011Registers)
899 .cast::<u32>()
900 .add(offset / core::mem::size_of::<u32>())
901 .read_volatile()
902 }
903 }
904
905 fn owner_lease() -> OwnerLease<'static> {
906 unsafe { OwnerLease::new_unchecked(OwnerId(0)) }
907 }
908
909 fn started_parts(uart: Pl011) -> SerialParts<64, 64> {
910 let parts = SerialPort::<64, 64>::split(uart, OwnerId(0));
911 parts.port.startup(owner_lease(), &Config::new()).unwrap();
912 parts
913 }
914
915 #[test]
916 fn raw_rx_reports_overrun_instead_of_swallowing_it() {
917 let (_regs, mut uart) = pl011_with_overrun_data();
918
919 let mut buf = [0];
920 let err = uart
921 .try_read(&mut buf)
922 .expect_err("overrun must be reported to the caller");
923
924 assert_eq!(buf[0], 0xab);
925 assert_eq!(err.bytes_transferred, 1);
926 assert_eq!(err.kind, TransferError::Overrun(0xab));
927 }
928
929 #[test]
930 fn raw_rx_sample_reports_overrun_instead_of_swallowing_it() {
931 let (mut regs, uart) = pl011_with_overrun_data();
932 let mut uart = uart;
933
934 write_test_reg(&mut regs, 0x040, UARTIS::OE::SET.value);
935 let snapshot = uart.take_irq_snapshot();
936 assert!(snapshot.claimed);
937 assert!(snapshot.sources.contains(IrqSource::RX_STATUS));
938
939 let sample = uart.read_rx().expect("RX sample should be available");
940 assert_eq!(sample.byte, Some(0xab));
941 assert_eq!(sample.flag, RxFlag::Normal);
942 assert!(sample.overrun);
943 }
944
945 #[test]
946 fn irq_status_without_rx_byte_is_preserved_after_irq_ack() {
947 let (mut regs, mut uart) = pl011_with_registers();
948
949 write_test_reg(
950 &mut regs,
951 0x040,
952 UARTIS::OE::SET.value | UARTIS::PE::SET.value,
953 );
954 write_test_reg(&mut regs, 0x018, UARTFR::RXFE::SET.value);
955
956 let snapshot = uart.take_irq_snapshot();
957 assert!(snapshot.claimed);
958 assert!(snapshot.sources.contains(IrqSource::RX_STATUS));
959
960 let sample = uart.read_rx().expect("saved RX status should be available");
961 assert_eq!(sample.byte, None);
962 assert_eq!(sample.flag, RxFlag::Parity);
963 assert!(sample.overrun);
964 assert!(uart.read_rx().is_none());
965 }
966
967 #[test]
968 fn serial_core_tx_irq_drains_software_fifo() {
969 let (mut regs, uart) = pl011_with_registers();
970 let parts = started_parts(uart);
971 let mut tx = parts.tx;
972 let mut irq = parts.irq;
973
974 write_test_reg(&mut regs, 0x018, UARTFR::TXFF::SET.value);
975 assert_eq!(tx.submit(b"x").accepted, 1);
976 assert_eq!(tx.chars_in_buffer(), 1);
977
978 write_test_reg(&mut regs, 0x018, 0);
979 write_test_reg(&mut regs, 0x040, UARTIS::TX::SET.value);
980 let outcome = irq.handle(owner_lease());
981 assert!(outcome.claimed);
982 assert_eq!(outcome.tx_sent, 1);
983 assert_eq!(regs.uartdr.get() as u8, b'x');
984 assert_eq!(tx.chars_in_buffer(), 0);
985 }
986
987 #[test]
988 fn tx_irq_snapshot_acknowledges_tx_interrupt() {
989 let (mut regs, mut uart) = pl011_with_registers();
990
991 write_test_reg(&mut regs, 0x040, UARTIS::TX::SET.value);
992 let snapshot = uart.take_irq_snapshot();
993
994 assert!(snapshot.claimed);
995 assert!(snapshot.sources.contains(IrqSource::TX_SPACE));
996 assert_eq!(
997 read_test_reg(®s, 0x044) & UARTIS::TX::SET.value,
998 UARTIS::TX::SET.value
999 );
1000 }
1001
1002 #[test]
1003 fn set_config_preserves_enabled_tx_and_rx_paths() {
1004 let (regs, mut uart) = pl011_with_registers();
1005 regs.uartcr
1006 .write(UARTCR::UARTEN::SET + UARTCR::TXE::SET + UARTCR::RXE::SET);
1007
1008 uart.set_config(&Config::new()).unwrap();
1009
1010 let cr = regs.uartcr.extract();
1011 assert!(cr.is_set(UARTCR::UARTEN));
1012 assert!(cr.is_set(UARTCR::TXE));
1013 assert!(cr.is_set(UARTCR::RXE));
1014 }
1015
1016 #[test]
1017 fn rx_available_mask_enables_timeout_and_error_interrupts() {
1018 let (regs, mut uart) = pl011_with_registers();
1019
1020 uart.set_irq_mask(InterruptMask::RX_AVAILABLE);
1021
1022 let imsc = regs.uartimsc.extract();
1023 assert!(imsc.is_set(UARTIS::RX));
1024 assert!(imsc.is_set(UARTIS::RT));
1025 assert!(imsc.is_set(UARTIS::FE));
1026 assert!(imsc.is_set(UARTIS::PE));
1027 assert!(imsc.is_set(UARTIS::BE));
1028 assert!(imsc.is_set(UARTIS::OE));
1029 assert_eq!(uart.get_irq_mask(), InterruptMask::RX_AVAILABLE);
1030 }
1031
1032 #[test]
1033 fn hard_irq_does_not_claim_rx_ready_without_mis() {
1034 let (mut regs, mut uart) = pl011_with_registers();
1035
1036 uart.set_irq_mask(InterruptMask::RX_AVAILABLE);
1037 write_test_reg(&mut regs, 0x040, 0);
1038 write_test_reg(&mut regs, 0x018, 0);
1039
1040 assert!(uart.handle_irq().is_empty());
1041 }
1042
1043 #[test]
1044 fn raw_rx_ready_is_visible_without_irq_snapshot() {
1045 let (mut regs, mut uart) = pl011_with_registers();
1046
1047 uart.set_irq_mask(InterruptMask::RX_AVAILABLE);
1048 write_test_reg(&mut regs, 0x040, 0);
1049 write_test_reg(&mut regs, 0x018, 0);
1050 regs.uartdr.set(UARTDR::DATA.val(b'r' as u32).into());
1051
1052 let status = uart.poll_status();
1053 assert!(status.rx_ready());
1054 let sample = uart.read_rx().expect("RX sample should be available");
1055 assert_eq!(sample.byte, Some(b'r'));
1056 assert_eq!(sample.flag, RxFlag::Normal);
1057 }
1058}