@@ -363,6 +363,16 @@ macro_rules! hal {
363363 }
364364 }
365365
366+ /// Check for, and return, any errors
367+ ///
368+ /// See [`Rx::check_for_error`].
369+ pub fn check_for_error( ) -> Result <( ) , Error > {
370+ let mut rx: Rx <pac:: $USARTX> = Rx {
371+ _usart: PhantomData ,
372+ } ;
373+ rx. check_for_error( )
374+ }
375+
366376 /// Stops listening for an interrupt event
367377 pub fn unlisten( & mut self , event: Event ) {
368378 match event {
@@ -417,32 +427,19 @@ macro_rules! hal {
417427 type Error = Error ;
418428
419429 fn read( & mut self ) -> nb:: Result <u8 , Error > {
430+ self . check_for_error( ) ?;
431+
420432 // NOTE(unsafe) atomic read with no side effects
421433 let isr = unsafe { ( * pac:: $USARTX:: ptr( ) ) . isr. read( ) } ;
422434
423- // NOTE(unsafe): Only used for atomic writes, to clear error flags.
424- let icr = unsafe { & ( * pac:: $USARTX:: ptr( ) ) . icr } ;
425-
426- Err ( if isr. pe( ) . bit_is_set( ) {
427- icr. write( |w| w. pecf( ) . clear( ) ) ;
428- nb:: Error :: Other ( Error :: Parity )
429- } else if isr. fe( ) . bit_is_set( ) {
430- icr. write( |w| w. fecf( ) . clear( ) ) ;
431- nb:: Error :: Other ( Error :: Framing )
432- } else if isr. nf( ) . bit_is_set( ) {
433- icr. write( |w| w. ncf( ) . clear( ) ) ;
434- nb:: Error :: Other ( Error :: Noise )
435- } else if isr. ore( ) . bit_is_set( ) {
436- icr. write( |w| w. orecf( ) . clear( ) ) ;
437- nb:: Error :: Other ( Error :: Overrun )
438- } else if isr. rxne( ) . bit_is_set( ) {
435+ if isr. rxne( ) . bit_is_set( ) {
439436 // NOTE(read_volatile) see `write_volatile` below
440437 return Ok ( unsafe {
441438 ptr:: read_volatile( & ( * pac:: $USARTX:: ptr( ) ) . rdr as * const _ as * const _)
442439 } ) ;
443- } else {
444- nb :: Error :: WouldBlock
445- } )
440+ }
441+
442+ Err ( nb :: Error :: WouldBlock )
446443 }
447444 }
448445
@@ -643,6 +640,38 @@ macro_rules! hal {
643640 false
644641 }
645642 }
643+
644+ /// Check for, and return, any errors
645+ ///
646+ /// The `read` methods can only return one error at a time, but
647+ /// there might actually be multiple errors. This method will
648+ /// return and clear a currently active error. Once it returns
649+ /// `Ok(())`, it should be possible to proceed with the next
650+ /// `read` call unimpeded.
651+ pub fn check_for_error( & mut self ) -> Result <( ) , Error > {
652+ // NOTE(unsafe): Only used for atomic access.
653+ let isr = unsafe { ( * pac:: $USARTX:: ptr( ) ) . isr. read( ) } ;
654+ let icr = unsafe { & ( * pac:: $USARTX:: ptr( ) ) . icr } ;
655+
656+ if isr. pe( ) . bit_is_set( ) {
657+ icr. write( |w| w. pecf( ) . clear( ) ) ;
658+ return Err ( Error :: Parity ) ;
659+ }
660+ if isr. fe( ) . bit_is_set( ) {
661+ icr. write( |w| w. fecf( ) . clear( ) ) ;
662+ return Err ( Error :: Framing ) ;
663+ }
664+ if isr. nf( ) . bit_is_set( ) {
665+ icr. write( |w| w. ncf( ) . clear( ) ) ;
666+ return Err ( Error :: Noise ) ;
667+ }
668+ if isr. ore( ) . bit_is_set( ) {
669+ icr. write( |w| w. orecf( ) . clear( ) ) ;
670+ return Err ( Error :: Overrun ) ;
671+ }
672+
673+ Ok ( ( ) )
674+ }
646675 }
647676
648677 impl Tx <pac:: $USARTX> {
0 commit comments