continue improvements

This commit is contained in:
Robin Müller 2024-09-23 11:27:06 +02:00
parent dc7918a696
commit 731fe7ca4f
Signed by: muellerr
GPG Key ID: A649FB78196E3849
2 changed files with 30 additions and 34 deletions

View File

@ -308,12 +308,6 @@ pub struct Uart<UartInstance, Pins> {
/// Serial receiver
pub struct Rx<Uart>(Uart);
// Serial receiver, using interrupts to offload reading to the hardware.
pub struct RxWithIrq<Uart> {
inner: Rx<Uart>,
// irq_info: IrqContextTimeoutOrMaxSize,
}
/// Serial transmitter
pub struct Tx<Uart>(Uart);
@ -588,7 +582,7 @@ impl<TxPinInst: TxPin<UartInstance>, RxPinInst: RxPin<UartInstance>, UartInstanc
) {
let (inner, pins) = self.downgrade_internal();
let (tx, rx) = inner.split();
(tx, RxWithIrq { inner: rx }, pins)
(tx, RxWithIrq(rx), pins)
}
delegate::delegate! {
@ -715,15 +709,23 @@ pub enum IrqError {
Uart(IrqUartError),
}
// Serial receiver, using interrupts to offload reading to the hardware.
pub struct RxWithIrq<Uart>(Rx<Uart>);
impl<Uart: Instance> RxWithIrq<Uart> {
/// This function should be called once at initialization time if the regular
/// [Self::irq_handler] is used to read the UART receiver to enable and start the receiver.
pub fn start(&mut self) {
self.inner.enable();
self.0.enable();
self.enable_rx_irq_sources(true);
unsafe { enable_interrupt(Uart::IRQ_RX) };
}
#[inline(always)]
pub fn uart(&self) -> &Uart {
&self.0 .0
}
/// This function is used together with the [Self::irq_handler_max_size_or_timeout_based]
/// function to read packets with a maximum size or variable sized packets by using the
/// receive timeout of the hardware.
@ -747,7 +749,7 @@ impl<Uart: Instance> RxWithIrq<Uart> {
#[inline]
fn enable_rx_irq_sources(&mut self, timeout: bool) {
self.inner.0.irq_enb().modify(|_, w| {
self.uart().irq_enb().modify(|_, w| {
if timeout {
w.irq_rx_to().set_bit();
}
@ -758,7 +760,7 @@ impl<Uart: Instance> RxWithIrq<Uart> {
#[inline]
fn disable_rx_irq_sources(&mut self) {
self.inner.0.irq_enb().modify(|_, w| {
self.uart().irq_enb().modify(|_, w| {
w.irq_rx_to().clear_bit();
w.irq_rx_status().clear_bit();
w.irq_rx().clear_bit()
@ -767,11 +769,7 @@ impl<Uart: Instance> RxWithIrq<Uart> {
pub fn cancel_transfer(&mut self) {
self.disable_rx_irq_sources();
self.inner.clear_fifo();
}
pub fn uart(&self) -> &Uart {
&self.inner.0
self.0.clear_fifo();
}
/// This function should be called in the user provided UART interrupt handler.
@ -785,8 +783,8 @@ impl<Uart: Instance> RxWithIrq<Uart> {
let mut result = IrqResult::default();
let mut current_idx = 0;
let irq_end = self.inner.0.irq_end().read();
let enb_status = self.inner.0.enable().read();
let irq_end = self.uart().irq_end().read();
let enb_status = self.uart().enable().read();
let rx_enabled = enb_status.rxenable().bit_is_set();
// Half-Full interrupt. We have a guaranteed amount of data we can read.
@ -795,19 +793,19 @@ impl<Uart: Instance> RxWithIrq<Uart> {
// We use this trick/hack because the timeout feature of the peripheral relies on data
// being in the RX FIFO. If data continues arriving, another half-full IRQ will fire.
// If not, the last byte(s) is/are emptied by the timeout interrupt.
let available_bytes = self.inner.0.rxfifoirqtrg().read().bits() as usize;
let available_bytes = self.uart().rxfifoirqtrg().read().bits() as usize;
// If this interrupt bit is set, the trigger level is available at the very least.
// Read everything as fast as possible
for _ in 0..available_bytes {
buf[current_idx] = (self.inner.0.data().read().bits() & 0xff) as u8;
buf[current_idx] = (self.uart().data().read().bits() & 0xff) as u8;
current_idx += 1;
}
}
// Timeout, empty the FIFO completely.
if irq_end.irq_rx_to().bit_is_set() {
let read_result = self.inner.read();
let read_result = self.0.read();
// While there is data in the FIFO, write it into the reception buffer
while let Some(byte) = self.read_handler(&mut result.errors, &read_result) {
buf[current_idx] = byte;
@ -821,8 +819,7 @@ impl<Uart: Instance> RxWithIrq<Uart> {
}
// Clear the interrupt status bits
self.inner
.0
self.uart()
.irq_clr()
.write(|w| unsafe { w.bits(irq_end.bits()) });
Ok(result)
@ -852,8 +849,8 @@ impl<Uart: Instance> RxWithIrq<Uart> {
}
let mut result = IrqResultMaxSizeTimeout::default();
let irq_end = self.inner.0.irq_end().read();
let enb_status = self.inner.0.enable().read();
let irq_end = self.uart().irq_end().read();
let enb_status = self.uart().enable().read();
let rx_enabled = enb_status.rxenable().bit_is_set();
// Half-Full interrupt. We have a guaranteed amount of data we can read.
@ -862,7 +859,7 @@ impl<Uart: Instance> RxWithIrq<Uart> {
// We use this trick/hack because the timeout feature of the peripheral relies on data
// being in the RX FIFO. If data continues arriving, another half-full IRQ will fire.
// If not, the last byte(s) is/are emptied by the timeout interrupt.
let available_bytes = self.inner.0.rxfifoirqtrg().read().bits() as usize;
let available_bytes = self.uart().rxfifoirqtrg().read().bits() as usize;
let bytes_to_read = core::cmp::min(
available_bytes.saturating_sub(1),
@ -872,7 +869,7 @@ impl<Uart: Instance> RxWithIrq<Uart> {
// If this interrupt bit is set, the trigger level is available at the very least.
// Read everything as fast as possible
for _ in 0..bytes_to_read {
buf[context.rx_idx] = (self.inner.0.data().read().bits() & 0xff) as u8;
buf[context.rx_idx] = (self.uart().data().read().bits() & 0xff) as u8;
context.rx_idx += 1;
}
@ -888,7 +885,7 @@ impl<Uart: Instance> RxWithIrq<Uart> {
if context.rx_idx == context.max_len {
break;
}
let read_result = self.inner.read();
let read_result = self.0.read();
if let Some(byte) = self.read_handler(&mut result.errors, &read_result) {
buf[context.rx_idx] = byte;
context.rx_idx += 1;
@ -906,8 +903,7 @@ impl<Uart: Instance> RxWithIrq<Uart> {
}
// Clear the interrupt status bits
self.inner
.0
self.uart()
.irq_clr()
.write(|w| unsafe { w.bits(irq_end.bits()) });
Ok(result)
@ -943,7 +939,7 @@ impl<Uart: Instance> RxWithIrq<Uart> {
fn check_for_errors(&self, errors: &mut IrqUartError) {
// Read status register again, might have changed since reading received data
let rx_status = self.inner.0.rxstatus().read();
let rx_status = self.uart().rxstatus().read();
if rx_status.rxovr().bit_is_set() {
errors.overflow = true;
}
@ -961,7 +957,7 @@ impl<Uart: Instance> RxWithIrq<Uart> {
context: &mut IrqContextTimeoutOrMaxSize,
) {
self.disable_rx_irq_sources();
self.inner.disable();
self.0.disable();
res.bytes_read = context.rx_idx;
res.complete = true;
context.mode = IrqReceptionMode::Idle;
@ -969,7 +965,7 @@ impl<Uart: Instance> RxWithIrq<Uart> {
}
pub fn release(self) -> Uart {
self.inner.release()
self.0.release()
}
}