@@ -36,6 +36,8 @@ use embedded_hal::prelude::*;
3636#[ allow( unused) ]
3737use crate :: { gpio:: * , rcc:: Clocks , time:: Bps } ;
3838
39+ use core:: marker:: PhantomData ;
40+
3941/// Serial error
4042#[ derive( Debug ) ]
4143pub enum Error {
@@ -188,11 +190,15 @@ pub struct Serial<USART, TXPIN, RXPIN> {
188190 pins : ( TXPIN , RXPIN ) ,
189191}
190192
193+ // Common register
194+ #[ cfg( feature = "device-selected" ) ]
195+ type SerialRegisterBlock = crate :: stm32:: usart1:: RegisterBlock ;
196+
191197/// Serial receiver
192198#[ allow( unused) ]
193199pub struct Rx < USART > {
194- // This is ok, because the USART types only contains PhantomData
195- usart : * const USART ,
200+ usart : * const SerialRegisterBlock ,
201+ _instance : PhantomData < USART > ,
196202}
197203
198204// NOTE(unsafe) Required to allow protected shared access in handlers
@@ -201,8 +207,8 @@ unsafe impl<USART> Send for Rx<USART> {}
201207/// Serial transmitter
202208#[ allow( unused) ]
203209pub struct Tx < USART > {
204- // This is ok, because the USART types only contains PhantomData
205- usart : * const USART ,
210+ usart : * const SerialRegisterBlock ,
211+ _instance : PhantomData < USART > ,
206212}
207213
208214// NOTE(unsafe) Required to allow protected shared access in handlers
@@ -343,11 +349,6 @@ usart! {
343349 USART6 : ( usart6, usart6tx, usart6rx, usart6en, apb2enr) ,
344350}
345351
346- // It's s needed for the impls, but rustc doesn't recognize that
347- #[ allow( dead_code) ]
348- #[ cfg( feature = "device-selected" ) ]
349- type SerialRegisterBlock = crate :: stm32:: usart1:: RegisterBlock ;
350-
351352#[ cfg( feature = "device-selected" ) ]
352353impl < USART > embedded_hal:: serial:: Read < u8 > for Rx < USART >
353354where
@@ -357,23 +358,7 @@ where
357358
358359 /// Tries to read a byte from the uart
359360 fn read ( & mut self ) -> nb:: Result < u8 , Error > {
360- // NOTE(unsafe) atomic read with no side effects
361- let isr = unsafe { ( * self . usart ) . isr . read ( ) } ;
362-
363- Err ( if isr. pe ( ) . bit_is_set ( ) {
364- nb:: Error :: Other ( Error :: Parity )
365- } else if isr. fe ( ) . bit_is_set ( ) {
366- nb:: Error :: Other ( Error :: Framing )
367- } else if isr. nf ( ) . bit_is_set ( ) {
368- nb:: Error :: Other ( Error :: Noise )
369- } else if isr. ore ( ) . bit_is_set ( ) {
370- nb:: Error :: Other ( Error :: Overrun )
371- } else if isr. rxne ( ) . bit_is_set ( ) {
372- // NOTE(read_volatile) see `write_volatile` below
373- return Ok ( unsafe { ptr:: read_volatile ( & ( * self . usart ) . rdr as * const _ as * const _ ) } ) ;
374- } else {
375- nb:: Error :: WouldBlock
376- } )
361+ read ( self . usart )
377362 }
378363}
379364
@@ -386,10 +371,7 @@ where
386371
387372 /// Tries to read a byte from the uart
388373 fn read ( & mut self ) -> nb:: Result < u8 , Error > {
389- Rx {
390- usart : & self . usart as * const _ ,
391- }
392- . read ( )
374+ read ( & * self . usart )
393375 }
394376}
395377
@@ -402,30 +384,13 @@ where
402384
403385 /// Ensures that none of the previously written words are still buffered
404386 fn flush ( & mut self ) -> nb:: Result < ( ) , Self :: Error > {
405- // NOTE(unsafe) atomic read with no side effects
406- let isr = unsafe { ( * self . usart ) . isr . read ( ) } ;
407-
408- if isr. tc ( ) . bit_is_set ( ) {
409- Ok ( ( ) )
410- } else {
411- Err ( nb:: Error :: WouldBlock )
412- }
387+ flush ( self . usart )
413388 }
414389
415390 /// Tries to write a byte to the uart
416391 /// Fails if the transmit buffer is full
417392 fn write ( & mut self , byte : u8 ) -> nb:: Result < ( ) , Self :: Error > {
418- // NOTE(unsafe) atomic read with no side effects
419- let isr = unsafe { ( * self . usart ) . isr . read ( ) } ;
420-
421- if isr. txe ( ) . bit_is_set ( ) {
422- // NOTE(unsafe) atomic write to stateless register
423- // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
424- unsafe { ptr:: write_volatile ( & ( * self . usart ) . tdr as * const _ as * mut _ , byte) }
425- Ok ( ( ) )
426- } else {
427- Err ( nb:: Error :: WouldBlock )
428- }
393+ write ( self . usart , byte)
429394 }
430395}
431396
@@ -438,19 +403,13 @@ where
438403
439404 /// Ensures that none of the previously written words are still buffered
440405 fn flush ( & mut self ) -> nb:: Result < ( ) , Self :: Error > {
441- Tx {
442- usart : & self . usart as * const _ ,
443- }
444- . flush ( )
406+ flush ( & * self . usart )
445407 }
446408
447409 /// Tries to write a byte to the uart
448410 /// Fails if the transmit buffer is full
449411 fn write ( & mut self , byte : u8 ) -> nb:: Result < ( ) , Self :: Error > {
450- Tx {
451- usart : & self . usart as * const _ ,
452- }
453- . write ( byte)
412+ write ( & * self . usart , byte)
454413 }
455414}
456415
@@ -468,10 +427,12 @@ where
468427 {
469428 (
470429 Tx {
471- usart : & self . usart as * const _ ,
430+ usart : & * self . usart ,
431+ _instance : PhantomData ,
472432 } ,
473433 Rx {
474- usart : & self . usart as * const _ ,
434+ usart : & * self . usart ,
435+ _instance : PhantomData ,
475436 } ,
476437 )
477438 }
@@ -493,3 +454,52 @@ where
493454 Ok ( ( ) )
494455 }
495456}
457+
458+ /// Ensures that none of the previously written words are still buffered
459+ fn flush ( usart : * const SerialRegisterBlock ) -> nb:: Result < ( ) , void:: Void > {
460+ // NOTE(unsafe) atomic read with no side effects
461+ let isr = unsafe { ( * usart) . isr . read ( ) } ;
462+
463+ if isr. tc ( ) . bit_is_set ( ) {
464+ Ok ( ( ) )
465+ } else {
466+ Err ( nb:: Error :: WouldBlock )
467+ }
468+ }
469+
470+ /// Tries to write a byte to the uart
471+ /// Fails if the transmit buffer is full
472+ fn write ( usart : * const SerialRegisterBlock , byte : u8 ) -> nb:: Result < ( ) , void:: Void > {
473+ // NOTE(unsafe) atomic read with no side effects
474+ let isr = unsafe { ( * usart) . isr . read ( ) } ;
475+
476+ if isr. txe ( ) . bit_is_set ( ) {
477+ // NOTE(unsafe) atomic write to stateless register
478+ // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
479+ unsafe { ptr:: write_volatile ( & ( * usart) . tdr as * const _ as * mut _ , byte) }
480+ Ok ( ( ) )
481+ } else {
482+ Err ( nb:: Error :: WouldBlock )
483+ }
484+ }
485+
486+ /// Tries to read a byte from the uart
487+ fn read ( usart : * const SerialRegisterBlock ) -> nb:: Result < u8 , Error > {
488+ // NOTE(unsafe) atomic read with no side effects
489+ let isr = unsafe { ( * usart) . isr . read ( ) } ;
490+
491+ Err ( if isr. pe ( ) . bit_is_set ( ) {
492+ nb:: Error :: Other ( Error :: Parity )
493+ } else if isr. fe ( ) . bit_is_set ( ) {
494+ nb:: Error :: Other ( Error :: Framing )
495+ } else if isr. nf ( ) . bit_is_set ( ) {
496+ nb:: Error :: Other ( Error :: Noise )
497+ } else if isr. ore ( ) . bit_is_set ( ) {
498+ nb:: Error :: Other ( Error :: Overrun )
499+ } else if isr. rxne ( ) . bit_is_set ( ) {
500+ // NOTE(read_volatile) see `write_volatile` below
501+ return Ok ( unsafe { ptr:: read_volatile ( & ( * usart) . rdr as * const _ as * const _ ) } ) ;
502+ } else {
503+ nb:: Error :: WouldBlock
504+ } )
505+ }
0 commit comments