@@ -66,7 +66,7 @@ use crate::{
66
66
hal:: digital:: v2:: OutputPin ,
67
67
pac:: { Interrupt , EXTI } ,
68
68
rcc:: AHB ,
69
- syscfg :: SysCfg ,
69
+ Toggle ,
70
70
} ;
71
71
72
72
use crate :: hal:: digital:: v2:: { toggleable, InputPin , StatefulOutputPin } ;
@@ -209,6 +209,9 @@ impl private::Gpio for Gpiox {
209
209
impl marker:: Gpio for Gpiox { }
210
210
211
211
/// Runtime defined pin number (type state)
212
+ // TODO(Sh3Rm4n): If the pin number wouldn't be runtime defined, the implementation for all
213
+ // statically defined pins would be much easier (and withless overhead). What could be the
214
+ // solution?
212
215
pub struct Ux ( u8 ) ;
213
216
214
217
impl marker:: Index for Ux {
@@ -250,6 +253,8 @@ impl<Otype> marker::Active for Output<Otype> {}
250
253
impl < Otype , const AF : u8 > marker:: Active for Alternate < Otype , AF > { }
251
254
252
255
/// Slew rate configuration
256
+ #[ derive( Copy , Clone , PartialEq , Eq ) ]
257
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
253
258
pub enum Speed {
254
259
/// Low speed
255
260
Low ,
@@ -260,6 +265,8 @@ pub enum Speed {
260
265
}
261
266
262
267
/// Internal pull-up and pull-down resistor configuration
268
+ #[ derive( Copy , Clone , PartialEq , Eq ) ]
269
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
263
270
pub enum Resistor {
264
271
/// Floating
265
272
Floating ,
@@ -270,6 +277,8 @@ pub enum Resistor {
270
277
}
271
278
272
279
/// GPIO interrupt trigger edge selection
280
+ #[ derive( Copy , Clone , PartialEq , Eq ) ]
281
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
273
282
pub enum Edge {
274
283
/// Rising edge of voltage
275
284
Rising ,
@@ -281,8 +290,8 @@ pub enum Edge {
281
290
282
291
/// Generic pin
283
292
pub struct Pin < Gpio , Index , Mode > {
284
- gpio : Gpio ,
285
- index : Index ,
293
+ pub ( crate ) gpio : Gpio ,
294
+ pub ( crate ) index : Index ,
286
295
_mode : PhantomData < Mode > ,
287
296
}
288
297
@@ -300,17 +309,6 @@ impl<Gpio, Index, Mode> crate::private::Sealed for Pin<Gpio, Index, Mode> {}
300
309
/// [examples/gpio_erased.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.7.0/examples/gpio_erased.rs
301
310
pub type PXx < Mode > = Pin < Gpiox , Ux , Mode > ;
302
311
303
- /// Modify specific index of array-like register
304
- macro_rules! modify_at {
305
- ( $reg: expr, $bitwidth: expr, $index: expr, $value: expr) => {
306
- $reg. modify( |r, w| {
307
- let mask = !( u32 :: MAX >> ( 32 - $bitwidth) << ( $bitwidth * $index) ) ;
308
- let value = $value << ( $bitwidth * $index) ;
309
- w. bits( r. bits( ) & mask | value)
310
- } ) ;
311
- } ;
312
- }
313
-
314
312
impl < Gpio , Mode , const X : u8 > Pin < Gpio , U < X > , Mode > {
315
313
/// Erases the pin number from the type
316
314
///
@@ -563,6 +561,11 @@ where
563
561
Mode : marker:: Active ,
564
562
{
565
563
/// NVIC interrupt number of interrupt from this pin
564
+ ///
565
+ /// Used to unmask / enable the interrupt with [`cortex_m::peripheral::NVIC::unmask()`].
566
+ /// This is also useful for all other [`cortex_m::peripheral::NVIC`] functions.
567
+ // TODO(Sh3rm4n): It would be cool to have this either const or have a const function.
568
+ // But this is currenlty not possible, because index() is runtime defined.
566
569
pub fn nvic ( & self ) -> Interrupt {
567
570
match self . index . index ( ) {
568
571
0 => Interrupt :: EXTI0 ,
@@ -578,62 +581,68 @@ where
578
581
#[ cfg( not( feature = "svd-f373" ) ) ]
579
582
5 ..=9 => Interrupt :: EXTI9_5 ,
580
583
10 ..=15 => Interrupt :: EXTI15_10 ,
581
- _ => unreachable ! ( ) ,
584
+ _ => crate :: unreachable!( ) ,
582
585
}
583
586
}
584
587
585
- /// Make corresponding EXTI line sensitive to this pin
586
- pub fn make_interrupt_source ( & mut self , syscfg : & mut SysCfg ) {
587
- let bitwidth = 4 ;
588
- let index = self . index . index ( ) % 4 ;
589
- let extigpionr = self . gpio . port_index ( ) as u32 ;
590
- match self . index . index ( ) {
591
- 0 ..=3 => unsafe { modify_at ! ( syscfg. exticr1, bitwidth, index, extigpionr) } ,
592
- 4 ..=7 => unsafe { modify_at ! ( syscfg. exticr2, bitwidth, index, extigpionr) } ,
593
- 8 ..=11 => unsafe { modify_at ! ( syscfg. exticr3, bitwidth, index, extigpionr) } ,
594
- 12 ..=15 => unsafe { modify_at ! ( syscfg. exticr4, bitwidth, index, extigpionr) } ,
595
- _ => unreachable ! ( ) ,
596
- } ;
597
- }
598
-
599
588
/// Generate interrupt on rising edge, falling edge, or both
600
589
pub fn trigger_on_edge ( & mut self , exti : & mut EXTI , edge : Edge ) {
601
- let bitwidth = 1 ;
590
+ const BITWIDTH : u8 = 1 ;
602
591
let index = self . index . index ( ) ;
603
592
let ( rise, fall) = match edge {
604
593
Edge :: Rising => ( true as u32 , false as u32 ) ,
605
594
Edge :: Falling => ( false as u32 , true as u32 ) ,
606
595
Edge :: RisingFalling => ( true as u32 , true as u32 ) ,
607
596
} ;
597
+ // SAFETY: Unguarded write to the register, but behind a &mut
608
598
unsafe {
609
- modify_at ! ( reg_for_cpu!( exti, rtsr) , bitwidth , index, rise) ;
610
- modify_at ! ( reg_for_cpu!( exti, ftsr) , bitwidth , index, fall) ;
599
+ crate :: modify_at!( reg_for_cpu!( exti, rtsr) , BITWIDTH , index, rise) ;
600
+ crate :: modify_at!( reg_for_cpu!( exti, ftsr) , BITWIDTH , index, fall) ;
611
601
}
612
602
}
613
603
604
+ /// Configure external interrupts from this pin
605
+ ///
606
+ /// # Note
607
+ ///
608
+ /// Remeber to also configure the interrupt pin on
609
+ /// the SysCfg site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`]
610
+ pub fn configure_interrupt ( & mut self , exti : & mut EXTI , enable : impl Into < Toggle > ) {
611
+ const BITWIDTH : u8 = 1 ;
612
+
613
+ let enable: Toggle = enable. into ( ) ;
614
+ let enable: bool = enable. into ( ) ;
615
+
616
+ let index = self . index . index ( ) ;
617
+ let value = u32:: from ( enable) ;
618
+ // SAFETY: Unguarded write to the register, but behind a &mut
619
+ unsafe { crate :: modify_at!( reg_for_cpu!( exti, imr) , BITWIDTH , index, value) } ;
620
+ }
621
+
614
622
/// Enable external interrupts from this pin
623
+ ///
624
+ /// # Note
625
+ ///
626
+ /// Remeber to also configure the interrupt pin on
627
+ /// the SysCfg site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`]
615
628
pub fn enable_interrupt ( & mut self , exti : & mut EXTI ) {
616
- let bitwidth = 1 ;
617
- let index = self . index . index ( ) ;
618
- let value = 1 ;
619
- unsafe { modify_at ! ( reg_for_cpu!( exti, imr) , bitwidth, index, value) } ;
629
+ self . configure_interrupt ( exti, Toggle :: On )
620
630
}
621
631
622
632
/// Disable external interrupts from this pin
623
633
pub fn disable_interrupt ( & mut self , exti : & mut EXTI ) {
624
- let bitwidth = 1 ;
625
- let index = self . index . index ( ) ;
626
- let value = 0 ;
627
- unsafe { modify_at ! ( reg_for_cpu!( exti, imr) , bitwidth, index, value) } ;
634
+ self . configure_interrupt ( exti, Toggle :: Off )
628
635
}
629
636
630
637
/// Clear the interrupt pending bit for this pin
631
- pub fn clear_interrupt_pending_bit ( & mut self ) {
638
+ pub fn clear_interrupt ( & mut self ) {
639
+ // SAFETY: Atomic write to register without side-effects.
632
640
unsafe { reg_for_cpu ! ( ( * EXTI :: ptr( ) ) , pr) . write ( |w| w. bits ( 1 << self . index . index ( ) ) ) } ;
633
641
}
634
642
635
643
/// Reads the interrupt pending bit for this pin
636
- pub fn check_interrupt ( & self ) -> bool {
644
+ pub fn is_interrupt_pending ( & self ) -> bool {
645
+ // SAFETY: Atomic write to register without side-effects.
637
646
unsafe { reg_for_cpu ! ( ( * EXTI :: ptr( ) ) , pr) . read ( ) . bits ( ) & ( 1 << self . index . index ( ) ) != 0 }
638
647
}
639
648
}
@@ -735,7 +744,7 @@ macro_rules! r_trait {
735
744
#[ inline]
736
745
fn $fn( & mut self , i: u8 ) {
737
746
let value = $gpioy:: $xr:: $enum:: $VARIANT as u32 ;
738
- unsafe { modify_at!( ( * $GPIOX:: ptr( ) ) . $xr, $bitwidth, i, value) } ;
747
+ unsafe { crate :: modify_at!( ( * $GPIOX:: ptr( ) ) . $xr, $bitwidth, i, value) } ;
739
748
}
740
749
) +
741
750
}
@@ -875,8 +884,8 @@ macro_rules! gpio {
875
884
impl Afr for AFRH {
876
885
#[ inline]
877
886
fn afx( & mut self , i: u8 , x: u8 ) {
878
- let bitwidth = 4 ;
879
- unsafe { modify_at!( ( * $GPIOX:: ptr( ) ) . afrh, bitwidth , i - 8 , x as u32 ) } ;
887
+ const BITWIDTH : u8 = 4 ;
888
+ unsafe { crate :: modify_at!( ( * $GPIOX:: ptr( ) ) . afrh, BITWIDTH , i - 8 , x as u32 ) } ;
880
889
}
881
890
}
882
891
@@ -886,8 +895,8 @@ macro_rules! gpio {
886
895
impl Afr for AFRL {
887
896
#[ inline]
888
897
fn afx( & mut self , i: u8 , x: u8 ) {
889
- let bitwidth = 4 ;
890
- unsafe { modify_at!( ( * $GPIOX:: ptr( ) ) . afrl, bitwidth , i, x as u32 ) } ;
898
+ const BITWIDTH : u8 = 4 ;
899
+ unsafe { crate :: modify_at!( ( * $GPIOX:: ptr( ) ) . afrl, BITWIDTH , i, x as u32 ) } ;
891
900
}
892
901
}
893
902
0 commit comments