Skip to content

Commit ead8e7b

Browse files
Add APIs for querying and clearing RX errors
1 parent dc4d0cd commit ead8e7b

File tree

1 file changed

+58
-18
lines changed

1 file changed

+58
-18
lines changed

src/serial.rs

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,19 @@ macro_rules! usart {
337337
}
338338
}
339339

340+
/// Checks for reception errors that may have occurred.
341+
///
342+
/// Note that multiple errors can be signaled at the same time. In that case,
343+
/// calling this function repeatedly will return the remaining errors.
344+
pub fn check_errors(&mut self) -> Result<(), Error> {
345+
self.rx.check_errors()
346+
}
347+
348+
/// Clears any signaled errors without returning them.
349+
pub fn clear_errors(&mut self) {
350+
self.rx.clear_errors()
351+
}
352+
340353
pub fn split(self) -> (Tx<$USARTX>, Rx<$USARTX>) {
341354
(self.tx, self.rx)
342355
}
@@ -366,7 +379,49 @@ macro_rules! usart {
366379
}
367380
}
368381

369-
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
382+
impl Rx<$USARTX> {
383+
/// Checks for reception errors that may have occurred.
384+
///
385+
/// Note that multiple errors can be signaled at the same time. In that case,
386+
/// calling this function repeatedly will return the remaining errors.
387+
pub fn check_errors(&mut self) -> Result<(), Error> {
388+
let isr = unsafe { (*$USARTX::ptr()).isr.read() };
389+
let icr = unsafe { &(*$USARTX::ptr()).icr };
390+
391+
// We don't want to drop any errors, so check each error bit in sequence. If
392+
// any bit is set, clear it and return its error.
393+
if isr.pe().bit_is_set() {
394+
icr.write(|w| {w.pecf().set_bit()});
395+
return Err(Error::Parity.into());
396+
} else if isr.fe().bit_is_set() {
397+
icr.write(|w| {w.fecf().set_bit()});
398+
return Err(Error::Framing.into());
399+
} else if isr.nf().bit_is_set() {
400+
icr.write(|w| {w.ncf().set_bit()});
401+
return Err(Error::Noise.into());
402+
} else if isr.ore().bit_is_set() {
403+
icr.write(|w| {w.orecf().set_bit()});
404+
return Err(Error::Overrun.into());
405+
}
406+
407+
Ok(())
408+
}
409+
410+
/// Clears any signaled errors without returning them.
411+
pub fn clear_errors(&mut self) {
412+
let icr = unsafe { &(*$USARTX::ptr()).icr };
413+
414+
icr.write(|w| w
415+
.pecf().set_bit()
416+
.fecf().set_bit()
417+
.ncf().set_bit()
418+
.orecf().set_bit()
419+
);
420+
}
421+
}
422+
423+
/// DMA operations.
424+
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
370425
impl Rx<$USARTX> {
371426
pub fn read_all<Buffer, Channel>(self,
372427
dma: &mut dma::Handle,
@@ -423,25 +478,10 @@ macro_rules! usart {
423478
type Error = Error;
424479

425480
fn read(&mut self) -> nb::Result<u8, Error> {
481+
self.check_errors()?;
482+
426483
// NOTE(unsafe) atomic read with no side effects
427484
let isr = unsafe { (*$USARTX::ptr()).isr.read() };
428-
let icr = unsafe { &(*$USARTX::ptr()).icr };
429-
430-
// Check for errors. We don't want to drop errors, so check each error bit in
431-
// sequence. If any bit is set, clear it and return its error.
432-
if isr.pe().bit_is_set() {
433-
icr.write(|w| {w.pecf().set_bit()});
434-
return Err(Error::Parity.into());
435-
} else if isr.fe().bit_is_set() {
436-
icr.write(|w| {w.fecf().set_bit()});
437-
return Err(Error::Framing.into());
438-
} else if isr.nf().bit_is_set() {
439-
icr.write(|w| {w.ncf().set_bit()});
440-
return Err(Error::Noise.into());
441-
} else if isr.ore().bit_is_set() {
442-
icr.write(|w| {w.orecf().set_bit()});
443-
return Err(Error::Overrun.into());
444-
}
445485

446486
// Check if a byte is available
447487
if isr.rxne().bit_is_set() {

0 commit comments

Comments
 (0)