44#[ path = "../examples/utils/mod.rs" ]
55mod utils;
66
7- use utils:: logger:: println ;
7+ use utils:: logger:: debug ;
88
99use core:: ops:: FnMut ;
1010use core:: result:: Result ;
11- use fugit:: { ExtU32 , MicrosDurationU32 } ;
12- use hal:: delay:: { DelayExt , SystDelay } ;
11+ use fugit:: { ExtU32 , HertzU32 , MicrosDurationU32 } ;
12+ use hal:: delay:: DelayExt ;
1313use hal:: stm32;
1414use stm32g4xx_hal as hal;
1515
16+ pub const F_SYS : HertzU32 = HertzU32 :: MHz ( 16 ) ;
17+ pub const CYCLES_PER_US : u32 = F_SYS . raw ( ) / 1_000_000 ;
18+
19+ pub fn enable_timer ( cp : & mut stm32:: CorePeripherals ) {
20+ cp. DCB . enable_trace ( ) ;
21+ cp. DWT . enable_cycle_counter ( ) ;
22+ }
23+
24+ pub fn now ( ) -> MicrosDurationU32 {
25+ ( stm32:: DWT :: cycle_count ( ) / CYCLES_PER_US ) . micros ( )
26+ }
27+
1628#[ defmt_test:: tests]
1729mod tests {
1830 use embedded_hal:: {
31+ delay:: DelayNs ,
1932 digital:: { InputPin , OutputPin } ,
2033 pwm:: SetDutyCycle ,
2134 } ;
35+ use fixed:: types:: I1F15 ;
2236 use fugit:: RateExtU32 ;
2337 use stm32g4xx_hal:: {
38+ adc:: { self , AdcClaim , Temperature , Vref } ,
39+ cordic:: {
40+ op:: { dynamic:: Mode , Magnitude , SinCos , Sqrt } ,
41+ prec:: P60 ,
42+ scale:: N0 ,
43+ types:: { Q15 , Q31 } ,
44+ Ext ,
45+ } ,
46+ dac:: { DacExt , DacOut } ,
2447 delay:: SYSTDelayExt ,
2548 gpio:: { GpioExt , AF6 } ,
2649 pwm:: PwmExt ,
2750 rcc:: RccExt ,
51+ signature:: { VrefCal , VDDA_CALIB } ,
2852 stm32:: GPIOA ,
2953 } ;
3054
@@ -37,6 +61,7 @@ mod tests {
3761 let dp = unsafe { stm32:: Peripherals :: steal ( ) } ;
3862 let mut rcc = dp. RCC . constrain ( ) ;
3963 let mut delay = cp. SYST . delay ( & rcc. clocks ) ;
64+ defmt:: dbg!( rcc. clocks. sys_clk) ;
4065
4166 let gpioa = dp. GPIOA . split ( & mut rcc) ;
4267 let mut pin = gpioa. pa8 . into_push_pull_output ( ) ;
@@ -46,15 +71,15 @@ mod tests {
4671 assert ! ( pin. is_high( ) . unwrap( ) ) ;
4772 {
4873 let gpioa = unsafe { & * GPIOA :: PTR } ;
49- assert ! ( !is_pa8_low ( gpioa) ) ;
74+ assert ! ( !is_pax_low ( gpioa, 8 ) ) ;
5075 }
5176
5277 pin. set_low ( ) . unwrap ( ) ;
5378 delay. delay ( 1 . millis ( ) ) ; // Give the pin plenty of time to go low
5479 assert ! ( pin. is_low( ) . unwrap( ) ) ;
5580 {
5681 let gpioa = unsafe { & * GPIOA :: PTR } ;
57- assert ! ( is_pa8_low ( gpioa) ) ;
82+ assert ! ( is_pax_low ( gpioa, 8 ) ) ;
5883 }
5984 }
6085
@@ -82,15 +107,15 @@ mod tests {
82107 assert ! ( pin. is_high( ) . unwrap( ) ) ;
83108 {
84109 let gpioa = unsafe { & * GPIOA :: PTR } ;
85- assert ! ( !is_pa8_low ( gpioa) ) ;
110+ assert ! ( !is_pax_low ( gpioa, 8 ) ) ;
86111 }
87112
88113 pin. set_low ( ) . unwrap ( ) ;
89114 delay. delay ( 1 . millis ( ) ) ; // Give the pin plenty of time to go low
90115 assert ! ( pin. is_low( ) . unwrap( ) ) ;
91116 {
92117 let gpioa = unsafe { & * GPIOA :: PTR } ;
93- assert ! ( is_pa8_low ( gpioa) ) ;
118+ assert ! ( is_pax_low ( gpioa, 8 ) ) ;
94119 }
95120 }
96121
@@ -99,10 +124,12 @@ mod tests {
99124 use super :: * ;
100125
101126 // TODO: Is it ok to steal these?
102- let cp = unsafe { stm32:: CorePeripherals :: steal ( ) } ;
127+ let mut cp = unsafe { stm32:: CorePeripherals :: steal ( ) } ;
103128 let dp = unsafe { stm32:: Peripherals :: steal ( ) } ;
129+ enable_timer ( & mut cp) ;
130+
104131 let mut rcc = dp. RCC . constrain ( ) ;
105- let mut delay = cp . SYST . delay ( & rcc. clocks ) ;
132+ assert_eq ! ( rcc. clocks. sys_clk , F_SYS ) ;
106133
107134 let gpioa = dp. GPIOA . split ( & mut rcc) ;
108135 let pin: stm32g4xx_hal:: gpio:: gpioa:: PA8 < stm32g4xx_hal:: gpio:: Alternate < AF6 > > =
@@ -115,75 +142,195 @@ mod tests {
115142
116143 let gpioa = unsafe { & * GPIOA :: PTR } ;
117144
118- //let get_pin_state = || unsafe { (0x4800_0004 as *const u32).read_volatile() };
119-
120- // TODO: This is a very bad way to measure time
121- let min: MicrosDurationU32 = 490u32 . micros ( ) ; // Some extra on min for cpu overhead
145+ let min: MicrosDurationU32 = 495u32 . micros ( ) ;
122146 let max: MicrosDurationU32 = 505u32 . micros ( ) ;
123147
124- {
125- println ! ( "Awaiting first rising edge..." ) ;
126- let duration_until_lo = await_lo ( & gpioa, & mut delay, max) . unwrap ( ) ;
127- println ! ( "Low..., Waited ~{} until low" , duration_until_lo) ;
128- let lo_duration = await_hi ( & gpioa, & mut delay, max) . unwrap ( ) ;
129- println ! ( "High..., Low half period: {}" , lo_duration) ;
130- }
148+ debug ! ( "Awaiting first rising edge..." ) ;
149+ let duration_until_lo = await_lo ( & gpioa, max) . unwrap ( ) ;
150+ let first_lo_duration = await_hi ( & gpioa, max) . unwrap ( ) ;
151+
152+ let mut hi_duration = 0 . micros ( ) ;
153+ let mut lo_duration = 0 . micros ( ) ;
131154
132155 for _ in 0 ..10 {
133- // Make sure the timer half periods are within 490-505us
156+ // Make sure the timer half periods are within 495-505us
157+
158+ hi_duration = await_lo ( & gpioa, max) . unwrap ( ) ;
159+ assert ! (
160+ hi_duration > min && hi_duration < max,
161+ "hi: {} < {} < {}" ,
162+ min,
163+ hi_duration,
164+ max
165+ ) ;
166+
167+ lo_duration = await_hi ( & gpioa, max) . unwrap ( ) ;
168+ assert ! (
169+ lo_duration > min && lo_duration < max,
170+ "lo: {} < {} < {}" ,
171+ min,
172+ lo_duration,
173+ max
174+ ) ;
175+ }
176+
177+ // Prints deferred until here to not mess up timing
178+ debug ! ( "Waited ~{} until low" , duration_until_lo) ;
179+ debug ! ( "First low half period: {}" , first_lo_duration) ;
134180
135- let hi_duration = await_lo ( & gpioa, & mut delay, max) . unwrap ( ) ;
136- println ! ( "Low..., High half period: {}" , hi_duration) ;
137- assert ! ( hi_duration > min, "{} > {}" , hi_duration, min) ;
181+ debug ! ( "High half period: {}" , hi_duration) ;
182+ debug ! ( "Low half period: {}" , lo_duration) ;
138183
139- let lo_duration = await_hi ( & gpioa, & mut delay, max) . unwrap ( ) ;
140- println ! ( "High..., Low half period: {}" , lo_duration) ;
141- assert ! ( lo_duration > min, "{} > {}" , lo_duration, min) ;
184+ debug ! ( "Done!" ) ;
185+
186+ pwm. disable ( ) ;
187+ }
188+
189+ #[ test]
190+ fn cordic ( ) {
191+ fn is_almost_equals ( a : f32 , b : f32 ) -> bool {
192+ ( a - b) . abs ( ) < 0.001
142193 }
143194
144- println ! ( "Done!" ) ;
145- for i in ( 0 ..5 ) . rev ( ) {
146- println ! ( "{}" , i) ;
147- delay. delay ( 1000 . millis ( ) ) ;
195+ use super :: * ;
196+
197+ let dp = unsafe { stm32:: Peripherals :: steal ( ) } ;
198+ let mut rcc = dp. RCC . constrain ( ) ;
199+
200+ let mut cordic = dp
201+ . CORDIC
202+ . constrain ( & mut rcc)
203+ . freeze :: < Q15 , Q31 , P60 , SinCos > ( ) ; // 16 bit arguments, 32 bit results, compute sine and cosine, 60 iterations
204+
205+ // static operation (zero overhead)
206+
207+ cordic. start ( I1F15 :: from_num ( -0.25 /* -45 degreees */ ) ) ;
208+
209+ let ( sin, cos) = cordic. result ( ) ;
210+
211+ debug ! ( "sin: {}, cos: {}" , sin. to_num:: <f32 >( ) , cos. to_num:: <f32 >( ) ) ;
212+ assert ! ( is_almost_equals( sin. to_num:: <f32 >( ) , -0.707 ) ) ;
213+ assert ! ( is_almost_equals( cos. to_num:: <f32 >( ) , 0.707 ) ) ;
214+
215+ // dynamic operation
216+
217+ let mut cordic = cordic. into_dynamic ( ) ;
218+
219+ let sqrt = cordic. run :: < Sqrt < N0 > > ( I1F15 :: from_num ( 0.25 ) ) ;
220+ debug ! ( "sqrt: {}" , sqrt. to_num:: <f32 >( ) ) ;
221+ assert ! ( is_almost_equals( sqrt. to_num:: <f32 >( ) , 0.5 ) ) ;
222+ let magnitude = cordic. run :: < Magnitude > ( ( I1F15 :: from_num ( 0.25 ) , I1F15 :: from_num ( 0.5 ) ) ) ;
223+ debug ! ( "magnitude: {}" , magnitude. to_num:: <f32 >( ) ) ;
224+ assert ! ( is_almost_equals( magnitude. to_num:: <f32 >( ) , 0.559 ) ) ;
225+ }
226+
227+ #[ test]
228+ fn adc ( ) {
229+ use super :: * ;
230+
231+ // TODO: Is it ok to steal these?
232+ let cp = unsafe { stm32:: CorePeripherals :: steal ( ) } ;
233+ let dp = unsafe { stm32:: Peripherals :: steal ( ) } ;
234+ let rcc = dp. RCC . constrain ( ) ;
235+ let mut delay = cp. SYST . delay ( & rcc. clocks ) ;
236+
237+ let mut adc = dp
238+ . ADC1
239+ . claim ( adc:: ClockSource :: SystemClock , & rcc, & mut delay, true ) ;
240+
241+ adc. enable_temperature ( & dp. ADC12_COMMON ) ;
242+ adc. enable_vref ( & dp. ADC12_COMMON ) ;
243+ let sample_time = adc:: config:: SampleTime :: Cycles_640_5 ;
244+
245+ let vref = adc. convert ( & Vref , sample_time) ;
246+ let vref_cal = VrefCal :: get ( ) . read ( ) ;
247+ let vdda = VDDA_CALIB * vref_cal as u32 / vref as u32 ;
248+ debug ! ( "vdda: {}mV" , vdda) ;
249+ assert ! ( ( 3200 ..3400 ) . contains( & vdda) ) ;
250+
251+ let vref = Vref :: sample_to_millivolts_ext ( vref, vdda, adc:: config:: Resolution :: Twelve ) ;
252+ debug ! ( "vref: {}mV" , vref) ;
253+ assert ! ( ( 1182 ..1232 ) . contains( & vref) ) ; // From G474 datasheet
254+
255+ let temperature_reading = adc. convert ( & Temperature , sample_time) ;
256+ let temp = Temperature :: temperature_to_degrees_centigrade (
257+ temperature_reading,
258+ vdda as f32 / 1000. ,
259+ adc:: config:: Resolution :: Twelve ,
260+ ) ;
261+ debug ! ( "temp: {}°C" , temp) ;
262+ assert ! ( ( 20.0 ..30.0 ) . contains( & temp) , "20.0 < {} < 30.0" , temp) ;
263+ }
264+
265+ // TODO: This does not seem to work
266+ #[ test]
267+ fn dac ( ) {
268+ use super :: * ;
269+
270+ // TODO: Is it ok to steal these?
271+ let cp = unsafe { stm32:: CorePeripherals :: steal ( ) } ;
272+ let dp = unsafe { stm32:: Peripherals :: steal ( ) } ;
273+ let mut rcc = dp. RCC . constrain ( ) ;
274+ let mut delay = cp. SYST . delay ( & rcc. clocks ) ;
275+
276+ let gpioa = dp. GPIOA . split ( & mut rcc) ;
277+ let dac1ch1 = dp. DAC1 . constrain ( gpioa. pa4 , & mut rcc) ;
278+
279+ let gpioa = unsafe { & * GPIOA :: PTR } ;
280+
281+ // dac_manual will have its value set manually
282+ let mut dac = dac1ch1. calibrate_buffer ( & mut delay) . enable ( ) ;
283+
284+ dac. set_value ( 0 ) ;
285+ delay. delay_ms ( 100 ) ;
286+ assert ! ( is_pax_low( & gpioa, 4 ) ) ;
287+
288+ /*for i in (0..=4095).step_by(10) {
289+ dac.set_value(i);
290+ delay.delay_ms(1);
291+ defmt::println!("i: {}, is_pax_low: {}", i, gpioa.idr().read().bits());
148292 }
149293
150- pwm. disable ( ) ;
294+ delay.delay_ms(100);
295+ assert!(!is_pax_low(&gpioa, 4)); // TODO: <---- Why does this not work?
296+ */
151297 }
152298}
153299
154- fn is_pa8_low ( gpioa : & stm32:: gpioa:: RegisterBlock ) -> bool {
155- gpioa. idr ( ) . read ( ) . idr ( 8 ) . is_low ( )
300+ fn is_pax_low ( gpioa : & stm32:: gpioa:: RegisterBlock , x : u8 ) -> bool {
301+ gpioa. idr ( ) . read ( ) . idr ( x ) . is_low ( )
156302}
157303
158304#[ derive( Debug , defmt:: Format ) ]
159305struct ErrorTimedOut ;
160306
161307fn await_lo (
162308 gpioa : & stm32:: gpioa:: RegisterBlock ,
163- delay : & mut SystDelay ,
164309 timeout : MicrosDurationU32 ,
165310) -> Result < MicrosDurationU32 , ErrorTimedOut > {
166- await_p ( || is_pa8_low ( gpioa) , delay , timeout)
311+ await_p ( || is_pax_low ( gpioa, 8 ) , timeout)
167312}
168313
169314fn await_hi (
170315 gpioa : & stm32:: gpioa:: RegisterBlock ,
171- delay : & mut SystDelay ,
172316 timeout : MicrosDurationU32 ,
173317) -> Result < MicrosDurationU32 , ErrorTimedOut > {
174- await_p ( || !is_pa8_low ( gpioa) , delay , timeout)
318+ await_p ( || !is_pax_low ( gpioa, 8 ) , timeout)
175319}
176320
177321fn await_p (
178322 mut p : impl FnMut ( ) -> bool ,
179- delay : & mut SystDelay ,
180323 timeout : MicrosDurationU32 ,
181324) -> Result < MicrosDurationU32 , ErrorTimedOut > {
182- for i in 0 ..timeout. ticks ( ) {
325+ let before = now ( ) ;
326+
327+ loop {
328+ let passed_time = now ( ) - before;
183329 if p ( ) {
184- return Ok ( i. micros ( ) ) ;
330+ return Ok ( passed_time) ;
331+ }
332+ if passed_time > timeout {
333+ return Err ( ErrorTimedOut ) ;
185334 }
186- delay. delay ( 1_u32 . micros ( ) ) ;
187335 }
188- Err ( ErrorTimedOut )
189336}
0 commit comments