diff --git a/CHANGELOG.md b/CHANGELOG.md index 832d370c..82656007 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +- use `Listen` for `Rx/Tx` + ## [v0.23.0] - 2025-09-22 - Implement `embedded_hal::i2c::I2c` for `I2cMasterDma` [#838] diff --git a/examples/rtic-serial-dma-rx-idle.rs b/examples/rtic-serial-dma-rx-idle.rs index 2d13b412..01ba8be3 100644 --- a/examples/rtic-serial-dma-rx-idle.rs +++ b/examples/rtic-serial-dma-rx-idle.rs @@ -76,7 +76,7 @@ mod app { .unwrap(); // Listen UART IDLE event, which will be call USART1 interrupt - rx.listen_idle(); + rx.listen(serial::RxEvent::Idle); let dma2 = StreamsTuple::new(dp.DMA2, &mut rcc); diff --git a/examples/uart-dma.rs b/examples/uart-dma.rs index 9d3fab63..70cc606e 100644 --- a/examples/uart-dma.rs +++ b/examples/uart-dma.rs @@ -159,7 +159,7 @@ fn main() -> ! { let (tx, mut rx) = uart3.split(); - rx.listen_idle(); + rx.listen(serial::RxEvent::Idle); cortex_m::interrupt::free(|cs| *G_UART3_TX.borrow(cs).borrow_mut() = Some(tx)); diff --git a/src/dma/mod.rs b/src/dma/mod.rs index e5bee19f..64d75f74 100644 --- a/src/dma/mod.rs +++ b/src/dma/mod.rs @@ -456,18 +456,12 @@ where type Event = DmaEvent; #[inline(always)] - fn listen(&mut self, interrupts: impl Into>) { - self.listen_event(None, Some(interrupts.into())); - } - - #[inline(always)] - fn listen_only(&mut self, interrupts: impl Into>) { - self.listen_event(Some(BitFlags::ALL), Some(interrupts.into())); - } - - #[inline(always)] - fn unlisten(&mut self, interrupts: impl Into>) { - self.listen_event(Some(interrupts.into()), None); + fn listen_event( + &mut self, + disable: Option>, + enable: Option>, + ) { + self.listen_event(disable, enable) } } diff --git a/src/lib.rs b/src/lib.rs index ecc0e994..c0dee8bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -177,20 +177,35 @@ pub trait Listen { /// Enum of bit flags associated with events type Event: BitFlag; + #[doc(hidden)] + fn listen_event( + &mut self, + disable: Option>, + enable: Option>, + ); + /// Start listening for `Event`s /// /// Note, you will also have to enable the appropriate interrupt in the NVIC to start /// receiving events. - fn listen(&mut self, event: impl Into>); + #[inline(always)] + fn listen(&mut self, event: impl Into>) { + self.listen_event(None, Some(event.into())); + } /// Start listening for `Event`s, stop all other /// /// Note, you will also have to enable the appropriate interrupt in the NVIC to start /// receiving events. - fn listen_only(&mut self, event: impl Into>); + #[inline(always)] + fn listen_only(&mut self, event: impl Into>) { + self.listen_event(Some(BitFlags::ALL), Some(event.into())); + } /// Stop listening for `Event`s - fn unlisten(&mut self, event: impl Into>); + fn unlisten(&mut self, event: impl Into>) { + self.listen_event(Some(event.into()), None); + } /// Start listening all `Event`s #[inline(always)] diff --git a/src/prelude.rs b/src/prelude.rs index d3722cca..81689b34 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -76,10 +76,8 @@ pub use crate::serial::dma::SerialHandleIT as _stm32f4xx_hal_serial_dma_SerialHa pub use crate::serial::dma::SerialReadDMA as _stm32f4xx_hal_serial_dma_SerialReadDMA; pub use crate::serial::dma::SerialWriteDMA as _stm32f4xx_hal_serial_dma_SerialWriteDMA; pub use crate::serial::RxISR as _stm32f4xx_hal_serial_RxISR; -pub use crate::serial::RxListen as _stm32f4xx_hal_serial_RxListen; pub use crate::serial::SerialExt as _stm32f4xx_hal_serial_SerialExt; pub use crate::serial::TxISR as _stm32f4xx_hal_serial_TxISR; -pub use crate::serial::TxListen as _stm32f4xx_hal_serial_TxListen; pub use crate::spi::SpiExt as _stm32f4xx_hal_spi_SpiExt; pub use crate::syscfg::SysCfgExt as _stm32f4xx_hal_syscfg_SysCfgExt; pub use crate::time::U32Ext as _stm32f4xx_hal_time_U32Ext; diff --git a/src/serial.rs b/src/serial.rs index 4d8f4517..a8eab73f 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -24,7 +24,7 @@ mod hal_02; mod hal_1; mod uart_impls; -use uart_impls::RegisterBlockImpl; +use uart_impls::RBExt; use crate::gpio::{self, PushPull}; @@ -77,6 +77,32 @@ pub enum Event { ParityError = 1 << 8, } +/// UART interrupt events +#[enumflags2::bitflags] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[repr(u16)] +pub enum RxEvent { + /// IDLE interrupt enable + Idle = 1 << 4, + /// RXNE interrupt enable + RxNotEmpty = 1 << 5, + /// PE interrupt enable + ParityError = 1 << 8, +} + +/// UART interrupt events +#[enumflags2::bitflags] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[repr(u16)] +pub enum TxEvent { + /// Transmission complete interrupt enable + TransmissionComplete = 1 << 6, + /// TXE interrupt enable + TxEmpty = 1 << 7, +} + /// UART/USART status flags #[enumflags2::bitflags] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -128,7 +154,7 @@ pub use gpio::alt::SerialAsync as CommonPins; // Implemented by all USART/UART instances pub trait Instance: crate::Sealed - + crate::Ptr + + crate::Ptr + crate::Steal + core::ops::Deref + rcc::Enable @@ -161,37 +187,30 @@ pub trait TxISR { fn is_tx_empty(&self) -> bool; } -/// Trait for listening [`Rx`] interrupt events. -pub trait RxListen { - /// Start listening for an rx not empty interrupt event - /// - /// Note, you will also have to enable the corresponding interrupt - /// in the NVIC to start receiving events. - fn listen(&mut self); - - /// Stop listening for the rx not empty interrupt event - fn unlisten(&mut self); - - /// Start listening for a line idle interrupt event - /// - /// Note, you will also have to enable the corresponding interrupt - /// in the NVIC to start receiving events. - fn listen_idle(&mut self); +impl crate::Listen for Rx { + type Event = RxEvent; - /// Stop listening for the line idle interrupt event - fn unlisten_idle(&mut self); + #[inline(always)] + fn listen_event( + &mut self, + disable: Option>, + enable: Option>, + ) { + self.usart.listen_rx(disable, enable) + } } -/// Trait for listening [`Tx`] interrupt event. -pub trait TxListen { - /// Start listening for a tx empty interrupt event - /// - /// Note, you will also have to enable the corresponding interrupt - /// in the NVIC to start receiving events. - fn listen(&mut self); +impl crate::Listen for Tx { + type Event = TxEvent; - /// Stop listening for the tx empty interrupt event - fn unlisten(&mut self); + #[inline(always)] + fn listen_event( + &mut self, + disable: Option>, + enable: Option>, + ) { + self.usart.listen_tx(disable, enable) + } } /// Serial abstraction @@ -578,34 +597,6 @@ impl TxISR for Tx { } } -impl RxListen for Rx { - fn listen(&mut self) { - self.usart.listen_rxne() - } - - fn unlisten(&mut self) { - self.usart.unlisten_rxne() - } - - fn listen_idle(&mut self) { - self.usart.listen_idle() - } - - fn unlisten_idle(&mut self) { - self.usart.unlisten_idle() - } -} - -impl TxListen for Tx { - fn listen(&mut self) { - self.usart.listen_txe() - } - - fn unlisten(&mut self) { - self.usart.unlisten_txe() - } -} - impl crate::ClearFlags for Serial { type Flag = CFlag; @@ -628,20 +619,12 @@ impl crate::Listen for Serial { type Event = Event; #[inline(always)] - fn listen(&mut self, event: impl Into>) { - self.tx.usart.listen_event(None, Some(event.into())); - } - - #[inline(always)] - fn listen_only(&mut self, event: impl Into>) { - self.tx - .usart - .listen_event(Some(BitFlags::ALL), Some(event.into())); - } - - #[inline(always)] - fn unlisten(&mut self, event: impl Into>) { - self.tx.usart.listen_event(Some(event.into()), None); + fn listen_event( + &mut self, + disable: Option>, + enable: Option>, + ) { + self.tx.usart.listen_event(disable, enable) } } diff --git a/src/serial/dma.rs b/src/serial/dma.rs index 4d36c38b..52923e22 100644 --- a/src/serial/dma.rs +++ b/src/serial/dma.rs @@ -1,6 +1,6 @@ use core::{marker::PhantomData, mem::transmute}; -use super::{Instance, RegisterBlockImpl, Serial}; +use super::{Instance, RBExt, Serial}; use crate::dma::{ config::DmaConfig, traits::{Channel, DMASet, DmaFlagExt, PeriAddress, Stream, StreamISR}, diff --git a/src/serial/hal_02.rs b/src/serial/hal_02.rs index 2776ee1f..3df4fa17 100644 --- a/src/serial/hal_02.rs +++ b/src/serial/hal_02.rs @@ -1,6 +1,6 @@ mod nb { #[allow(unused)] - use super::super::RegisterBlockImpl; + use super::super::RBExt; use super::super::{Error, Instance, Rx, Serial, Tx}; use embedded_hal_02::serial::{Read, Write}; @@ -84,7 +84,7 @@ mod blocking { use core::ops::Deref; #[allow(unused)] - use super::super::RegisterBlockImpl; + use super::super::RBExt; use super::super::{Error, Instance, Serial, Tx}; use embedded_hal_02::blocking::serial::Write; diff --git a/src/serial/hal_1.rs b/src/serial/hal_1.rs index ae608075..38690840 100644 --- a/src/serial/hal_1.rs +++ b/src/serial/hal_1.rs @@ -1,6 +1,6 @@ mod nb { #[allow(unused)] - use super::super::RegisterBlockImpl; + use super::super::RBExt; use super::super::{Error, Instance, Rx, Serial, Tx}; use embedded_hal_nb::serial::{ErrorKind, Read, Write}; @@ -92,7 +92,7 @@ mod nb { mod io { #[allow(unused)] - use super::super::RegisterBlockImpl; + use super::super::RBExt; use super::super::{Error, Instance, Rx, Serial, Tx}; use embedded_io::Write; diff --git a/src/serial/uart_impls.rs b/src/serial/uart_impls.rs index e1eb6963..a7c88b46 100644 --- a/src/serial/uart_impls.rs +++ b/src/serial/uart_impls.rs @@ -1,9 +1,9 @@ use crate::pacext::uart::{Cr3W, SrR, UartRB}; -use super::{config, config::IrdaMode, CFlag, Error, Event, Flag}; +use super::{config, config::IrdaMode, CFlag, Error, Event, Flag, RxEvent, TxEvent}; use enumflags2::BitFlags; -pub trait RegisterBlockImpl: UartRB { +pub trait RBExt: UartRB { const IRDA: bool; fn configure_irda(&self, irda: IrdaMode, pclk_freq: u32); fn set_stopbits(&self, bits: config::StopBits); @@ -171,29 +171,34 @@ pub trait RegisterBlockImpl: UartRB { }); } - #[inline(always)] - fn listen_rxne(&self) { - self.listen_event(None, Some(Event::RxNotEmpty.into())) - } - #[inline(always)] - fn unlisten_rxne(&self) { - self.listen_event(Some(Event::RxNotEmpty.into()), None) - } - #[inline(always)] - fn listen_idle(&self) { - self.listen_event(None, Some(Event::Idle.into())) - } - #[inline(always)] - fn unlisten_idle(&self) { - self.listen_event(Some(Event::Idle.into()), None) - } - #[inline(always)] - fn listen_txe(&self) { - self.listen_event(None, Some(Event::TxEmpty.into())) + fn listen_rx(&self, disable: Option>, enable: Option>) { + self.cr1().modify(|r, w| unsafe { + w.bits({ + let mut bits = r.bits(); + if let Some(d) = disable { + bits &= !(d.bits()); + } + if let Some(e) = enable { + bits |= e.bits(); + } + bits + }) + }); } - #[inline(always)] - fn unlisten_txe(&self) { - self.listen_event(Some(Event::TxEmpty.into()), None) + + fn listen_tx(&self, disable: Option>, enable: Option>) { + self.cr1().modify(|r, w| unsafe { + w.bits({ + let mut bits = r.bits(); + if let Some(d) = disable { + bits &= !(d.bits()); + } + if let Some(e) = enable { + bits |= e.bits(); + } + bits + }) + }); } // PeriAddress @@ -221,7 +226,7 @@ pub trait RegisterBlockImpl: UartRB { } } -impl RegisterBlockImpl for crate::pac::usart1::RegisterBlock { +impl RBExt for crate::pac::usart1::RegisterBlock { const IRDA: bool = true; fn set_stopbits(&self, bits: config::StopBits) { use crate::pac::usart1::cr2::STOP; @@ -256,7 +261,7 @@ impl RegisterBlockImpl for crate::pac::usart1::RegisterBlock { } #[cfg(feature = "uart4")] -impl RegisterBlockImpl for crate::pac::uart4::RegisterBlock { +impl RBExt for crate::pac::uart4::RegisterBlock { const IRDA: bool = false; fn set_stopbits(&self, bits: config::StopBits) { use crate::pac::uart4::cr2::STOP; diff --git a/src/spi.rs b/src/spi.rs index 83d28f98..f9019e1e 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -875,16 +875,13 @@ impl Inner { impl crate::Listen for Inner { type Event = Event; - fn listen(&mut self, event: impl Into>) { - self.listen_event(None, Some(event.into())); - } - - fn listen_only(&mut self, event: impl Into>) { - self.listen_event(Some(BitFlags::ALL), Some(event.into())); - } - - fn unlisten(&mut self, event: impl Into>) { - self.listen_event(Some(event.into()), None); + #[inline(always)] + fn listen_event( + &mut self, + disable: Option>, + enable: Option>, + ) { + self.listen_event(disable, enable) } } diff --git a/src/timer.rs b/src/timer.rs index 752286e0..72618346 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -992,29 +992,27 @@ pub(crate) const fn compute_arr_presc(freq: u32, clock: u32) -> (u16, u32) { impl crate::Listen for Timer { type Event = Event; - fn listen(&mut self, event: impl Into>) { - self.tim.listen_event(None, Some(event.into())); - } - fn listen_only(&mut self, event: impl Into>) { - self.tim - .listen_event(Some(BitFlags::ALL), Some(event.into())); - } - fn unlisten(&mut self, event: impl Into>) { - self.tim.listen_event(Some(event.into()), None); + + #[inline(always)] + fn listen_event( + &mut self, + disable: Option>, + enable: Option>, + ) { + self.tim.listen_event(disable, enable) } } impl crate::Listen for FTimer { type Event = Event; - fn listen(&mut self, event: impl Into>) { - self.tim.listen_event(None, Some(event.into())); - } - fn listen_only(&mut self, event: impl Into>) { - self.tim - .listen_event(Some(BitFlags::ALL), Some(event.into())); - } - fn unlisten(&mut self, event: impl Into>) { - self.tim.listen_event(Some(event.into()), None); + + #[inline(always)] + fn listen_event( + &mut self, + disable: Option>, + enable: Option>, + ) { + self.tim.listen_event(disable, enable) } }