diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dff0247..2f3eebac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Use `stm32f4-staging` until `stm32f4` is released [#706] - RTIC2 monotonics fix: CC1 instead of CC3 - Allow different lengths of buffers in hal_1 SpiBus impl [#566] + - `steal` UART peripheral on `Rx::new` [#566]: https://github.com/stm32-rs/stm32f4xx-hal/pull/566 [#706]: https://github.com/stm32-rs/stm32f4xx-hal/pull/706 diff --git a/src/serial.rs b/src/serial.rs index 77e4f609..3af6dd1e 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -183,7 +183,8 @@ pub struct Serial { /// Serial receiver containing RX pin pub struct Rx { - _word: PhantomData<(USART, WORD)>, + _word: PhantomData, + usart: USART, pin: USART::Rx, } @@ -276,8 +277,8 @@ macro_rules! halUsart { }); } - fn peri_address() -> u32 { - unsafe { (*(<$USART>::ptr() as *const Self::RegisterBlock)).peri_address() } + unsafe fn steal() -> Self { + Self::steal() } } }; @@ -293,13 +294,13 @@ halUsart! { pac::USART3, Serial3, Rx3, Tx3 } impl Rx { pub(crate) fn with_u16_data(self) -> Rx { - Rx::new(self.pin) + Rx::new(self.usart, self.pin) } } impl Rx { pub(crate) fn with_u8_data(self) -> Rx { - Rx::new(self.pin) + Rx::new(self.usart, self.pin) } } @@ -316,9 +317,10 @@ impl Tx { } impl Rx { - pub(crate) fn new(pin: UART::Rx) -> Self { + pub(crate) fn new(usart: UART, pin: UART::Rx) -> Self { Self { _word: PhantomData, + usart, pin, } } diff --git a/src/serial/dma.rs b/src/serial/dma.rs index 6c723cd6..4d36c38b 100644 --- a/src/serial/dma.rs +++ b/src/serial/dma.rs @@ -1,4 +1,4 @@ -use core::{marker::PhantomData, mem::transmute, ops::Deref}; +use core::{marker::PhantomData, mem::transmute}; use super::{Instance, RegisterBlockImpl, Serial}; use crate::dma::{ @@ -67,12 +67,7 @@ pub trait SerialHandleIT { fn handle_error_interrupt(&mut self); } -impl Serial -where - Serial_: Instance, - Serial_: Deref::RegisterBlock>, - ::RegisterBlock: RegisterBlockImpl, -{ +impl Serial { /// Converts blocking [Serial] to non-blocking [SerialDma] that use `tx_stream` and `rx_stream` to send/receive data pub fn use_dma( self, @@ -152,10 +147,7 @@ where /// /// The struct can be also used to send/receive bytes in blocking mode with methods: /// [`write`](Self::write()), [`read`](Self::read()), [`write_read`](Self::write_read()). -pub struct SerialDma -where - Serial_: Instance, -{ +pub struct SerialDma { hal_serial: Serial, callback: Option, tx: TX_TRANSFER, @@ -338,11 +330,8 @@ where } /// Common implementation -impl SerialDma +impl SerialDma where - Serial_: Instance, - Serial_: Deref::RegisterBlock>, - ::RegisterBlock: RegisterBlockImpl, TX_TRANSFER: DMATransfer<&'static [u8]>, RX_TRANSFER: DMATransfer<&'static mut [u8]>, { @@ -386,13 +375,9 @@ where } } -impl SerialHandleIT +impl SerialHandleIT for SerialDma, NoDMA> where - Serial_: Instance, - Serial_: Deref::RegisterBlock>, - ::RegisterBlock: RegisterBlockImpl, - TX_STREAM: Stream, ChannelX: Channel, Tx: DMASet, @@ -428,13 +413,9 @@ where } } -impl SerialHandleIT +impl SerialHandleIT for SerialDma> where - Serial_: Instance, - Serial_: Deref::RegisterBlock>, - ::RegisterBlock: RegisterBlockImpl, - RX_STREAM: Stream, ChannelX: Channel, Rx: DMASet, @@ -471,13 +452,9 @@ where } /// Only for both TX and RX DMA -impl SerialHandleIT +impl SerialHandleIT for SerialDma, RxDMA> where - Serial_: Instance, - Serial_: Deref::RegisterBlock>, - ::RegisterBlock: RegisterBlockImpl, - TX_STREAM: Stream, ChannelX: Channel, Tx: DMASet, @@ -550,13 +527,9 @@ where } // Write DMA implementations for TX only and TX/RX Serial DMA -impl SerialWriteDMA +impl SerialWriteDMA for SerialDma, RX_TRANSFER> where - Serial_: Instance, - Serial_: Deref::RegisterBlock>, - ::RegisterBlock: RegisterBlockImpl, - TX_STREAM: Stream, ChannelX: Channel, Tx: DMASet, @@ -581,13 +554,9 @@ where } // Read DMA implementations for RX only and TX/RX Serial DMA -impl SerialReadDMA +impl SerialReadDMA for SerialDma> where - Serial_: Instance, - Serial_: Deref::RegisterBlock>, - ::RegisterBlock: RegisterBlockImpl, - RX_STREAM: Stream, ChannelX: Channel, Rx: DMASet, diff --git a/src/serial/hal_02.rs b/src/serial/hal_02.rs index d4721df4..bdefabfa 100644 --- a/src/serial/hal_02.rs +++ b/src/serial/hal_02.rs @@ -1,5 +1,4 @@ mod nb { - use core::ops::Deref; use super::super::{Error, Instance, RegisterBlockImpl, Rx, Serial, Tx}; use embedded_hal_02::serial::{Read, Write}; @@ -19,7 +18,7 @@ mod nb { type Error = Error; fn read(&mut self) -> nb::Result { - unsafe { (*USART::ptr()).read_u8() } + self.usart.read_u8() } } @@ -32,7 +31,7 @@ mod nb { type Error = Error; fn read(&mut self) -> nb::Result { - unsafe { (*USART::ptr()).read_u16() } + self.usart.read_u16() } } @@ -51,10 +50,7 @@ mod nb { } } - impl Write for Tx - where - USART: Deref::RegisterBlock>, - { + impl Write for Tx { type Error = Error; fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { @@ -70,10 +66,7 @@ mod nb { /// If the UART/USART was configured with `WordLength::DataBits9`, the 9 least significant bits will /// be transmitted and the other 7 bits will be ignored. Otherwise, the 8 least significant bits /// will be transmitted and the other 8 bits will be ignored. - impl Write for Tx - where - USART: Deref::RegisterBlock>, - { + impl Write for Tx { type Error = Error; fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { @@ -92,10 +85,7 @@ mod blocking { use super::super::{Error, Instance, RegisterBlockImpl, Serial, Tx}; use embedded_hal_02::blocking::serial::Write; - impl Write for Tx - where - USART: Deref::RegisterBlock>, - { + impl Write for Tx { type Error = Error; fn bwrite_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { diff --git a/src/serial/hal_1.rs b/src/serial/hal_1.rs index 145d8444..b928ea12 100644 --- a/src/serial/hal_1.rs +++ b/src/serial/hal_1.rs @@ -1,6 +1,4 @@ mod nb { - use core::ops::Deref; - use super::super::{Error, Instance, RegisterBlockImpl, Rx, Serial, Tx}; use embedded_hal_nb::serial::{ErrorKind, Read, Write}; @@ -37,7 +35,7 @@ mod nb { impl Read for Rx { fn read(&mut self) -> nb::Result { - unsafe { (*USART::ptr()).read_u8() } + self.usart.read_u8() } } @@ -48,7 +46,7 @@ mod nb { /// 8 received data bits and all other bits set to zero. impl Read for Rx { fn read(&mut self) -> nb::Result { - unsafe { (*USART::ptr()).read_u16() } + self.usart.read_u16() } } @@ -65,10 +63,7 @@ mod nb { } } - impl Write for Tx - where - USART: Deref::RegisterBlock>, - { + impl Write for Tx { fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { self.usart.write_u8(word) } @@ -82,10 +77,7 @@ mod nb { /// If the UART/USART was configured with `WordLength::DataBits9`, the 9 least significant bits will /// be transmitted and the other 7 bits will be ignored. Otherwise, the 8 least significant bits /// will be transmitted and the other 8 bits will be ignored. - impl Write for Tx - where - USART: Deref::RegisterBlock>, - { + impl Write for Tx { fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { self.usart.write_u16(word) } diff --git a/src/serial/uart_impls.rs b/src/serial/uart_impls.rs index 16979c69..30ffaaa1 100644 --- a/src/serial/uart_impls.rs +++ b/src/serial/uart_impls.rs @@ -1,4 +1,4 @@ -use core::{fmt, ops::Deref}; +use core::fmt; use enumflags2::BitFlags; use nb::block; @@ -22,7 +22,14 @@ impl crate::Sealed for RegisterBlockUart {} impl crate::Sealed for RegisterBlockUsart {} // Implemented by all USART/UART instances -pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset + rcc::BusClock + CommonPins { +pub trait Instance: + crate::Sealed + + rcc::Enable + + rcc::Reset + + rcc::BusClock + + CommonPins + + core::ops::Deref +{ type RegisterBlock: RegisterBlockImpl; #[doc(hidden)] @@ -30,7 +37,12 @@ pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset + rcc::BusClock + C #[doc(hidden)] fn set_stopbits(&self, bits: config::StopBits); #[doc(hidden)] - fn peri_address() -> u32; + #[inline(always)] + fn peri_address() -> u32 { + unsafe { &*Self::ptr() }.peri_address() + } + #[doc(hidden)] + unsafe fn steal() -> Self; } pub trait RegisterBlockImpl: crate::Sealed { @@ -336,32 +348,28 @@ where { return Err(config::InvalidConfig); }; - let register_block = unsafe { &*UART::ptr() }; - register_block.brr().write(|w| unsafe { w.bits(div) }); + uart.brr().write(|w| unsafe { w.bits(div) }); // Reset other registers to disable advanced USART features - register_block.cr2().reset(); - register_block.cr3().reset(); // IrDA configuration - see STM32F411xC/E (RM0383) sections: - // 19.3.12 "IrDA SIR ENDEC block" - // 19.6.7 "Guard time and prescaler register (USART_GTPR)" + uart.cr2().reset(); + uart.cr3().reset(); // IrDA configuration - see STM32F411xC/E (RM0383) sections: + // 19.3.12 "IrDA SIR ENDEC block" + // 19.6.7 "Guard time and prescaler register (USART_GTPR)" if config.irda != IrdaMode::None && config.stopbits != StopBits::STOP1 { return Err(config::InvalidConfig); } match config.irda { IrdaMode::Normal => unsafe { - register_block.gtpr().reset(); - register_block.cr3().write(|w| w.iren().enabled()); - register_block.gtpr().write(|w| w.psc().bits(1u8)) + uart.gtpr().reset(); + uart.cr3().write(|w| w.iren().enabled()); + uart.gtpr().write(|w| w.psc().bits(1u8)) }, IrdaMode::LowPower => unsafe { - register_block.gtpr().reset(); - register_block - .cr3() - .write(|w| w.iren().enabled().irlp().low_power()); + uart.gtpr().reset(); + uart.cr3().write(|w| w.iren().enabled().irlp().low_power()); // FIXME - register_block - .gtpr() + uart.gtpr() .write(|w| w.psc().bits((1843200u32 / pclk_freq) as u8)) }, IrdaMode::None => {} @@ -370,7 +378,7 @@ where { // Enable transmission and receiving // and configure frame - register_block.cr1().write(|w| { + uart.cr1().write(|w| { w.ue().set_bit(); w.over8().bit(over8); w.te().set_bit(); @@ -381,17 +389,15 @@ where { }); match config.dma { - DmaConfig::Tx => register_block.cr3().write(|w| w.dmat().enabled()), - DmaConfig::Rx => register_block.cr3().write(|w| w.dmar().enabled()), - DmaConfig::TxRx => register_block - .cr3() - .write(|w| w.dmar().enabled().dmat().enabled()), + DmaConfig::Tx => uart.cr3().write(|w| w.dmat().enabled()), + DmaConfig::Rx => uart.cr3().write(|w| w.dmar().enabled()), + DmaConfig::TxRx => uart.cr3().write(|w| w.dmar().enabled().dmat().enabled()), DmaConfig::None => {} } let serial = Serial { tx: Tx::new(uart, pins.0.into()), - rx: Rx::new(pins.1.into()), + rx: Rx::new(unsafe { UART::steal() }, pins.1.into()), }; serial.tx.usart.set_stopbits(config.stopbits); Ok(serial) @@ -470,17 +476,16 @@ where { return Err(config::InvalidConfig); }; - let register_block = unsafe { &*UART::ptr() }; - register_block.brr().write(|w| unsafe { w.bits(div) }); + uart.brr().write(|w| unsafe { w.bits(div) }); // Reset other registers to disable advanced USART features - register_block.cr2().reset(); - register_block.cr3().reset(); + uart.cr2().reset(); + uart.cr3().reset(); // Enable transmission and receiving // and configure frame - register_block.cr1().write(|w| { + uart.cr1().write(|w| { w.ue().set_bit(); w.over8().bit(over8); w.te().set_bit(); @@ -491,17 +496,15 @@ where { }); match config.dma { - DmaConfig::Tx => register_block.cr3().write(|w| w.dmat().enabled()), - DmaConfig::Rx => register_block.cr3().write(|w| w.dmar().enabled()), - DmaConfig::TxRx => register_block - .cr3() - .write(|w| w.dmar().enabled().dmat().enabled()), + DmaConfig::Tx => uart.cr3().write(|w| w.dmat().enabled()), + DmaConfig::Rx => uart.cr3().write(|w| w.dmar().enabled()), + DmaConfig::TxRx => uart.cr3().write(|w| w.dmar().enabled().dmat().enabled()), DmaConfig::None => {} } let serial = Serial { tx: Tx::new(uart, pins.0.into()), - rx: Rx::new(pins.1.into()), + rx: Rx::new(unsafe { UART::steal() }, pins.1.into()), }; serial.tx.usart.set_stopbits(config.stopbits); Ok(serial) @@ -530,18 +533,16 @@ where impl RxISR for Rx { fn is_idle(&self) -> bool { - unsafe { (*UART::ptr()).is_idle() } + self.usart.is_idle() } fn is_rx_not_empty(&self) -> bool { - unsafe { (*UART::ptr()).is_rx_not_empty() } + self.usart.is_rx_not_empty() } /// This clears `Idle`, `Overrun`, `Noise`, `FrameError` and `ParityError` flags fn clear_idle_interrupt(&self) { - unsafe { - (*UART::ptr()).clear_idle_interrupt(); - } + self.usart.clear_idle_interrupt(); } } @@ -554,10 +555,7 @@ where } } -impl TxISR for Tx -where - UART: Deref::RegisterBlock>, -{ +impl TxISR for Tx { fn is_tx_empty(&self) -> bool { self.usart.is_tx_empty() } @@ -565,26 +563,23 @@ where impl RxListen for Rx { fn listen(&mut self) { - unsafe { (*UART::ptr()).listen_rxne() } + self.usart.listen_rxne() } fn unlisten(&mut self) { - unsafe { (*UART::ptr()).unlisten_rxne() } + self.usart.unlisten_rxne() } fn listen_idle(&mut self) { - unsafe { (*UART::ptr()).listen_idle() } + self.usart.listen_idle() } fn unlisten_idle(&mut self) { - unsafe { (*UART::ptr()).unlisten_idle() } + self.usart.unlisten_idle() } } -impl TxListen for Tx -where - UART: Deref::RegisterBlock>, -{ +impl TxListen for Tx { fn listen(&mut self) { self.usart.listen_txe() } @@ -594,10 +589,7 @@ where } } -impl crate::ClearFlags for Serial -where - UART: Deref::RegisterBlock>, -{ +impl crate::ClearFlags for Serial { type Flag = CFlag; #[inline(always)] @@ -606,10 +598,7 @@ where } } -impl crate::ReadFlags for Serial -where - UART: Deref::RegisterBlock>, -{ +impl crate::ReadFlags for Serial { type Flag = Flag; #[inline(always)] @@ -618,10 +607,7 @@ where } } -impl crate::Listen for Serial -where - UART: Deref::RegisterBlock>, -{ +impl crate::Listen for Serial { type Event = Event; #[inline(always)] @@ -651,10 +637,7 @@ where } } -impl fmt::Write for Tx -where - UART: Deref::RegisterBlock>, -{ +impl fmt::Write for Tx { fn write_str(&mut self, s: &str) -> fmt::Result { s.bytes() .try_for_each(|c| block!(self.usart.write_u8(c))) @@ -726,7 +709,7 @@ impl Serial { unsafe impl PeriAddress for Rx { #[inline(always)] fn address(&self) -> u32 { - unsafe { (*UART::ptr()).peri_address() } + self.usart.peri_address() } type MemSize = u8; @@ -739,10 +722,7 @@ where { } -unsafe impl PeriAddress for Tx -where - UART: Deref::RegisterBlock>, -{ +unsafe impl PeriAddress for Tx { #[inline(always)] fn address(&self) -> u32 { self.usart.peri_address() diff --git a/src/uart.rs b/src/uart.rs index 392877ed..ad6b6b96 100644 --- a/src/uart.rs +++ b/src/uart.rs @@ -52,8 +52,8 @@ macro_rules! halUart { }); } - fn peri_address() -> u32 { - unsafe { (*Self::ptr()).peri_address() } + unsafe fn steal() -> Self { + Self::steal() } } };