continue improvements
This commit is contained in:
parent
dc7918a696
commit
731fe7ca4f
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user