37
37
use cast:: u32;
38
38
use cortex_m:: peripheral:: syst:: SystClkSource ;
39
39
use cortex_m:: peripheral:: SYST ;
40
-
41
- use crate :: nb:: block;
42
- use crate :: rcc:: CoreClocks ;
43
- use crate :: time:: { Hertz , U32Ext } ;
44
40
use embedded_hal:: {
45
41
blocking:: delay:: { DelayMs , DelayUs } ,
46
42
timer:: CountDown ,
47
43
} ;
44
+ use void:: Void ;
45
+
46
+ use crate :: nb:: block;
47
+ use crate :: rcc:: CoreClocks ;
48
+ use crate :: time:: { Hertz , U32Ext } ;
48
49
49
50
pub trait DelayExt {
50
51
fn delay ( self , clocks : CoreClocks ) -> Delay ;
@@ -62,6 +63,89 @@ pub struct Delay {
62
63
syst : SYST ,
63
64
}
64
65
66
+ /// Implements [CountDown](embedded_hal::timer::CountDown) for the System timer (SysTick).
67
+ /// Time is measured in microseconds
68
+ pub struct CountdownUs < ' a > {
69
+ clocks : CoreClocks ,
70
+ syst : & ' a mut SYST ,
71
+ total_rvr : u64 ,
72
+ finished : bool ,
73
+ }
74
+
75
+ impl < ' a > CountdownUs < ' a > {
76
+ /// Create a new [CountDown] measured in microseconds.
77
+ pub fn new ( syst : & ' a mut SYST , clocks : CoreClocks ) -> Self {
78
+ Self {
79
+ syst,
80
+ clocks,
81
+ total_rvr : 0 ,
82
+ finished : true ,
83
+ }
84
+ }
85
+
86
+ /// start a wait cycle and sets finished to true if [CountdownUs] is done waiting.
87
+ fn start_wait ( & mut self ) {
88
+ // The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
89
+ const MAX_RVR : u32 = 0x00FF_FFFF ;
90
+
91
+ if self . total_rvr != 0 {
92
+ self . finished = false ;
93
+ let current_rvr = if self . total_rvr <= MAX_RVR . into ( ) {
94
+ self . total_rvr as u32
95
+ } else {
96
+ MAX_RVR
97
+ } ;
98
+
99
+ self . syst . set_reload ( current_rvr) ;
100
+ self . syst . clear_current ( ) ;
101
+ self . syst . enable_counter ( ) ;
102
+
103
+ self . total_rvr -= current_rvr as u64 ;
104
+ } else {
105
+ self . finished = true ;
106
+ }
107
+ }
108
+ }
109
+
110
+ impl < ' a > CountDown for CountdownUs < ' a > {
111
+ type Time = u32 ;
112
+
113
+ fn start < T > ( & mut self , count : T )
114
+ where
115
+ T : Into < Self :: Time > ,
116
+ {
117
+ let us = count. into ( ) ;
118
+
119
+ // With c_ck up to 480e6, we need u64 for delays > 8.9s
120
+
121
+ self . total_rvr = if cfg ! ( not( feature = "revision_v" ) ) {
122
+ // See errata ES0392 §2.2.3. Revision Y does not have the /8 divider
123
+ u64:: from ( us) * u64:: from ( self . clocks . c_ck ( ) . 0 / 1_000_000 )
124
+ } else if cfg ! ( feature = "cm4" ) {
125
+ // CM4 dervived from HCLK
126
+ u64:: from ( us) * u64:: from ( self . clocks . hclk ( ) . 0 / 8_000_000 )
127
+ } else {
128
+ // Normally divide by 8
129
+ u64:: from ( us) * u64:: from ( self . clocks . c_ck ( ) . 0 / 8_000_000 )
130
+ } ;
131
+
132
+ self . start_wait ( ) ;
133
+ }
134
+
135
+ fn wait ( & mut self ) -> nb:: Result < ( ) , Void > {
136
+ if self . finished {
137
+ return Ok ( ( ) ) ;
138
+ }
139
+
140
+ if self . syst . has_wrapped ( ) {
141
+ self . syst . disable_counter ( ) ;
142
+ self . start_wait ( ) ;
143
+ }
144
+
145
+ Err ( nb:: Error :: WouldBlock )
146
+ }
147
+ }
148
+
65
149
impl Delay {
66
150
/// Configures the system timer (SysTick) as a delay provider
67
151
pub fn new ( mut syst : SYST , clocks : CoreClocks ) -> Self {
0 commit comments