@@ -109,9 +109,17 @@ LOG_MODULE_REGISTER(adc_stm32);
109
109
st_adc_oversampler,\
110
110
value) 0)
111
111
112
+ #define ANY_CHILD_NODE_IS_DIFFERENTIAL (inst ) \
113
+ (DT_INST_FOREACH_CHILD_VARGS(inst, IS_EQ_NODE_PROP_OR, \
114
+ zephyr_differential, \
115
+ 0, 1) 0)
116
+
112
117
#define IS_EQ_PROP_OR (inst , prop , default_value , compare_value ) \
113
118
IS_EQ(DT_INST_PROP_OR(inst, prop, default_value), compare_value) ||
114
119
120
+ #define IS_EQ_NODE_PROP_OR (node , prop , default_value , compare_value ) \
121
+ IS_EQ(DT_PROP_OR(node, prop, default_value), compare_value) ||
122
+
115
123
#define IS_EQ_STRING_PROP (inst , prop , compare_value ) \
116
124
IS_EQ(DT_INST_STRING_UPPER_TOKEN(inst, prop), compare_value) ||
117
125
@@ -187,6 +195,7 @@ struct adc_stm32_cfg {
187
195
size_t pclk_len ;
188
196
uint32_t clk_prescaler ;
189
197
const struct pinctrl_dev_config * pcfg ;
198
+ bool differential_channels_used ;
190
199
const uint16_t sampling_time_table [STM32_NB_SAMPLING_TIME ];
191
200
int8_t num_sampling_time_common_channels ;
192
201
int8_t sequencer_type ;
@@ -484,11 +493,16 @@ static void adc_stm32_calibration_measure(ADC_TypeDef *adc, uint32_t *calibratio
484
493
}
485
494
#endif
486
495
487
- static void adc_stm32_calibration_start (const struct device * dev )
496
+ static void adc_stm32_calibration_start (const struct device * dev , bool single_ended )
488
497
{
489
498
const struct adc_stm32_cfg * config =
490
499
(const struct adc_stm32_cfg * )dev -> config ;
491
500
ADC_TypeDef * adc = config -> base ;
501
+ #ifdef LL_ADC_SINGLE_ENDED
502
+ uint32_t calib_type = single_ended ? LL_ADC_SINGLE_ENDED : LL_ADC_DIFFERENTIAL_ENDED ;
503
+ #else
504
+ ARG_UNUSED (single_ended );
505
+ #endif
492
506
493
507
#if defined(STM32F3XX_ADC ) || \
494
508
defined(CONFIG_SOC_SERIES_STM32L4X ) || \
@@ -497,7 +511,7 @@ static void adc_stm32_calibration_start(const struct device *dev)
497
511
defined(CONFIG_SOC_SERIES_STM32H7RSX ) || \
498
512
defined(CONFIG_SOC_SERIES_STM32WBX ) || \
499
513
defined(CONFIG_SOC_SERIES_STM32G4X )
500
- LL_ADC_StartCalibration (adc , LL_ADC_SINGLE_ENDED );
514
+ LL_ADC_StartCalibration (adc , calib_type );
501
515
#elif defined(CONFIG_SOC_SERIES_STM32C0X ) || \
502
516
defined(CONFIG_SOC_SERIES_STM32F0X ) || \
503
517
DT_HAS_COMPAT_STATUS_OKAY (st_stm32f1_adc ) || \
@@ -509,6 +523,7 @@ static void adc_stm32_calibration_start(const struct device *dev)
509
523
510
524
LL_ADC_StartCalibration (adc );
511
525
#elif defined(CONFIG_SOC_SERIES_STM32U5X )
526
+ ARG_UNUSED (calib_type );
512
527
if (adc != ADC4 ) {
513
528
uint32_t dev_id = LL_DBGMCU_GetDeviceID ();
514
529
uint32_t rev_id = LL_DBGMCU_GetRevisionID ();
@@ -531,9 +546,11 @@ static void adc_stm32_calibration_start(const struct device *dev)
531
546
}
532
547
LL_ADC_StartCalibration (adc , LL_ADC_CALIB_OFFSET );
533
548
#elif defined(CONFIG_SOC_SERIES_STM32H7X )
534
- LL_ADC_StartCalibration (adc , LL_ADC_CALIB_OFFSET , LL_ADC_SINGLE_ENDED );
549
+ LL_ADC_StartCalibration (adc , LL_ADC_CALIB_OFFSET , calib_type );
535
550
#elif defined(CONFIG_SOC_SERIES_STM32N6X )
536
551
uint32_t calibration_factor ;
552
+
553
+ ARG_UNUSED (calib_type );
537
554
/* Start ADC calibration */
538
555
LL_ADC_StartCalibration (adc , LL_ADC_SINGLE_ENDED );
539
556
/* Disable additional offset before calibration start */
@@ -580,7 +597,10 @@ static int adc_stm32_calibrate(const struct device *dev)
580
597
#if !DT_HAS_COMPAT_STATUS_OKAY (st_stm32f1_adc ) && \
581
598
!defined(CONFIG_SOC_SERIES_STM32N6X )
582
599
adc_stm32_disable (adc );
583
- adc_stm32_calibration_start (dev );
600
+ adc_stm32_calibration_start (dev , true);
601
+ if (config -> differential_channels_used ) {
602
+ adc_stm32_calibration_start (dev , false);
603
+ }
584
604
adc_stm32_calibration_delay (dev );
585
605
#endif /* !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) */
586
606
@@ -592,7 +612,7 @@ static int adc_stm32_calibrate(const struct device *dev)
592
612
#if DT_HAS_COMPAT_STATUS_OKAY (st_stm32f1_adc ) || \
593
613
defined(CONFIG_SOC_SERIES_STM32N6X )
594
614
adc_stm32_calibration_delay (dev );
595
- adc_stm32_calibration_start (dev );
615
+ adc_stm32_calibration_start (dev , true );
596
616
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) */
597
617
598
618
#if defined(CONFIG_SOC_SERIES_STM32H7X ) && \
@@ -1287,18 +1307,64 @@ static int adc_stm32_sampling_time_setup(const struct device *dev, uint8_t id,
1287
1307
return 0 ;
1288
1308
}
1289
1309
1310
+ #if defined(STM32F3XX_ADC ) || \
1311
+ defined(CONFIG_SOC_SERIES_STM32G4X ) || \
1312
+ defined(CONFIG_SOC_SERIES_STM32H5X ) || \
1313
+ defined(CONFIG_SOC_SERIES_STM32H7X ) || \
1314
+ defined(CONFIG_SOC_SERIES_STM32H7RSX ) || \
1315
+ defined(CONFIG_SOC_SERIES_STM32L4X ) || \
1316
+ defined(CONFIG_SOC_SERIES_STM32L5X ) || \
1317
+ defined(CONFIG_SOC_SERIES_STM32U5X ) || \
1318
+ defined(CONFIG_SOC_SERIES_STM32WBX )
1319
+ #define DIFFERENTIAL_MODE_SUPPORTED 1
1320
+ #else
1321
+ #define DIFFERENTIAL_MODE_SUPPORTED 0
1322
+ #endif
1323
+
1324
+ #if DIFFERENTIAL_MODE_SUPPORTED
1325
+ static void set_channel_differential_mode (ADC_TypeDef * adc , uint8_t channel_id , bool differential )
1326
+ {
1327
+ const uint32_t mode = differential ? LL_ADC_DIFFERENTIAL_ENDED : LL_ADC_SINGLE_ENDED ;
1328
+ const uint32_t channel = __LL_ADC_DECIMAL_NB_TO_CHANNEL (channel_id );
1329
+
1330
+ /* The ADC must be disabled to change the single ended / differential mode setting. The
1331
+ * disable / re-enable cycle can take some time, so avoid doing this if the channel is
1332
+ * already set to the correct mode.
1333
+ */
1334
+ if (LL_ADC_GetChannelSingleDiff (adc , channel ) == mode ) {
1335
+ return ;
1336
+ }
1337
+
1338
+ adc_stm32_disable (adc );
1339
+ LL_ADC_SetChannelSingleDiff (adc , channel , mode );
1340
+ adc_stm32_enable (adc );
1341
+ }
1342
+ #endif
1343
+
1290
1344
static int adc_stm32_channel_setup (const struct device * dev ,
1291
1345
const struct adc_channel_cfg * channel_cfg )
1292
1346
{
1293
- #ifdef CONFIG_SOC_SERIES_STM32H5X
1347
+ #if defined( CONFIG_SOC_SERIES_STM32H5X ) || DIFFERENTIAL_MODE_SUPPORTED
1294
1348
const struct adc_stm32_cfg * config = (const struct adc_stm32_cfg * )dev -> config ;
1295
1349
ADC_TypeDef * adc = config -> base ;
1296
1350
#endif
1297
1351
1352
+ #if !DIFFERENTIAL_MODE_SUPPORTED
1298
1353
if (channel_cfg -> differential ) {
1299
- LOG_ERR ("Differential channels are not supported" );
1354
+ LOG_ERR ("Differential channels not supported on this SOC series " );
1300
1355
return - EINVAL ;
1301
1356
}
1357
+ #else
1358
+ if (channel_cfg -> differential && !config -> differential_channels_used ) {
1359
+ /* At least one channel must be set to differential mode in the devicetree
1360
+ * to cause a differential calibration to be performed during init.
1361
+ */
1362
+ LOG_ERR ("Differential calibration not done, cannot use differential mode" );
1363
+ return - EINVAL ;
1364
+ }
1365
+
1366
+ set_channel_differential_mode (adc , channel_cfg -> channel_id , channel_cfg -> differential );
1367
+ #endif
1302
1368
1303
1369
if (channel_cfg -> gain != ADC_GAIN_1 ) {
1304
1370
LOG_ERR ("Invalid channel gain" );
@@ -1918,6 +1984,7 @@ static const struct adc_stm32_cfg adc_stm32_cfg_##index = { \
1918
1984
.pclk_len = DT_INST_NUM_CLOCKS(index), \
1919
1985
.clk_prescaler = ADC_STM32_DT_PRESC(index), \
1920
1986
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \
1987
+ .differential_channels_used = (ANY_CHILD_NODE_IS_DIFFERENTIAL(index) > 0), \
1921
1988
.sequencer_type = DT_INST_STRING_UPPER_TOKEN(index, st_adc_sequencer), \
1922
1989
.oversampler_type = DT_INST_STRING_UPPER_TOKEN(index, st_adc_oversampler), \
1923
1990
.sampling_time_table = DT_INST_PROP(index, sampling_times), \
0 commit comments