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