1
1
//! Analog to Digital Converter (ADC)
2
+ //!
3
+ //! ADC1 and ADC2 share a reset line. To initialise both of them, use the
4
+ //! `adc12` method.
2
5
3
6
use crate :: hal:: adc:: { Channel , OneShot } ;
4
7
use crate :: hal:: blocking:: delay:: DelayUs ;
5
8
6
9
use core:: marker:: PhantomData ;
7
10
8
- use crate :: stm32;
9
11
use crate :: stm32:: { ADC1 , ADC2 , ADC3 , ADC3_COMMON } ;
10
12
11
13
use crate :: delay:: Delay ;
@@ -17,7 +19,10 @@ use crate::gpio::gpiof::{
17
19
} ;
18
20
use crate :: gpio:: gpioh:: { PH2 , PH3 , PH4 , PH5 } ;
19
21
use crate :: gpio:: Analog ;
22
+ use crate :: rcc:: rec:: AdcClkSelGetter ;
20
23
use crate :: rcc:: { rec, CoreClocks , ResetEnable } ;
24
+ use crate :: time:: Hertz ;
25
+ use stm32h7:: Variant :: Val ;
21
26
22
27
#[ cfg( not( feature = "revision_v" ) ) ]
23
28
const ADC_KER_CK_MAX : u32 = 36_000_000 ;
@@ -287,13 +292,84 @@ pub trait AdcExt<ADC>: Sized {
287
292
#[ derive( Copy , Clone , Debug , PartialEq ) ]
288
293
pub struct StoredConfig ( AdcSampleTime , Resolution , AdcLshift ) ;
289
294
295
+ /// Get and check the adc_ker_ck_input
296
+ fn check_clock ( prec : & impl AdcClkSelGetter , clocks : & CoreClocks ) -> Hertz {
297
+ // Select Kernel Clock
298
+ let adc_clock = match prec. get_kernel_clk_mux ( ) {
299
+ Val ( rec:: AdcClkSel :: PER ) => clocks. per_ck ( ) ,
300
+ _ => unreachable ! ( ) ,
301
+ }
302
+ . expect ( "adc_ker_ck_input is not running!" ) ;
303
+
304
+ // Check against datasheet requirements
305
+ assert ! (
306
+ adc_clock. 0 <= ADC_KER_CK_MAX ,
307
+ "adc_ker_ck_input is too fast"
308
+ ) ;
309
+
310
+ adc_clock
311
+ }
312
+
313
+ // ADC12 is a unique case where a single reset line is used to control two
314
+ // peripherals that have separate peripheral definitons in the SVD.
315
+
316
+ /// Initialise ADC12 together
317
+ ///
318
+ /// Sets all configurable parameters to one-shot defaults,
319
+ /// performs a boot-time calibration.
320
+ pub fn adc12 (
321
+ adc1 : ADC1 ,
322
+ adc2 : ADC2 ,
323
+ delay : & mut Delay ,
324
+ prec : rec:: Adc12 ,
325
+ clocks : & CoreClocks ,
326
+ ) -> ( Adc < ADC1 , Disabled > , Adc < ADC2 , Disabled > ) {
327
+ let mut a1 = Adc :: < ADC1 , Disabled > :: default_from_rb ( adc1) ;
328
+ let mut a2 = Adc :: < ADC2 , Disabled > :: default_from_rb ( adc2) ;
329
+
330
+ // Check adc_ker_ck_input
331
+ check_clock ( & prec, clocks) ;
332
+
333
+ // Enable AHB clock
334
+ let prec = prec. enable ( ) ;
335
+
336
+ // Power Down
337
+ a1. power_down ( ) ;
338
+ a2. power_down ( ) ;
339
+
340
+ // Reset peripheral
341
+ prec. reset ( ) ;
342
+
343
+ // Power Up, Preconfigure and Calibrate
344
+ a1. power_up ( delay) ;
345
+ a2. power_up ( delay) ;
346
+ a1. preconfigure ( ) ;
347
+ a2. preconfigure ( ) ;
348
+ a1. calibrate ( ) ;
349
+ a2. calibrate ( ) ;
350
+
351
+ ( a1, a2)
352
+ }
353
+
354
+ /// Freeing both the periperhal and PREC is possible for ADC3
355
+ impl < ED > Adc < ADC3 , ED > {
356
+ /// Releases the ADC peripheral
357
+ pub fn free ( self ) -> ( ADC3 , rec:: Adc3 ) {
358
+ (
359
+ self . rb ,
360
+ rec:: Adc3 {
361
+ _marker : PhantomData ,
362
+ } ,
363
+ )
364
+ }
365
+ }
366
+
290
367
#[ allow( unused_macros) ]
291
368
macro_rules! adc_hal {
292
369
( $(
293
370
$ADC: ident: (
294
371
$adcX: ident,
295
- $Rec: ident,
296
- $COMMON: ident
372
+ $Rec: ident
297
373
)
298
374
) ,+ $( , ) * ) => {
299
375
$(
@@ -317,46 +393,37 @@ macro_rules! adc_hal {
317
393
pub fn $adcX( adc: $ADC, delay: & mut Delay ,
318
394
prec: rec:: $Rec, clocks: & CoreClocks
319
395
) -> Self {
320
- let mut s = Self {
321
- rb: adc,
322
- sample_time: AdcSampleTime :: default ( ) ,
323
- resolution: Resolution :: SIXTEENBIT ,
324
- lshift: AdcLshift :: default ( ) ,
325
- _enabled: PhantomData ,
326
- } ;
396
+ let mut a = Self :: default_from_rb( adc) ;
327
397
328
- // Select Kernel Clock
329
- s. enable_clock(
330
- clocks. per_ck( ) . expect( "per_ck is not running!" ) . 0
331
- ) ;
398
+ // Check adc_ker_ck_input
399
+ check_clock( & prec, clocks) ;
332
400
333
401
// Enable AHB clock
334
402
let prec = prec. enable( ) ;
335
403
336
404
// Power Down
337
- s . power_down( ) ;
405
+ a . power_down( ) ;
338
406
339
- // Reset periperal
407
+ // Reset peripheral
340
408
prec. reset( ) ;
341
409
342
410
// Power Up, Preconfigure and Calibrate
343
- s . power_up( delay) ;
344
- s . preconfigure( ) ;
345
- s . calibrate( ) ;
411
+ a . power_up( delay) ;
412
+ a . preconfigure( ) ;
413
+ a . calibrate( ) ;
346
414
347
- s
415
+ a
348
416
}
349
-
350
- fn enable_clock ( & mut self , per_ck : u32 ) {
351
- // Set per_ck as adc clock, TODO: we might want to
352
- // change this so we can also use other clocks as
353
- // input for this
354
- assert! ( per_ck <= ADC_KER_CK_MAX , "per_ck is not running or too fast" ) ;
355
- let d3ccipr = & unsafe { & * stm32 :: RCC :: ptr ( ) } . d3ccipr ;
356
-
357
- d3ccipr . modify ( |_ , w| unsafe { w . adcsel ( ) . bits ( 0b10 ) } ) ;
417
+ /// Creates ADC with default settings
418
+ fn default_from_rb ( rb : $ADC ) -> Self {
419
+ Self {
420
+ rb ,
421
+ sample_time : AdcSampleTime :: default ( ) ,
422
+ resolution : Resolution :: SIXTEENBIT ,
423
+ lshift : AdcLshift :: default ( ) ,
424
+ _enabled : PhantomData ,
425
+ }
358
426
}
359
-
360
427
/// Disables Deeppowerdown-mode and enables voltage regulator
361
428
///
362
429
/// Note: After power-up, a [`calibration`](#method.calibrate) shall be run
@@ -571,12 +638,6 @@ macro_rules! adc_hal {
571
638
}
572
639
573
640
impl <ED > Adc <$ADC, ED > {
574
-
575
- /// Releases the ADC peripheral
576
- pub fn free( self ) -> ( $ADC, rec:: $Rec) {
577
- ( self . rb, rec:: $Rec { _marker: PhantomData } )
578
- }
579
-
580
641
/// Save current ADC config
581
642
pub fn save_cfg( & mut self ) -> StoredConfig {
582
643
StoredConfig ( self . get_sample_time( ) , self . get_resolution( ) , self . get_lshift( ) )
@@ -714,7 +775,7 @@ macro_rules! adc_hal {
714
775
}
715
776
716
777
adc_hal ! (
717
- ADC1 : ( adc1, Adc12 , ADC12_COMMON ) ,
718
- ADC2 : ( adc2, Adc12 , ADC12_COMMON ) ,
719
- ADC3 : ( adc3, Adc3 , ADC3_COMMON ) ,
778
+ ADC1 : ( adc1, Adc12 ) , // ADC1
779
+ ADC2 : ( adc2, Adc12 ) , // ADC2
780
+ ADC3 : ( adc3, Adc3 ) , // ADC3
720
781
) ;
0 commit comments