Skip to content

Commit 1c285b1

Browse files
committed
Support pin type erasure in Serial
There are many possible pin combinations for a Serial peripheral. Many support at least one alternative pin group to be used, and in addition to that, each pin can also be configured differently. For instance, instead of the common Output<PushPull> with an Input<Floating>, one could also use Output<OpenDrain> and Input<PullUp>, e.g. when interfacing with a 1-Wire bus. This pin information is already lost when splitting the Serial object into Rx/Tx. In order to allow a reunification into a Serial object which represents ownership of both Tx and Rx, we need a Serial variant which has that pin information erased.
1 parent ecd81e0 commit 1c285b1

File tree

1 file changed

+104
-8
lines changed

1 file changed

+104
-8
lines changed

src/serial.rs

Lines changed: 104 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,12 @@ use crate::pac::usart1 as uart_base;
185185

186186
/// Serial abstraction
187187
pub struct Serial<USART, PINS> {
188-
usart: USART,
189188
pins: PINS,
189+
inner: ErasedSerial<USART>,
190+
}
191+
192+
pub struct ErasedSerial<USART> {
193+
usart: USART,
190194
tx: Tx<USART>,
191195
rx: Rx<USART>,
192196
}
@@ -224,7 +228,7 @@ impl<USART> Tx<USART> {
224228
}
225229
}
226230

227-
impl<USART, PINS> Serial<USART, PINS>
231+
impl<USART> ErasedSerial<USART>
228232
where
229233
USART: Instance,
230234
{
@@ -348,15 +352,81 @@ where
348352
}
349353
}
350354

355+
/// Separates the serial struct into separate channel objects for sending (Tx) and
356+
/// receiving (Rx)
357+
pub fn split(self) -> (Tx<USART>, Rx<USART>) {
358+
(self.tx, self.rx)
359+
}
360+
}
361+
362+
impl<USART, PINS> Serial<USART, PINS>
363+
where
364+
USART: Instance,
365+
{
351366
/// Returns ownership of the borrowed register handles
352367
pub fn release(self) -> (USART, PINS) {
353-
(self.usart, self.pins)
368+
(self.inner.usart, self.pins)
369+
}
370+
371+
/// Erase the pins used for the Serial from the type
372+
pub fn erase(self) -> ErasedSerial<USART> {
373+
self.inner
354374
}
355375

356376
/// Separates the serial struct into separate channel objects for sending (Tx) and
357377
/// receiving (Rx)
378+
#[inline(always)]
358379
pub fn split(self) -> (Tx<USART>, Rx<USART>) {
359-
(self.tx, self.rx)
380+
self.inner.split()
381+
}
382+
383+
/// Reconfigure the USART instance.
384+
///
385+
/// If a transmission is currently in progress, this returns
386+
/// [`nb::Error::WouldBlock`].
387+
#[inline(always)]
388+
pub fn reconfigure(&mut self, config: impl Into<Config>, clocks: Clocks) -> nb::Result<(), ()> {
389+
self.inner.reconfigure(config, clocks)
390+
}
391+
392+
/// Starts listening to the USART by enabling the _Received data
393+
/// ready to be read (RXNE)_ interrupt and _Transmit data
394+
/// register empty (TXE)_ interrupt
395+
#[inline(always)]
396+
pub fn listen(&mut self, event: Event) {
397+
self.inner.listen(event)
398+
}
399+
400+
/// Stops listening to the USART by disabling the _Received data
401+
/// ready to be read (RXNE)_ interrupt and _Transmit data
402+
/// register empty (TXE)_ interrupt
403+
#[inline(always)]
404+
pub fn unlisten(&mut self, event: Event) {
405+
self.inner.unlisten(event)
406+
}
407+
408+
/// Returns true if the line idle status is set
409+
#[inline(always)]
410+
pub fn is_idle(&self) -> bool {
411+
self.inner.is_idle()
412+
}
413+
414+
/// Returns true if the tx register is empty (and can accept data)
415+
#[inline(always)]
416+
pub fn is_tx_empty(&self) -> bool {
417+
self.inner.is_tx_empty()
418+
}
419+
420+
/// Returns true if the rx register is not empty (and can be read)
421+
#[inline(always)]
422+
pub fn is_rx_not_empty(&self) -> bool {
423+
self.inner.is_rx_not_empty()
424+
}
425+
426+
/// Clear idle line interrupt flag
427+
#[inline(always)]
428+
pub fn clear_idle_interrupt(&self) {
429+
self.inner.clear_idle_interrupt()
360430
}
361431
}
362432

@@ -406,12 +476,12 @@ macro_rules! hal {
406476
PINS: Pins<$USARTX>,
407477
{
408478
#[allow(unused_unsafe)]
409-
Serial { usart, pins, tx: Tx::new(), rx: Rx::new() }.init(config.into(), clocks, || {
479+
Serial { pins, inner: ErasedSerial{ usart, tx: Tx::new(), rx: Rx::new() }.init(config.into(), clocks, || {
410480
mapr.modify_mapr(|_, w| unsafe {
411481
#[allow(clippy::redundant_closure_call)]
412482
w.$usartX_remap().$bit(($closure)(PINS::REMAP))
413483
})
414-
})
484+
}) }
415485
}
416486
}
417487

@@ -557,7 +627,7 @@ where
557627
}
558628
}
559629

560-
impl<USART, PINS> crate::hal::serial::Read<u8> for Serial<USART, PINS>
630+
impl<USART> crate::hal::serial::Read<u8> for ErasedSerial<USART>
561631
where
562632
USART: Instance,
563633
{
@@ -568,7 +638,7 @@ where
568638
}
569639
}
570640

571-
impl<USART, PINS> crate::hal::serial::Write<u8> for Serial<USART, PINS>
641+
impl<USART> crate::hal::serial::Write<u8> for ErasedSerial<USART>
572642
where
573643
USART: Instance,
574644
{
@@ -583,6 +653,32 @@ where
583653
}
584654
}
585655

656+
impl<USART, PINS> crate::hal::serial::Read<u8> for Serial<USART, PINS>
657+
where
658+
USART: Instance,
659+
{
660+
type Error = Error;
661+
662+
fn read(&mut self) -> nb::Result<u8, Error> {
663+
self.inner.rx.read()
664+
}
665+
}
666+
667+
impl<USART, PINS> crate::hal::serial::Write<u8> for Serial<USART, PINS>
668+
where
669+
USART: Instance,
670+
{
671+
type Error = Infallible;
672+
673+
fn flush(&mut self) -> nb::Result<(), Self::Error> {
674+
self.inner.tx.flush()
675+
}
676+
677+
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
678+
self.inner.tx.write(byte)
679+
}
680+
}
681+
586682
impl<USART> core::fmt::Write for Tx<USART>
587683
where
588684
Tx<USART>: embedded_hal::serial::Write<u8>,

0 commit comments

Comments
 (0)