@@ -41,6 +41,8 @@ use embedded_hal::prelude::*;
41
41
42
42
use crate :: { gpio:: * , rcc:: Rcc , time:: Bps } ;
43
43
44
+ use core:: marker:: PhantomData ;
45
+
44
46
/// Serial error
45
47
#[ derive( Debug ) ]
46
48
pub enum Error {
@@ -208,19 +210,22 @@ pub struct Serial<USART, TXPIN, RXPIN> {
208
210
pins : ( TXPIN , RXPIN ) ,
209
211
}
210
212
213
+ // Common register
214
+ type SerialRegisterBlock = crate :: stm32:: usart1:: RegisterBlock ;
215
+
211
216
/// Serial receiver
212
217
pub 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 > ,
215
220
}
216
221
217
222
// NOTE(unsafe) Required to allow protected shared access in handlers
218
223
unsafe impl < USART > Send for Rx < USART > { }
219
224
220
225
/// Serial transmitter
221
226
pub 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 > ,
224
229
}
225
230
226
231
// NOTE(unsafe) Required to allow protected shared access in handlers
@@ -359,10 +364,6 @@ usart! {
359
364
USART6 : ( usart6, usart6tx, usart6rx, usart6en, apb2enr) ,
360
365
}
361
366
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
-
366
367
impl < USART > embedded_hal:: serial:: Read < u8 > for Rx < USART >
367
368
where
368
369
USART : Deref < Target = SerialRegisterBlock > ,
@@ -371,23 +372,7 @@ where
371
372
372
373
/// Tries to read a byte from the uart
373
374
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 )
391
376
}
392
377
}
393
378
@@ -400,10 +385,7 @@ where
400
385
401
386
/// Tries to read a byte from the uart
402
387
fn read ( & mut self ) -> nb:: Result < u8 , Error > {
403
- Rx {
404
- usart : & self . usart as * const _ ,
405
- }
406
- . read ( )
388
+ read ( & * self . usart )
407
389
}
408
390
}
409
391
@@ -415,30 +397,13 @@ where
415
397
416
398
/// Ensures that none of the previously written words are still buffered
417
399
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 )
426
401
}
427
402
428
403
/// Tries to write a byte to the uart
429
404
/// Fails if the transmit buffer is full
430
405
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)
442
407
}
443
408
}
444
409
@@ -451,19 +416,13 @@ where
451
416
452
417
/// Ensures that none of the previously written words are still buffered
453
418
fn flush ( & mut self ) -> nb:: Result < ( ) , Self :: Error > {
454
- Tx {
455
- usart : & self . usart as * const _ ,
456
- }
457
- . flush ( )
419
+ flush ( & * self . usart )
458
420
}
459
421
460
422
/// Tries to write a byte to the uart
461
423
/// Fails if the transmit buffer is full
462
424
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)
467
426
}
468
427
}
469
428
@@ -480,10 +439,12 @@ where
480
439
{
481
440
(
482
441
Tx {
483
- usart : & self . usart as * const _ ,
442
+ usart : & * self . usart ,
443
+ _instance : PhantomData ,
484
444
} ,
485
445
Rx {
486
- usart : & self . usart as * const _ ,
446
+ usart : & * self . usart ,
447
+ _instance : PhantomData ,
487
448
} ,
488
449
)
489
450
}
@@ -504,3 +465,52 @@ where
504
465
Ok ( ( ) )
505
466
}
506
467
}
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