1
1
//! Low-power timers
2
2
//!
3
- //! Unlike other modules most functionality is exposed via a single trait shared
4
- //! for all timers, [`LpTim`].
3
+ //! The low power timers implements the `embedded-hal`
4
+ //! [`PwmPin`](embedded_hal::PwmPin) and
5
+ //! [`CountDown`](embedded_hal::timer::CountDown) traits.
5
6
//!
6
7
//! # Example
7
8
//!
@@ -36,7 +37,7 @@ pub use cr::Cr;
36
37
use crate :: {
37
38
gpio:: {
38
39
pins,
39
- sealed:: { LpTim1Etr , LpTim2Etr , LpTim3Etr } ,
40
+ sealed:: { LpTim1Etr , LpTim1Out , LpTim2Etr , LpTim2Out , LpTim3Etr , LpTim3Out } ,
40
41
} ,
41
42
pac, Ratio ,
42
43
} ;
@@ -101,6 +102,7 @@ pub(crate) mod sealed {
101
102
fn modify_cfgr < F : FnOnce ( Cfgr ) -> Cfgr > ( & mut self , f : F ) ;
102
103
fn cr ( & self ) -> Cr ;
103
104
fn set_cr ( & mut self , cr : Cr ) ;
105
+ fn cmp ( & self ) -> u16 ;
104
106
fn set_cmp ( & mut self , cmp : u16 ) ;
105
107
fn set_autoreload ( & mut self , ar : u16 ) ;
106
108
unsafe fn cnt ( ) -> u16 ;
@@ -165,6 +167,11 @@ macro_rules! impl_lptim_base_for {
165
167
self . cr. write( |w| unsafe { w. bits( u32 :: from( cr) & 0x1F ) } )
166
168
}
167
169
170
+ #[ inline( always) ]
171
+ fn cmp( & self ) -> u16 {
172
+ self . cmp. read( ) . cmp( ) . bits( )
173
+ }
174
+
168
175
#[ inline( always) ]
169
176
fn set_cmp( & mut self , cmp: u16 ) {
170
177
self . cmp. write( |w| w. cmp( ) . bits( cmp) ) ;
@@ -472,6 +479,7 @@ pub trait LpTim: sealed::LpTim {
472
479
}
473
480
474
481
/// Returns `true` if the timer is enabled.
482
+ #[ inline]
475
483
fn is_enabled ( & self ) -> bool {
476
484
self . as_tim ( ) . cr ( ) . enabled ( )
477
485
}
@@ -498,7 +506,7 @@ impl LpTim for LpTim1 {
498
506
rcc. ccipr . modify ( |_, w| w. lptim1sel ( ) . bits ( clk as u8 ) ) ;
499
507
unsafe { Self :: pulse_reset ( rcc) }
500
508
Self :: enable_clock ( rcc) ;
501
- tim. set_cfgr ( Cfgr :: RESET . set_prescaler ( pre) ) ;
509
+ tim. set_cfgr ( Cfgr :: RESET . set_prescaler ( pre) . set_wavepol ( true ) ) ;
502
510
503
511
let src: Ratio < u32 > = match clk {
504
512
Clk :: Pclk => crate :: rcc:: apb1timx ( rcc) ,
@@ -546,7 +554,7 @@ impl LpTim for LpTim2 {
546
554
rcc. ccipr . modify ( |_, w| w. lptim2sel ( ) . bits ( clk as u8 ) ) ;
547
555
unsafe { Self :: pulse_reset ( rcc) }
548
556
Self :: enable_clock ( rcc) ;
549
- tim. set_cfgr ( Cfgr :: RESET . set_prescaler ( pre) ) ;
557
+ tim. set_cfgr ( Cfgr :: RESET . set_prescaler ( pre) . set_wavepol ( true ) ) ;
550
558
551
559
let src: Ratio < u32 > = match clk {
552
560
Clk :: Pclk => crate :: rcc:: apb1timx ( rcc) ,
@@ -594,7 +602,7 @@ impl LpTim for LpTim3 {
594
602
rcc. ccipr . modify ( |_, w| w. lptim3sel ( ) . bits ( clk as u8 ) ) ;
595
603
unsafe { Self :: pulse_reset ( rcc) }
596
604
Self :: enable_clock ( rcc) ;
597
- tim. set_cfgr ( Cfgr :: RESET . set_prescaler ( pre) ) ;
605
+ tim. set_cfgr ( Cfgr :: RESET . set_prescaler ( pre) . set_wavepol ( true ) ) ;
598
606
599
607
let src: Ratio < u32 > = match clk {
600
608
Clk :: Pclk => crate :: rcc:: apb1timx ( rcc) ,
@@ -635,7 +643,7 @@ impl LpTim for LpTim3 {
635
643
}
636
644
}
637
645
638
- macro_rules! impl_eh_for {
646
+ macro_rules! impl_eh_countdown_for {
639
647
( $tim: ident) => {
640
648
impl embedded_hal:: timer:: CountDown for $tim {
641
649
type Time = u16 ;
@@ -681,9 +689,58 @@ macro_rules! impl_eh_for {
681
689
} ;
682
690
}
683
691
684
- impl_eh_for ! ( LpTim1 ) ;
685
- impl_eh_for ! ( LpTim2 ) ;
686
- impl_eh_for ! ( LpTim3 ) ;
692
+ impl_eh_countdown_for ! ( LpTim1 ) ;
693
+ impl_eh_countdown_for ! ( LpTim2 ) ;
694
+ impl_eh_countdown_for ! ( LpTim3 ) ;
695
+
696
+ macro_rules! impl_eh_pwmpin_for {
697
+ ( $tim: ident) => {
698
+ impl embedded_hal:: PwmPin for $tim {
699
+ type Duty = u16 ;
700
+
701
+ fn disable( & mut self ) {
702
+ self . as_mut_tim( ) . set_cr( Cr :: DISABLE ) ;
703
+ }
704
+
705
+ fn enable( & mut self ) {
706
+ const CR : Cr = Cr :: RESET . enable( ) . set_continuous( ) ;
707
+ self . as_mut_tim( ) . set_cr( CR ) ;
708
+ }
709
+
710
+ fn get_duty( & self ) -> Self :: Duty {
711
+ self . as_tim( ) . cmp( )
712
+ }
713
+
714
+ fn get_max_duty( & self ) -> Self :: Duty {
715
+ u16 :: MAX
716
+ }
717
+
718
+ fn set_duty( & mut self , duty: Self :: Duty ) {
719
+ if !self . is_enabled( ) {
720
+ const CR : Cr = Cr :: RESET . enable( ) ;
721
+ self . as_mut_tim( ) . set_cr( CR ) ;
722
+
723
+ // RM0461 Rev 4 "Timer enable":
724
+ // After setting the ENABLE bit, a delay of two counter
725
+ // clock is needed before the LPTIM is actually enabled.
726
+ const MAX_SYS_FREQ : u32 = 48_000_000 ;
727
+ let delay: u32 = ( MAX_SYS_FREQ * 2 ) / self . hz( ) . to_integer( ) ;
728
+ cortex_m:: asm:: delay( delay) ;
729
+ }
730
+
731
+ // can only be modified when enabled
732
+ self . as_mut_tim( ) . set_autoreload( u16 :: MAX ) ;
733
+ self . as_mut_tim( ) . set_cmp( duty) ;
734
+ while Self :: isr( ) & ( irq:: ARROK | irq:: CMPOK ) == 0 { }
735
+ unsafe { self . set_icr( irq:: ARROK | irq:: CMPOK ) } ;
736
+ }
737
+ }
738
+ } ;
739
+ }
740
+
741
+ impl_eh_pwmpin_for ! ( LpTim1 ) ;
742
+ impl_eh_pwmpin_for ! ( LpTim2 ) ;
743
+ impl_eh_pwmpin_for ! ( LpTim3 ) ;
687
744
688
745
/// Low-power timer 1 trigger pin.
689
746
///
@@ -917,3 +974,107 @@ impl LpTim3 {
917
974
pin. free ( )
918
975
}
919
976
}
977
+
978
+ /// Low-power timer 1 output pin.
979
+ ///
980
+ /// Constructed with [`new_output_pin`](LpTim1::new_output_pin).
981
+ #[ derive( Debug ) ]
982
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
983
+ pub struct LpTim1OutPin < P > {
984
+ pin : P ,
985
+ }
986
+
987
+ impl < P > LpTim1OutPin < P > {
988
+ fn free ( self ) -> P {
989
+ self . pin
990
+ }
991
+ }
992
+
993
+ // TODO: move to LpTim trait when GATs are stablized
994
+ impl LpTim1 {
995
+ /// Setup a new output pin.
996
+ #[ inline]
997
+ pub fn new_output_pin < P : LpTim1Out > (
998
+ & mut self ,
999
+ mut pin : P ,
1000
+ cs : & CriticalSection ,
1001
+ ) -> LpTim1OutPin < P > {
1002
+ pin. set_lptim1_out_af ( cs) ;
1003
+ LpTim1OutPin { pin }
1004
+ }
1005
+
1006
+ /// Free the output pin previously created with
1007
+ /// [`new_output_pin`](Self::new_output_pin).
1008
+ #[ inline]
1009
+ pub fn free_output_pin < P : LpTim1Out > ( & mut self , pin : LpTim1OutPin < P > ) -> P {
1010
+ pin. free ( )
1011
+ }
1012
+ }
1013
+
1014
+ /// Low-power timer 2 output pin.
1015
+ ///
1016
+ /// Constructed with [`new_output_pin`](LpTim2::new_output_pin).
1017
+ #[ derive( Debug ) ]
1018
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
1019
+ pub struct LpTim2OutPin < P > {
1020
+ pin : P ,
1021
+ }
1022
+
1023
+ impl < P > LpTim2OutPin < P > {
1024
+ fn free ( self ) -> P {
1025
+ self . pin
1026
+ }
1027
+ }
1028
+
1029
+ // TODO: move to LpTim trait when GATs are stablized
1030
+ impl LpTim2 {
1031
+ /// Setup a new output pin.
1032
+ #[ inline]
1033
+ pub fn new_output_pin < P : LpTim2Out > (
1034
+ & mut self ,
1035
+ mut pin : P ,
1036
+ cs : & CriticalSection ,
1037
+ ) -> LpTim2OutPin < P > {
1038
+ pin. set_lptim2_out_af ( cs) ;
1039
+ LpTim2OutPin { pin }
1040
+ }
1041
+
1042
+ /// Free the output pin previously created with
1043
+ /// [`new_output_pin`](Self::new_output_pin).
1044
+ #[ inline]
1045
+ pub fn free_output_pin < P : LpTim2Out > ( & mut self , pin : LpTim2OutPin < P > ) -> P {
1046
+ pin. free ( )
1047
+ }
1048
+ }
1049
+
1050
+ /// Low-power timer 3 output pin.
1051
+ ///
1052
+ /// Constructed with [`new_output_pin`](LpTim3::new_output_pin).
1053
+ #[ derive( Debug ) ]
1054
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
1055
+ pub struct LpTim3OutPin {
1056
+ pin : pins:: A1 ,
1057
+ }
1058
+
1059
+ impl LpTim3OutPin {
1060
+ fn free ( self ) -> pins:: A1 {
1061
+ self . pin
1062
+ }
1063
+ }
1064
+
1065
+ // TODO: move to LpTim trait when GATs are stablized
1066
+ impl LpTim3 {
1067
+ /// Setup a new output pin.
1068
+ #[ inline]
1069
+ pub fn new_output_pin ( & mut self , mut pin : pins:: A1 , cs : & CriticalSection ) -> LpTim3OutPin {
1070
+ pin. set_lptim3_out_af ( cs) ;
1071
+ LpTim3OutPin { pin }
1072
+ }
1073
+
1074
+ /// Free the output pin previously created with
1075
+ /// [`new_output_pin`](Self::new_output_pin).
1076
+ #[ inline]
1077
+ pub fn free_output_pin ( & mut self , pin : LpTim3OutPin ) -> pins:: A1 {
1078
+ pin. free ( )
1079
+ }
1080
+ }
0 commit comments