@@ -41,6 +41,8 @@ use embedded_hal::prelude::*;
4141
4242use crate :: { gpio:: * , rcc:: Rcc , time:: Bps } ;
4343
44+ use core:: marker:: PhantomData ;
45+
4446/// Serial error
4547#[ derive( Debug ) ]
4648pub enum Error {
@@ -208,19 +210,22 @@ pub struct Serial<USART, TXPIN, RXPIN> {
208210 pins : ( TXPIN , RXPIN ) ,
209211}
210212
213+ // Common register
214+ type SerialRegisterBlock = crate :: stm32:: usart1:: RegisterBlock ;
215+
211216/// Serial receiver
212217pub struct Rx < USART > {
213- // This is ok, because the USART types only contains PhantomData
214- usart : * const USART ,
218+ usart : * const SerialRegisterBlock ,
219+ _instance : PhantomData < USART > ,
215220}
216221
217222// NOTE(unsafe) Required to allow protected shared access in handlers
218223unsafe impl < USART > Send for Rx < USART > { }
219224
220225/// Serial transmitter
221226pub struct Tx < USART > {
222- // This is ok, because the USART types only contains PhantomData
223- usart : * const USART ,
227+ usart : * const SerialRegisterBlock ,
228+ _instance : PhantomData < USART > ,
224229}
225230
226231// NOTE(unsafe) Required to allow protected shared access in handlers
@@ -359,10 +364,6 @@ usart! {
359364 USART6 : ( usart6, usart6tx, usart6rx, usart6en, apb2enr) ,
360365}
361366
362- // It's s needed for the impls, but rustc doesn't recognize that
363- #[ allow( dead_code) ]
364- type SerialRegisterBlock = crate :: stm32:: usart1:: RegisterBlock ;
365-
366367impl < USART > embedded_hal:: serial:: Read < u8 > for Rx < USART >
367368where
368369 USART : Deref < Target = SerialRegisterBlock > ,
@@ -371,23 +372,7 @@ where
371372
372373 /// Tries to read a byte from the uart
373374 fn read ( & mut self ) -> nb:: Result < u8 , Error > {
374- // NOTE(unsafe) atomic read with no side effects
375- let isr = unsafe { ( * self . usart ) . isr . read ( ) } ;
376-
377- Err ( if isr. pe ( ) . bit_is_set ( ) {
378- nb:: Error :: Other ( Error :: Parity )
379- } else if isr. fe ( ) . bit_is_set ( ) {
380- nb:: Error :: Other ( Error :: Framing )
381- } else if isr. nf ( ) . bit_is_set ( ) {
382- nb:: Error :: Other ( Error :: Noise )
383- } else if isr. ore ( ) . bit_is_set ( ) {
384- nb:: Error :: Other ( Error :: Overrun )
385- } else if isr. rxne ( ) . bit_is_set ( ) {
386- // NOTE(read_volatile) see `write_volatile` below
387- return Ok ( unsafe { ptr:: read_volatile ( & ( * self . usart ) . rdr as * const _ as * const _ ) } ) ;
388- } else {
389- nb:: Error :: WouldBlock
390- } )
375+ read ( self . usart )
391376 }
392377}
393378
@@ -400,10 +385,7 @@ where
400385
401386 /// Tries to read a byte from the uart
402387 fn read ( & mut self ) -> nb:: Result < u8 , Error > {
403- Rx {
404- usart : & self . usart as * const _ ,
405- }
406- . read ( )
388+ read ( & * self . usart )
407389 }
408390}
409391
@@ -415,30 +397,13 @@ where
415397
416398 /// Ensures that none of the previously written words are still buffered
417399 fn flush ( & mut self ) -> 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. tc ( ) . bit_is_set ( ) {
422- Ok ( ( ) )
423- } else {
424- Err ( nb:: Error :: WouldBlock )
425- }
400+ flush ( self . usart )
426401 }
427402
428403 /// Tries to write a byte to the uart
429404 /// Fails if the transmit buffer is full
430405 fn write ( & mut self , byte : u8 ) -> nb:: Result < ( ) , Self :: Error > {
431- // NOTE(unsafe) atomic read with no side effects
432- let isr = unsafe { ( * self . usart ) . isr . read ( ) } ;
433-
434- if isr. txe ( ) . bit_is_set ( ) {
435- // NOTE(unsafe) atomic write to stateless register
436- // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
437- unsafe { ptr:: write_volatile ( & ( * self . usart ) . tdr as * const _ as * mut _ , byte) }
438- Ok ( ( ) )
439- } else {
440- Err ( nb:: Error :: WouldBlock )
441- }
406+ write ( self . usart , byte)
442407 }
443408}
444409
@@ -451,19 +416,13 @@ where
451416
452417 /// Ensures that none of the previously written words are still buffered
453418 fn flush ( & mut self ) -> nb:: Result < ( ) , Self :: Error > {
454- Tx {
455- usart : & self . usart as * const _ ,
456- }
457- . flush ( )
419+ flush ( & * self . usart )
458420 }
459421
460422 /// Tries to write a byte to the uart
461423 /// Fails if the transmit buffer is full
462424 fn write ( & mut self , byte : u8 ) -> nb:: Result < ( ) , Self :: Error > {
463- Tx {
464- usart : & self . usart as * const _ ,
465- }
466- . write ( byte)
425+ write ( & * self . usart , byte)
467426 }
468427}
469428
@@ -480,10 +439,12 @@ where
480439 {
481440 (
482441 Tx {
483- usart : & self . usart as * const _ ,
442+ usart : & * self . usart ,
443+ _instance : PhantomData ,
484444 } ,
485445 Rx {
486- usart : & self . usart as * const _ ,
446+ usart : & * self . usart ,
447+ _instance : PhantomData ,
487448 } ,
488449 )
489450 }
@@ -504,3 +465,52 @@ where
504465 Ok ( ( ) )
505466 }
506467}
468+
469+ /// Ensures that none of the previously written words are still buffered
470+ fn flush ( usart : * const SerialRegisterBlock ) -> nb:: Result < ( ) , void:: Void > {
471+ // NOTE(unsafe) atomic read with no side effects
472+ let isr = unsafe { ( * usart) . isr . read ( ) } ;
473+
474+ if isr. tc ( ) . bit_is_set ( ) {
475+ Ok ( ( ) )
476+ } else {
477+ Err ( nb:: Error :: WouldBlock )
478+ }
479+ }
480+
481+ /// Tries to write a byte to the uart
482+ /// Fails if the transmit buffer is full
483+ fn write ( usart : * const SerialRegisterBlock , byte : u8 ) -> nb:: Result < ( ) , void:: Void > {
484+ // NOTE(unsafe) atomic read with no side effects
485+ let isr = unsafe { ( * usart) . isr . read ( ) } ;
486+
487+ if isr. txe ( ) . bit_is_set ( ) {
488+ // NOTE(unsafe) atomic write to stateless register
489+ // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
490+ unsafe { ptr:: write_volatile ( & ( * usart) . tdr as * const _ as * mut _ , byte) }
491+ Ok ( ( ) )
492+ } else {
493+ Err ( nb:: Error :: WouldBlock )
494+ }
495+ }
496+
497+ /// Tries to read a byte from the uart
498+ fn read ( usart : * const SerialRegisterBlock ) -> nb:: Result < u8 , Error > {
499+ // NOTE(unsafe) atomic read with no side effects
500+ let isr = unsafe { ( * usart) . isr . read ( ) } ;
501+
502+ Err ( if isr. pe ( ) . bit_is_set ( ) {
503+ nb:: Error :: Other ( Error :: Parity )
504+ } else if isr. fe ( ) . bit_is_set ( ) {
505+ nb:: Error :: Other ( Error :: Framing )
506+ } else if isr. nf ( ) . bit_is_set ( ) {
507+ nb:: Error :: Other ( Error :: Noise )
508+ } else if isr. ore ( ) . bit_is_set ( ) {
509+ nb:: Error :: Other ( Error :: Overrun )
510+ } else if isr. rxne ( ) . bit_is_set ( ) {
511+ // NOTE(read_volatile) see `write_volatile` below
512+ return Ok ( unsafe { ptr:: read_volatile ( & ( * usart) . rdr as * const _ as * const _ ) } ) ;
513+ } else {
514+ nb:: Error :: WouldBlock
515+ } )
516+ }
0 commit comments