30
30
31
31
use core:: { convert:: Infallible , marker:: PhantomData } ;
32
32
33
- use crate :: { hal:: digital:: v2:: OutputPin , rcc:: AHB } ;
33
+ use crate :: { hal:: digital:: v2:: OutputPin , pac :: EXTI , rcc:: AHB , syscfg :: SysCfg } ;
34
34
35
35
#[ cfg( feature = "unproven" ) ]
36
36
use crate :: hal:: digital:: v2:: { toggleable, InputPin , StatefulOutputPin } ;
@@ -87,6 +87,7 @@ mod private {
87
87
type Reg : GpioRegExt + ?Sized ;
88
88
89
89
fn ptr ( & self ) -> * const Self :: Reg ;
90
+ fn port_index ( & self ) -> u8 ;
90
91
}
91
92
}
92
93
@@ -129,12 +130,13 @@ pub trait Readable {}
129
130
/// Marker trait for slew rate configurable pin modes
130
131
pub trait OutputSpeed { }
131
132
132
- /// Marker trait for internal resistor enabled pin modes
133
- pub trait InternalResistor { }
133
+ /// Marker trait for active pin modes
134
+ pub trait Active { }
134
135
135
136
/// Runtime defined GPIO port (type state)
136
137
pub struct Gpiox {
137
138
ptr : * const dyn GpioRegExt ,
139
+ index : u8 ,
138
140
}
139
141
140
142
impl private:: Gpio for Gpiox {
@@ -143,6 +145,10 @@ impl private::Gpio for Gpiox {
143
145
fn ptr ( & self ) -> * const Self :: Reg {
144
146
self . ptr
145
147
}
148
+
149
+ fn port_index ( & self ) -> u8 {
150
+ self . index
151
+ }
146
152
}
147
153
148
154
impl Gpio for Gpiox { }
@@ -174,9 +180,9 @@ impl Readable for Input {}
174
180
impl Readable for Output < OpenDrain > { }
175
181
impl < OTYPE > OutputSpeed for Output < OTYPE > { }
176
182
impl < AF , OTYPE > OutputSpeed for Alternate < AF , OTYPE > { }
177
- impl InternalResistor for Input { }
178
- impl < OTYPE > InternalResistor for Output < OTYPE > { }
179
- impl < AF , OTYPE > InternalResistor for Alternate < AF , OTYPE > { }
183
+ impl Active for Input { }
184
+ impl < OTYPE > Active for Output < OTYPE > { }
185
+ impl < AF , OTYPE > Active for Alternate < AF , OTYPE > { }
180
186
181
187
/// Slew rate configuration
182
188
pub enum Speed {
@@ -226,6 +232,14 @@ pub struct Pin<GPIO, INDEX, MODE> {
226
232
/// [examples/gpio_erased.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.0/examples/gpio_erased.rs
227
233
pub type PXx < MODE > = Pin < Gpiox , Ux , MODE > ;
228
234
235
+ macro_rules! modify_at {
236
+ ( $xr: expr, $bits: expr, $i: expr, $val: expr) => {
237
+ $xr. modify( |r, w| {
238
+ w. bits( r. bits( ) & !( u32 :: MAX >> 32 - $bits << $bits * $i) | $val << $bits * $i)
239
+ } ) ;
240
+ } ;
241
+ }
242
+
229
243
impl < GPIO , INDEX , MODE > Pin < GPIO , INDEX , MODE >
230
244
where
231
245
INDEX : Unsigned ,
@@ -256,6 +270,7 @@ where
256
270
PXx {
257
271
gpio : Gpiox {
258
272
ptr : self . gpio . ptr ( ) ,
273
+ index : self . gpio . port_index ( ) ,
259
274
} ,
260
275
index : self . index ,
261
276
_mode : self . _mode ,
@@ -374,7 +389,7 @@ impl<GPIO, INDEX, MODE> Pin<GPIO, INDEX, MODE>
374
389
where
375
390
GPIO : GpioStatic ,
376
391
INDEX : Index ,
377
- MODE : InternalResistor ,
392
+ MODE : Active ,
378
393
{
379
394
/// Set the internal pull-up and pull-down resistor
380
395
pub fn set_internal_resistor ( & mut self , pupdr : & mut GPIO :: PUPDR , resistor : Resistor ) {
@@ -458,6 +473,77 @@ where
458
473
{
459
474
}
460
475
476
+ /// Return an EXTI register for the current CPU
477
+ #[ cfg( any( feature = "stm32f373" , feature = "stm32f378" ) ) ]
478
+ macro_rules! reg_for_cpu {
479
+ ( $exti: expr, $xr: ident) => {
480
+ $exti. $xr
481
+ } ;
482
+ }
483
+
484
+ /// Return an EXTI register for the current CPU
485
+ #[ cfg( not( any( feature = "stm32f373" , feature = "stm32f378" ) ) ) ]
486
+ macro_rules! reg_for_cpu {
487
+ ( $exti: expr, $xr: ident) => {
488
+ paste:: paste! {
489
+ $exti. [ <$xr 1 >]
490
+ }
491
+ } ;
492
+ }
493
+
494
+ impl < GPIO , INDEX , MODE > Pin < GPIO , INDEX , MODE >
495
+ where
496
+ GPIO : Gpio ,
497
+ INDEX : Index ,
498
+ MODE : Active ,
499
+ {
500
+ /// Make corresponding EXTI line sensitive to this pin
501
+ pub fn make_interrupt_source ( & mut self , syscfg : & mut SysCfg ) {
502
+ let i = self . index . index ( ) % 4 ;
503
+ let extigpionr = self . gpio . port_index ( ) as u32 ;
504
+ match self . index . index ( ) {
505
+ 0 ..=3 => unsafe { modify_at ! ( syscfg. exticr1, 4 , i, extigpionr) } ,
506
+ 4 ..=7 => unsafe { modify_at ! ( syscfg. exticr2, 4 , i, extigpionr) } ,
507
+ 8 ..=11 => unsafe { modify_at ! ( syscfg. exticr3, 4 , i, extigpionr) } ,
508
+ 12 ..=15 => unsafe { modify_at ! ( syscfg. exticr4, 4 , i, extigpionr) } ,
509
+ _ => unreachable ! ( ) ,
510
+ }
511
+ }
512
+
513
+ /// Generate interrupt on rising edge, falling edge, or both
514
+ pub fn trigger_on_edge ( & mut self , exti : & mut EXTI , edge : Edge ) {
515
+ let ( rise, fall) = match edge {
516
+ Edge :: Rising => ( true , false ) ,
517
+ Edge :: Falling => ( false , true ) ,
518
+ Edge :: RisingFalling => ( true , true ) ,
519
+ } ;
520
+ unsafe {
521
+ modify_at ! ( reg_for_cpu!( exti, rtsr) , 1 , self . index. index( ) , rise as u32 ) ;
522
+ modify_at ! ( reg_for_cpu!( exti, ftsr) , 1 , self . index. index( ) , fall as u32 ) ;
523
+ }
524
+ }
525
+
526
+ /// Enable external interrupts from this pin.
527
+ pub fn enable_interrupt ( & mut self , exti : & mut EXTI ) {
528
+ unsafe { modify_at ! ( reg_for_cpu!( exti, imr) , 1 , self . index. index( ) , 1 ) } ;
529
+ }
530
+
531
+ /// Disable external interrupts from this pin
532
+ pub fn disable_interrupt ( & mut self , exti : & mut EXTI ) {
533
+ unsafe { modify_at ! ( reg_for_cpu!( exti, imr) , 1 , self . index. index( ) , 0 ) } ;
534
+ }
535
+
536
+ /// Clear the interrupt pending bit for this pin
537
+ pub fn clear_interrupt_pending_bit ( & mut self ) {
538
+ unsafe { reg_for_cpu ! ( ( * EXTI :: ptr( ) ) , pr) . write ( |w| w. bits ( 1 << self . index . index ( ) ) ) } ;
539
+ }
540
+
541
+ /// Reads the interrupt pending bit for this pin
542
+ pub fn check_interrupt ( & self ) -> bool {
543
+ unsafe { reg_for_cpu ! ( ( * EXTI :: ptr( ) ) , pr) . read ( ) . bits ( ) & ( 1 << self . index . index ( ) ) != 0 }
544
+ }
545
+ }
546
+
461
547
macro_rules! af {
462
548
( $i: literal, $Ui: ty, $AFi: ident, $IntoAfi: ident, $into_afi_push_pull: ident, $into_afi_open_drain: ident) => {
463
549
paste:: paste! {
@@ -545,22 +631,6 @@ macro_rules! gpio_trait {
545
631
}
546
632
}
547
633
) +
548
- }
549
- }
550
-
551
- macro_rules! afr_trait {
552
- ( $GPIOX: ident, $AFR: ty, $afr: ident, $offset: expr) => {
553
- impl Afr for $AFR {
554
- #[ inline]
555
- fn afx( & mut self , i: u8 , x: u8 ) {
556
- let i = i - $offset;
557
- unsafe {
558
- ( * $GPIOX:: ptr( ) ) . $afr. modify( |r, w| {
559
- w. bits( r. bits( ) & !( u32 :: MAX >> 32 - 4 << 4 * i) | ( x as u32 ) << 4 * i)
560
- } ) ;
561
- }
562
- }
563
- }
564
634
} ;
565
635
}
566
636
@@ -578,12 +648,7 @@ macro_rules! r_trait {
578
648
#[ inline]
579
649
fn $fn( & mut self , i: u8 ) {
580
650
unsafe {
581
- ( * $GPIOX:: ptr( ) ) . $xr. modify( |r, w| {
582
- w. bits(
583
- r. bits( ) & !( u32 :: MAX >> 32 - $bits << $bits * i)
584
- | ( $gpioy:: $xr:: $enum:: $VARIANT as u32 ) << $bits * i
585
- )
586
- } ) ;
651
+ modify_at!( ( * $GPIOX:: ptr( ) ) . $xr, $bits, i, $gpioy:: $xr:: $enum:: $VARIANT as u32 ) ;
587
652
}
588
653
}
589
654
) +
@@ -598,8 +663,8 @@ macro_rules! gpio {
598
663
Gpio : $Gpiox: ty,
599
664
port_index: $port_index: literal,
600
665
gpio_mapped: $gpioy: ident,
601
- gpio_mapped_ioen : $iopxen: ident,
602
- gpio_mapped_iorst : $iopxrst: ident,
666
+ iopen : $iopxen: ident,
667
+ ioprst : $iopxrst: ident,
603
668
partially_erased_pin: $PXx: ty,
604
669
pins: { $(
605
670
$PXi: ty: (
@@ -619,6 +684,11 @@ macro_rules! gpio {
619
684
fn ptr( & self ) -> * const Self :: Reg {
620
685
crate :: pac:: $GPIOX:: ptr( )
621
686
}
687
+
688
+ #[ inline( always) ]
689
+ fn port_index( & self ) -> u8 {
690
+ $port_index
691
+ }
622
692
}
623
693
624
694
impl Gpio for $Gpiox { }
@@ -704,12 +774,22 @@ macro_rules! gpio {
704
774
/// Opaque AFRH register
705
775
pub struct AFRH ( ( ) ) ;
706
776
707
- afr_trait!( $GPIOX, AFRH , afrh, 8 ) ;
777
+ impl Afr for AFRH {
778
+ #[ inline]
779
+ fn afx( & mut self , i: u8 , x: u8 ) {
780
+ unsafe { modify_at!( ( * $GPIOX:: ptr( ) ) . afrh, 4 , i - 8 , x as u32 ) ; }
781
+ }
782
+ }
708
783
709
784
/// Opaque AFRL register
710
785
pub struct AFRL ( ( ) ) ;
711
786
712
- afr_trait!( $GPIOX, AFRL , afrl, 0 ) ;
787
+ impl Afr for AFRL {
788
+ #[ inline]
789
+ fn afx( & mut self , i: u8 , x: u8 ) {
790
+ unsafe { modify_at!( ( * $GPIOX:: ptr( ) ) . afrl, 4 , i, x as u32 ) ; }
791
+ }
792
+ }
713
793
714
794
/// Opaque MODER register
715
795
pub struct MODER ( ( ) ) ;
@@ -785,7 +865,7 @@ macro_rules! gpio {
785
865
$i: literal => {
786
866
reset: $MODE: ty,
787
867
afr: $LH: ident,
788
- af: [ $( $af: literal ) ,* ]
868
+ af: [ $( $af: literal) ,* ]
789
869
} ,
790
870
) +] ,
791
871
} ,
@@ -800,8 +880,8 @@ macro_rules! gpio {
800
880
Gpio : [ <Gpio $x>] ,
801
881
port_index: $port_index,
802
882
gpio_mapped: $gpioy,
803
- gpio_mapped_ioen : [ <iop $x en>] ,
804
- gpio_mapped_iorst : [ <iop $x rst>] ,
883
+ iopen : [ <iop $x en>] ,
884
+ ioprst : [ <iop $x rst>] ,
805
885
partially_erased_pin: [ <P $X x>] ,
806
886
pins: { $(
807
887
[ <P $X $i>] : (
0 commit comments