Skip to content

Commit b9ec88d

Browse files
Allow Serial reconfiguration by references to the Tx and Rx parts
1 parent 272b1bd commit b9ec88d

File tree

3 files changed

+73
-37
lines changed

3 files changed

+73
-37
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1818
### Added
1919

2020
- Allow access to the `Tx` and `Rx` parts of the `Serial` without the need for splitting.
21+
- Allow `Serial` reconfiguration by references to the `Tx` and `Rx` parts.
2122

2223
## [v0.9.0] - 2022-03-02
2324

examples/serial_reconfigure.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use cortex_m_rt::entry;
1717
use stm32f1xx_hal::{
1818
pac,
1919
prelude::*,
20-
serial::{Config, Serial},
20+
serial::{self, Config, Serial},
2121
};
2222

2323
#[entry]
@@ -92,5 +92,15 @@ fn main() -> ! {
9292
assert_eq!(received, sent);
9393
asm::bkpt();
9494

95+
// You can reconfigure the serial port after split.
96+
let (mut tx, mut rx) = serial.split();
97+
block!(serial::reconfigure(
98+
&mut tx,
99+
&mut rx,
100+
Config::default().baudrate(9600.bps()),
101+
&clocks
102+
))
103+
.unwrap();
104+
95105
loop {}
96106
}

src/serial.rs

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ where
308308
USART::reset(rcc);
309309

310310
PINS::remap(mapr);
311-
Self::apply_config(&usart, config.into(), clocks);
311+
apply_config::<USART>(config.into(), clocks);
312312

313313
// UE: enable USART
314314
// RE: enable receiver
@@ -324,38 +324,45 @@ where
324324
rx: Rx::new(),
325325
}
326326
}
327+
}
327328

328-
fn apply_config(usart: &USART, config: Config, clocks: &Clocks) {
329-
// Configure baud rate
330-
let brr = USART::clock(clocks).raw() / config.baudrate.0;
331-
assert!(brr >= 16, "impossible baud rate");
332-
usart.brr.write(|w| unsafe { w.bits(brr) });
329+
fn apply_config<USART: Instance>(config: Config, clocks: &Clocks) {
330+
let usart = unsafe { &*USART::ptr() };
333331

334-
// Configure word
335-
let (parity_is_used, parity_is_odd) = match config.parity {
336-
Parity::ParityNone => (false, false),
337-
Parity::ParityEven => (true, false),
338-
Parity::ParityOdd => (true, true),
339-
};
340-
usart.cr1.modify(|_r, w| {
341-
w.m().bit(match config.wordlength {
342-
WordLength::Bits8 => false,
343-
WordLength::Bits9 => true,
344-
});
345-
w.ps().bit(parity_is_odd);
346-
w.pce().bit(parity_is_used)
347-
});
332+
// Configure baud rate
333+
let brr = USART::clock(clocks).raw() / config.baudrate.0;
334+
assert!(brr >= 16, "impossible baud rate");
335+
usart.brr.write(|w| unsafe { w.bits(brr) });
348336

349-
// Configure stop bits
350-
let stop_bits = match config.stopbits {
351-
StopBits::STOP1 => 0b00,
352-
StopBits::STOP0P5 => 0b01,
353-
StopBits::STOP2 => 0b10,
354-
StopBits::STOP1P5 => 0b11,
355-
};
356-
usart.cr2.modify(|_r, w| w.stop().bits(stop_bits));
357-
}
337+
// Configure word
338+
let (parity_is_used, parity_is_odd) = match config.parity {
339+
Parity::ParityNone => (false, false),
340+
Parity::ParityEven => (true, false),
341+
Parity::ParityOdd => (true, true),
342+
};
343+
usart.cr1.modify(|_r, w| {
344+
w.m().bit(match config.wordlength {
345+
WordLength::Bits8 => false,
346+
WordLength::Bits9 => true,
347+
});
348+
w.ps().bit(parity_is_odd);
349+
w.pce().bit(parity_is_used)
350+
});
351+
352+
// Configure stop bits
353+
let stop_bits = match config.stopbits {
354+
StopBits::STOP1 => 0b00,
355+
StopBits::STOP0P5 => 0b01,
356+
StopBits::STOP2 => 0b10,
357+
StopBits::STOP1P5 => 0b11,
358+
};
359+
usart.cr2.modify(|_r, w| w.stop().bits(stop_bits));
360+
}
358361

362+
impl<USART, PINS> Serial<USART, PINS>
363+
where
364+
USART: Instance,
365+
{
359366
/// Reconfigure the USART instance.
360367
///
361368
/// If a transmission is currently in progress, this returns
@@ -365,15 +372,33 @@ where
365372
config: impl Into<Config>,
366373
clocks: &Clocks,
367374
) -> nb::Result<(), Infallible> {
368-
// if we're currently busy transmitting, we have to wait until that is
369-
// over -- regarding reception, we assume that the caller -- with
370-
// exclusive access to the Serial instance due to &mut self -- knows
371-
// what they're doing.
372-
self.tx.flush()?;
373-
Self::apply_config(&self.usart, config.into(), clocks);
374-
Ok(())
375+
reconfigure(&mut self.tx, &mut self.rx, config, clocks)
375376
}
377+
}
376378

379+
/// Reconfigure the USART instance.
380+
///
381+
/// If a transmission is currently in progress, this returns
382+
/// [`nb::Error::WouldBlock`].
383+
pub fn reconfigure<USART: Instance>(
384+
tx: &mut Tx<USART>,
385+
#[allow(unused_variables)] rx: &mut Rx<USART>,
386+
config: impl Into<Config>,
387+
clocks: &Clocks,
388+
) -> nb::Result<(), Infallible> {
389+
// if we're currently busy transmitting, we have to wait until that is
390+
// over -- regarding reception, we assume that the caller -- with
391+
// exclusive access to the Serial instance due to &mut self -- knows
392+
// what they're doing.
393+
tx.flush()?;
394+
apply_config::<USART>(config.into(), clocks);
395+
Ok(())
396+
}
397+
398+
impl<USART, PINS> Serial<USART, PINS>
399+
where
400+
USART: Instance,
401+
{
377402
/// Starts listening to the USART by enabling the _Received data
378403
/// ready to be read (RXNE)_ interrupt and _Transmit data
379404
/// register empty (TXE)_ interrupt

0 commit comments

Comments
 (0)