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`](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,87 @@ 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 :: PLL2_P ) => clocks. pll2_p_ck ( ) ,
300
+ Val ( rec:: AdcClkSel :: PLL3_R ) => clocks. pll3_r_ck ( ) ,
301
+ Val ( rec:: AdcClkSel :: PER ) => clocks. per_ck ( ) ,
302
+ _ => unreachable ! ( ) ,
303
+ }
304
+ . expect ( "adc_ker_ck_input is not running!" ) ;
305
+
306
+ // Check against datasheet requirements
307
+ assert ! (
308
+ adc_clock. 0 <= ADC_KER_CK_MAX ,
309
+ "adc_ker_ck_input is too fast"
310
+ ) ;
311
+
312
+ adc_clock
313
+ }
314
+
315
+ // ADC12 is a unique case where a single reset line is used to control two
316
+ // peripherals that have separate peripheral definitons in the SVD.
317
+
318
+ /// Initialise ADC12 together
319
+ ///
320
+ /// Sets all configurable parameters to one-shot defaults,
321
+ /// performs a boot-time calibration.
322
+ pub fn adc12 (
323
+ adc1 : ADC1 ,
324
+ adc2 : ADC2 ,
325
+ delay : & mut Delay ,
326
+ prec : rec:: Adc12 ,
327
+ clocks : & CoreClocks ,
328
+ ) -> ( Adc < ADC1 , Disabled > , Adc < ADC2 , Disabled > ) {
329
+ // Consume ADC register block, produce ADC1/2 with default settings
330
+ let mut adc1 = Adc :: < ADC1 , Disabled > :: default_from_rb ( adc1) ;
331
+ let mut adc2 = Adc :: < ADC2 , Disabled > :: default_from_rb ( adc2) ;
332
+
333
+ // Check adc_ker_ck_input
334
+ check_clock ( & prec, clocks) ;
335
+
336
+ // Enable AHB clock
337
+ let prec = prec. enable ( ) ;
338
+
339
+ // Power Down
340
+ adc1. power_down ( ) ;
341
+ adc2. power_down ( ) ;
342
+
343
+ // Reset peripheral
344
+ prec. reset ( ) ;
345
+
346
+ // Power Up, Preconfigure and Calibrate
347
+ adc1. power_up ( delay) ;
348
+ adc2. power_up ( delay) ;
349
+ adc1. preconfigure ( ) ;
350
+ adc2. preconfigure ( ) ;
351
+ adc1. calibrate ( ) ;
352
+ adc2. calibrate ( ) ;
353
+
354
+ ( adc1, adc2)
355
+ }
356
+
357
+ /// Freeing both the periperhal and PREC is possible for ADC3
358
+ impl < ED > Adc < ADC3 , ED > {
359
+ /// Releases the ADC peripheral
360
+ pub fn free ( self ) -> ( ADC3 , rec:: Adc3 ) {
361
+ (
362
+ self . rb ,
363
+ rec:: Adc3 {
364
+ _marker : PhantomData ,
365
+ } ,
366
+ )
367
+ }
368
+ }
369
+
290
370
#[ allow( unused_macros) ]
291
371
macro_rules! adc_hal {
292
372
( $(
293
373
$ADC: ident: (
294
374
$adcX: ident,
295
- $Rec: ident,
296
- $COMMON: ident
375
+ $Rec: ident
297
376
)
298
377
) ,+ $( , ) * ) => {
299
378
$(
@@ -317,46 +396,39 @@ macro_rules! adc_hal {
317
396
pub fn $adcX( adc: $ADC, delay: & mut Delay ,
318
397
prec: rec:: $Rec, clocks: & CoreClocks
319
398
) -> 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
- } ;
399
+ // Consume ADC register block, produce Self with default
400
+ // settings
401
+ let mut adc = Self :: default_from_rb( adc) ;
327
402
328
- // Select Kernel Clock
329
- s. enable_clock(
330
- clocks. per_ck( ) . expect( "per_ck is not running!" ) . 0
331
- ) ;
403
+ // Check adc_ker_ck_input
404
+ check_clock( & prec, clocks) ;
332
405
333
406
// Enable AHB clock
334
407
let prec = prec. enable( ) ;
335
408
336
409
// Power Down
337
- s . power_down( ) ;
410
+ adc . power_down( ) ;
338
411
339
- // Reset periperal
412
+ // Reset peripheral
340
413
prec. reset( ) ;
341
414
342
415
// Power Up, Preconfigure and Calibrate
343
- s . power_up( delay) ;
344
- s . preconfigure( ) ;
345
- s . calibrate( ) ;
416
+ adc . power_up( delay) ;
417
+ adc . preconfigure( ) ;
418
+ adc . calibrate( ) ;
346
419
347
- s
420
+ adc
348
421
}
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 ) } ) ;
422
+ /// Creates ADC with default settings
423
+ fn default_from_rb ( rb : $ADC ) -> Self {
424
+ Self {
425
+ rb ,
426
+ sample_time : AdcSampleTime :: default ( ) ,
427
+ resolution : Resolution :: SIXTEENBIT ,
428
+ lshift : AdcLshift :: default ( ) ,
429
+ _enabled : PhantomData ,
430
+ }
358
431
}
359
-
360
432
/// Disables Deeppowerdown-mode and enables voltage regulator
361
433
///
362
434
/// Note: After power-up, a [`calibration`](#method.calibrate) shall be run
@@ -571,12 +643,6 @@ macro_rules! adc_hal {
571
643
}
572
644
573
645
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
646
/// Save current ADC config
581
647
pub fn save_cfg( & mut self ) -> StoredConfig {
582
648
StoredConfig ( self . get_sample_time( ) , self . get_resolution( ) , self . get_lshift( ) )
@@ -714,7 +780,7 @@ macro_rules! adc_hal {
714
780
}
715
781
716
782
adc_hal ! (
717
- ADC1 : ( adc1, Adc12 , ADC12_COMMON ) ,
718
- ADC2 : ( adc2, Adc12 , ADC12_COMMON ) ,
719
- ADC3 : ( adc3, Adc3 , ADC3_COMMON ) ,
783
+ ADC1 : ( adc1, Adc12 ) , // ADC1
784
+ ADC2 : ( adc2, Adc12 ) , // ADC2
785
+ ADC3 : ( adc3, Adc3 ) , // ADC3
720
786
) ;
0 commit comments