48
48
#elif defined(STM32G4 )
49
49
#define ADC_STAB_DELAY_US (20)
50
50
#elif defined(STM32H5 )
51
- #define ADC_STAB_DELAY_US (1) // TODO: Check if this is enough
51
+ // Stabilization delay = 1 conversion cycle
52
+ // ADC clk = PDIV / 16 = 250 MHz / 16 = 15.625 MHz -> 64 ns -> select 1 us
53
+ #define ADC_STAB_DELAY_US (1)
52
54
#elif defined(STM32L4 )
53
55
#define ADC_STAB_DELAY_US (10)
54
56
#elif defined(STM32WB )
61
63
#elif defined(STM32F4 ) || defined(STM32F7 )
62
64
#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_15CYCLES
63
65
#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_480CYCLES
64
- #elif defined(STM32G4 ) || defined( STM32H5 )
66
+ #elif defined(STM32G4 )
65
67
#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5
66
68
#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_247CYCLES_5
69
+ #elif defined(STM32H5 )
70
+ // Worst case sampling time: slow channel, 12 bits, 680 ohms -> 165 ns
71
+ // ADC clk = PDIV / 16 = 250 MHz / 16 = 15.625 MHz -> 64 ns -> 2.57 cycles -> select 6.5 cycles
72
+ #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_6CYCLES_5
73
+ #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_247CYCLES_5
67
74
#elif defined(STM32H7 )
68
75
#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_8CYCLES_5
69
76
#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_387CYCLES_5
81
88
// Timeout for waiting for end-of-conversion
82
89
#define ADC_EOC_TIMEOUT_MS (10)
83
90
84
- // This is a synthesised channel representing the maximum ADC reading (useful to scale other channels)
85
- #define ADC_CHANNEL_VREF (0xffff)
91
+ // Channel IDs for machine.ADC object
92
+ typedef enum _machine_adc_internal_ch_t {
93
+ // Regular external ADC inputs (0..19)
94
+ MACHINE_ADC_EXT_CH_0 = 0 ,
95
+ MACHINE_ADC_EXT_CH_19 = 19 ,
96
+
97
+ // Internal ADC channels (256..)
98
+ MACHINE_ADC_INT_CH_VREFINT = 256 ,
99
+ MACHINE_ADC_INT_CH_TEMPSENSOR ,
100
+ #if defined(ADC_CHANNEL_VBAT )
101
+ MACHINE_ADC_INT_CH_VBAT ,
102
+ #endif
103
+ #if defined(ADC_CHANNEL_VDDCORE )
104
+ MACHINE_ADC_INT_CH_VDDCORE ,
105
+ #endif
106
+
107
+ // This is a synthesised channel representing the maximum ADC reading (useful to scale other channels)
108
+ MACHINE_ADC_CH_VREF = 0xffff // 0xffff for backward compatibility
109
+ } machine_adc_internal_ch_t ;
110
+
111
+ // Convert machine_adc_internal_ch_t value to STM32 library ADC channel literal.
112
+ // This function is required as literals are uint32_t types that don't map with MP_ROM_INT (31 bit signed).
113
+ STATIC uint32_t adc_ll_channel (uint32_t channel_id ) {
114
+ uint32_t adc_ll_ch ;
115
+ switch (channel_id ) {
116
+ // external channels map 1:1
117
+ case MACHINE_ADC_EXT_CH_0 ... MACHINE_ADC_EXT_CH_19 :
118
+ adc_ll_ch = channel_id ;
119
+ break ;
120
+
121
+ // internal channels are converted to STM32 ADC defines
122
+ case MACHINE_ADC_INT_CH_VREFINT :
123
+ adc_ll_ch = ADC_CHANNEL_VREFINT ;
124
+ break ;
125
+ case MACHINE_ADC_INT_CH_TEMPSENSOR :
126
+ #if defined(STM32G4 )
127
+ adc_ll_ch = ADC_CHANNEL_TEMPSENSOR_ADC1 ;
128
+ #else
129
+ adc_ll_ch = ADC_CHANNEL_TEMPSENSOR ;
130
+ #endif
131
+ break ;
132
+ #if defined(ADC_CHANNEL_VBAT )
133
+ case MACHINE_ADC_INT_CH_VBAT :
134
+ adc_ll_ch = ADC_CHANNEL_VBAT ;
135
+ break ;
136
+ #endif
137
+ #if defined(ADC_CHANNEL_VDDCORE )
138
+ case MACHINE_ADC_INT_CH_VDDCORE :
139
+ adc_ll_ch = ADC_CHANNEL_VDDCORE ;
140
+ break ;
141
+ #endif
142
+
143
+ // To save code memory for costly error handling, default to Vref for unknown channels
144
+ default :
145
+ adc_ll_ch = ADC_CHANNEL_VREFINT ;
146
+ break ;
147
+ };
148
+ return adc_ll_ch ;
149
+ }
86
150
87
151
static inline void adc_stabilisation_delay_us (uint32_t us ) {
88
152
mp_hal_delay_us (us + 1 );
@@ -150,9 +214,9 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) {
150
214
adc -> CFGR2 = 2 << ADC_CFGR2_CKMODE_Pos ; // PCLK/4 (synchronous clock mode)
151
215
#elif defined(STM32F4 ) || defined(STM32F7 ) || defined(STM32L4 )
152
216
ADCx_COMMON -> CCR = 0 ; // ADCPR=PCLK/2
153
- #elif defined(STM32G4 )
217
+ #elif defined(STM32G4 ) || defined( STM32H5 )
154
218
ADC12_COMMON -> CCR = 7 << ADC_CCR_PRESC_Pos ; // PCLK/16 (asynchronous clock mode)
155
- #elif defined(STM32H5 ) || defined( STM32H7A3xx ) || defined(STM32H7A3xxQ ) || defined(STM32H7B3xx ) || defined(STM32H7B3xxQ )
219
+ #elif defined(STM32H7A3xx ) || defined(STM32H7A3xxQ ) || defined(STM32H7B3xx ) || defined(STM32H7B3xxQ )
156
220
ADC12_COMMON -> CCR = 3 << ADC_CCR_CKMODE_Pos ;
157
221
#elif defined(STM32H7 )
158
222
ADC12_COMMON -> CCR = 3 << ADC_CCR_CKMODE_Pos ;
@@ -352,9 +416,16 @@ STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t samp
352
416
#else
353
417
adc_common -> CCR |= ADC_CCR_VBATEN ;
354
418
#endif
419
+ #if defined(STM32H5 )
420
+ } else if (channel == ADC_CHANNEL_VDDCORE ) {
421
+ adc -> OR |= ADC_OR_OP0 ; // Enable Vddcore channel on ADC2
422
+ #endif
423
+ }
424
+ #if defined(STM32G4 ) || defined(STM32H5 )
425
+ // G4 and H5 use encoded literals for internal channels -> extract ADC channel for following code
426
+ if (__LL_ADC_IS_CHANNEL_INTERNAL (channel )) {
427
+ channel = __LL_ADC_CHANNEL_TO_DECIMAL_NB (channel );
355
428
}
356
- #if defined(STM32G4 )
357
- channel = __LL_ADC_CHANNEL_TO_DECIMAL_NB (channel );
358
429
adc -> DIFSEL &= ~(1 << channel ); // Set channel to Single-ended.
359
430
#endif
360
431
adc -> SQR1 = (channel & 0x1f ) << ADC_SQR1_SQ1_Pos | (1 - 1 ) << ADC_SQR1_L_Pos ;
@@ -391,10 +462,13 @@ STATIC uint32_t adc_read_channel(ADC_TypeDef *adc) {
391
462
}
392
463
393
464
uint32_t adc_config_and_read_u16 (ADC_TypeDef * adc , uint32_t channel , uint32_t sample_time ) {
394
- if (channel == ADC_CHANNEL_VREF ) {
465
+ if (channel == MACHINE_ADC_CH_VREF ) {
395
466
return 0xffff ;
396
467
}
397
468
469
+ // Map internal channel_id to STM32 ADC driver value/literal.
470
+ channel = adc_ll_channel (channel );
471
+
398
472
// Select, configure and read the channel.
399
473
adc_config_channel (adc , channel , sample_time );
400
474
uint32_t raw = adc_read_channel (adc );
@@ -421,7 +495,7 @@ const mp_obj_type_t machine_adc_type;
421
495
typedef struct _machine_adc_obj_t {
422
496
mp_obj_base_t base ;
423
497
ADC_TypeDef * adc ;
424
- uint32_t channel ;
498
+ uint32_t channel ; // one of machine_adc_internal_ch_t
425
499
uint32_t sample_time ;
426
500
} machine_adc_obj_t ;
427
501
@@ -452,20 +526,25 @@ STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, s
452
526
uint32_t sample_time = ADC_SAMPLETIME_DEFAULT ;
453
527
ADC_TypeDef * adc ;
454
528
if (mp_obj_is_int (source )) {
529
+ channel = mp_obj_get_int (source );
455
530
#if defined(STM32WL )
456
531
adc = ADC ;
532
+ #elif defined(STM32H5 )
533
+ // on STM32H5 vbat and vddcore channels are on ADC2
534
+ if (channel == MACHINE_ADC_INT_CH_VBAT || channel == MACHINE_ADC_INT_CH_VDDCORE ) {
535
+ adc = ADC2 ;
536
+ } else {
537
+ adc = ADC1 ;
538
+ }
457
539
#else
458
540
adc = ADC1 ;
459
541
#endif
460
- channel = mp_obj_get_int (source );
461
- if (channel == ADC_CHANNEL_VREFINT
462
- #if defined(STM32G4 )
463
- || channel == ADC_CHANNEL_TEMPSENSOR_ADC1
464
- #else
465
- || channel == ADC_CHANNEL_TEMPSENSOR
466
- #endif
542
+ if (channel == MACHINE_ADC_INT_CH_VREFINT || channel == MACHINE_ADC_INT_CH_TEMPSENSOR
467
543
#if defined(ADC_CHANNEL_VBAT )
468
- || channel == ADC_CHANNEL_VBAT
544
+ || channel == MACHINE_ADC_INT_CH_VBAT
545
+ #endif
546
+ #if defined(ADC_CHANNEL_VDDCORE )
547
+ || channel == MACHINE_ADC_INT_CH_VDDCORE
469
548
#endif
470
549
) {
471
550
sample_time = ADC_SAMPLETIME_DEFAULT_INT ;
@@ -516,15 +595,14 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16);
516
595
STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table [] = {
517
596
{ MP_ROM_QSTR (MP_QSTR_read_u16 ), MP_ROM_PTR (& machine_adc_read_u16_obj ) },
518
597
519
- { MP_ROM_QSTR (MP_QSTR_VREF ), MP_ROM_INT (ADC_CHANNEL_VREF ) },
520
- { MP_ROM_QSTR (MP_QSTR_CORE_VREF ), MP_ROM_INT (ADC_CHANNEL_VREFINT ) },
521
- #if defined(STM32G4 )
522
- { MP_ROM_QSTR (MP_QSTR_CORE_TEMP ), MP_ROM_INT (ADC_CHANNEL_TEMPSENSOR_ADC1 ) },
523
- #else
524
- { MP_ROM_QSTR (MP_QSTR_CORE_TEMP ), MP_ROM_INT (ADC_CHANNEL_TEMPSENSOR ) },
525
- #endif
598
+ { MP_ROM_QSTR (MP_QSTR_VREF ), MP_ROM_INT (MACHINE_ADC_CH_VREF ) },
599
+ { MP_ROM_QSTR (MP_QSTR_CORE_VREF ), MP_ROM_INT (MACHINE_ADC_INT_CH_VREFINT ) },
600
+ { MP_ROM_QSTR (MP_QSTR_CORE_TEMP ), MP_ROM_INT (MACHINE_ADC_INT_CH_TEMPSENSOR ) },
526
601
#if defined(ADC_CHANNEL_VBAT )
527
- { MP_ROM_QSTR (MP_QSTR_CORE_VBAT ), MP_ROM_INT (ADC_CHANNEL_VBAT ) },
602
+ { MP_ROM_QSTR (MP_QSTR_CORE_VBAT ), MP_ROM_INT (MACHINE_ADC_INT_CH_VBAT ) },
603
+ #endif
604
+ #if defined(ADC_CHANNEL_VDDCORE )
605
+ { MP_ROM_QSTR (MP_QSTR_CORE_VDD ), MP_ROM_INT (MACHINE_ADC_INT_CH_VDDCORE ) },
528
606
#endif
529
607
};
530
608
STATIC MP_DEFINE_CONST_DICT (machine_adc_locals_dict , machine_adc_locals_dict_table );
0 commit comments