@@ -36,6 +36,8 @@ use embedded_hal::prelude::*;
36
36
#[ allow( unused) ]
37
37
use crate :: { gpio:: * , rcc:: Clocks , time:: Bps } ;
38
38
39
+ use core:: marker:: PhantomData ;
40
+
39
41
/// Serial error
40
42
#[ derive( Debug ) ]
41
43
pub enum Error {
@@ -188,11 +190,15 @@ pub struct Serial<USART, TXPIN, RXPIN> {
188
190
pins : ( TXPIN , RXPIN ) ,
189
191
}
190
192
193
+ // Common register
194
+ #[ cfg( feature = "device-selected" ) ]
195
+ type SerialRegisterBlock = crate :: stm32:: usart1:: RegisterBlock ;
196
+
191
197
/// Serial receiver
192
198
#[ allow( unused) ]
193
199
pub 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 > ,
196
202
}
197
203
198
204
// NOTE(unsafe) Required to allow protected shared access in handlers
@@ -201,8 +207,8 @@ unsafe impl<USART> Send for Rx<USART> {}
201
207
/// Serial transmitter
202
208
#[ allow( unused) ]
203
209
pub 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 > ,
206
212
}
207
213
208
214
// NOTE(unsafe) Required to allow protected shared access in handlers
@@ -343,11 +349,6 @@ usart! {
343
349
USART6 : ( usart6, usart6tx, usart6rx, usart6en, apb2enr) ,
344
350
}
345
351
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
-
351
352
#[ cfg( feature = "device-selected" ) ]
352
353
impl < USART > embedded_hal:: serial:: Read < u8 > for Rx < USART >
353
354
where
@@ -357,23 +358,7 @@ where
357
358
358
359
/// Tries to read a byte from the uart
359
360
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 )
377
362
}
378
363
}
379
364
@@ -386,10 +371,7 @@ where
386
371
387
372
/// Tries to read a byte from the uart
388
373
fn read ( & mut self ) -> nb:: Result < u8 , Error > {
389
- Rx {
390
- usart : & self . usart as * const _ ,
391
- }
392
- . read ( )
374
+ read ( & * self . usart )
393
375
}
394
376
}
395
377
@@ -402,30 +384,13 @@ where
402
384
403
385
/// Ensures that none of the previously written words are still buffered
404
386
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 )
413
388
}
414
389
415
390
/// Tries to write a byte to the uart
416
391
/// Fails if the transmit buffer is full
417
392
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)
429
394
}
430
395
}
431
396
@@ -438,19 +403,13 @@ where
438
403
439
404
/// Ensures that none of the previously written words are still buffered
440
405
fn flush ( & mut self ) -> nb:: Result < ( ) , Self :: Error > {
441
- Tx {
442
- usart : & self . usart as * const _ ,
443
- }
444
- . flush ( )
406
+ flush ( & * self . usart )
445
407
}
446
408
447
409
/// Tries to write a byte to the uart
448
410
/// Fails if the transmit buffer is full
449
411
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)
454
413
}
455
414
}
456
415
@@ -468,10 +427,12 @@ where
468
427
{
469
428
(
470
429
Tx {
471
- usart : & self . usart as * const _ ,
430
+ usart : & * self . usart ,
431
+ _instance : PhantomData ,
472
432
} ,
473
433
Rx {
474
- usart : & self . usart as * const _ ,
434
+ usart : & * self . usart ,
435
+ _instance : PhantomData ,
475
436
} ,
476
437
)
477
438
}
@@ -493,3 +454,52 @@ where
493
454
Ok ( ( ) )
494
455
}
495
456
}
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