drivers: adc: use dts properties for stm32 adc sampling time
Use the new dts properties for sampling time in the STM32 ADC driver: - Get the sampling time from dts - Remove all sampling time macro concatenation. - Simplify/refactor setting of sampling time - Check that sampling time is the same for all series using common channel This also fixes a few cases where wrong sampling times were used for an ADC instance (like ADC4 on U5, or ADC3 on STM32H723). Signed-off-by: Guillaume Gautier <guillaume.gautier-ext@st.com>
This commit is contained in:
parent
aa2933b42f
commit
a7b8a5d61f
|
@ -51,6 +51,14 @@ LOG_MODULE_REGISTER(adc_stm32);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#define ANY_NUM_COMMON_SAMPLING_TIME_CHANNELS_IS(value) \
|
||||
(DT_INST_FOREACH_STATUS_OKAY_VARGS(IS_EQ_PROP_OR, \
|
||||
num_sampling_time_common_channels,\
|
||||
0, value) 0)
|
||||
|
||||
#define IS_EQ_PROP_OR(inst, prop, default_value, compare_value) \
|
||||
IS_EQ(DT_INST_PROP_OR(inst, prop, default_value), compare_value) ||
|
||||
|
||||
/* reference voltage for the ADC */
|
||||
#define STM32_ADC_VREF_MV DT_INST_PROP(0, vref_mv)
|
||||
|
||||
|
@ -101,137 +109,12 @@ static const uint32_t table_seq_len[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#define SMP_TIME(x, y) LL_ADC_SAMPLINGTIME_##x##CYCLE##y
|
||||
|
||||
/*
|
||||
* Conversion time in ADC cycles. Many values should have been 0.5 less,
|
||||
* but the adc api system currently does not support describing 'half cycles'.
|
||||
* So all half cycles are counted as one.
|
||||
*/
|
||||
#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32F1X)
|
||||
static const uint16_t acq_time_tbl[8] = {2, 8, 14, 29, 42, 56, 72, 240};
|
||||
static const uint32_t table_samp_time[] = {
|
||||
SMP_TIME(1, _5),
|
||||
SMP_TIME(7, S_5),
|
||||
SMP_TIME(13, S_5),
|
||||
SMP_TIME(28, S_5),
|
||||
SMP_TIME(41, S_5),
|
||||
SMP_TIME(55, S_5),
|
||||
SMP_TIME(71, S_5),
|
||||
SMP_TIME(239, S_5),
|
||||
};
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32F2X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32F4X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32F7X)
|
||||
static const uint16_t acq_time_tbl[8] = {3, 15, 28, 56, 84, 112, 144, 480};
|
||||
static const uint32_t table_samp_time[] = {
|
||||
SMP_TIME(3, S),
|
||||
SMP_TIME(15, S),
|
||||
SMP_TIME(28, S),
|
||||
SMP_TIME(56, S),
|
||||
SMP_TIME(84, S),
|
||||
SMP_TIME(112, S),
|
||||
SMP_TIME(144, S),
|
||||
SMP_TIME(480, S),
|
||||
};
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32F3X)
|
||||
#ifdef ADC5_V1_1
|
||||
static const uint16_t acq_time_tbl[8] = {2, 3, 5, 8, 20, 62, 182, 602};
|
||||
static const uint32_t table_samp_time[] = {
|
||||
SMP_TIME(1, _5),
|
||||
SMP_TIME(2, S_5),
|
||||
SMP_TIME(4, S_5),
|
||||
SMP_TIME(7, S_5),
|
||||
SMP_TIME(19, S_5),
|
||||
SMP_TIME(61, S_5),
|
||||
SMP_TIME(181, S_5),
|
||||
SMP_TIME(601, S_5),
|
||||
};
|
||||
#else
|
||||
static const uint16_t acq_time_tbl[8] = {2, 8, 14, 29, 42, 56, 72, 240};
|
||||
static const uint32_t table_samp_time[] = {
|
||||
SMP_TIME(1, _5),
|
||||
SMP_TIME(7, S_5),
|
||||
SMP_TIME(13, S_5),
|
||||
SMP_TIME(28, S_5),
|
||||
SMP_TIME(41, S_5),
|
||||
SMP_TIME(55, S_5),
|
||||
SMP_TIME(71, S_5),
|
||||
SMP_TIME(239, S_5),
|
||||
};
|
||||
#endif /* ADC5_V1_1 */
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32C0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32L0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32G0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32WLX)
|
||||
static const uint16_t acq_time_tbl[8] = {2, 4, 8, 13, 20, 40, 80, 161};
|
||||
static const uint32_t table_samp_time[] = {
|
||||
SMP_TIME(1, _5),
|
||||
SMP_TIME(3, S_5),
|
||||
SMP_TIME(7, S_5),
|
||||
SMP_TIME(12, S_5),
|
||||
SMP_TIME(19, S_5),
|
||||
SMP_TIME(39, S_5),
|
||||
SMP_TIME(79, S_5),
|
||||
SMP_TIME(160, S_5),
|
||||
};
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32L4X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32L5X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32H5X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32WBX) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32G4X)
|
||||
static const uint16_t acq_time_tbl[8] = {3, 7, 13, 25, 48, 93, 248, 641};
|
||||
static const uint32_t table_samp_time[] = {
|
||||
SMP_TIME(2, S_5),
|
||||
SMP_TIME(6, S_5),
|
||||
SMP_TIME(12, S_5),
|
||||
SMP_TIME(24, S_5),
|
||||
SMP_TIME(47, S_5),
|
||||
SMP_TIME(92, S_5),
|
||||
SMP_TIME(247, S_5),
|
||||
SMP_TIME(640, S_5),
|
||||
};
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32L1X)
|
||||
static const uint16_t acq_time_tbl[8] = {5, 10, 17, 25, 49, 97, 193, 385};
|
||||
static const uint32_t table_samp_time[] = {
|
||||
SMP_TIME(4, S),
|
||||
SMP_TIME(9, S),
|
||||
SMP_TIME(16, S),
|
||||
SMP_TIME(24, S),
|
||||
SMP_TIME(48, S),
|
||||
SMP_TIME(96, S),
|
||||
SMP_TIME(192, S),
|
||||
SMP_TIME(384, S),
|
||||
};
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32H7X)
|
||||
static const uint16_t acq_time_tbl[8] = {2, 3, 9, 17, 33, 65, 388, 811};
|
||||
static const uint32_t table_samp_time[] = {
|
||||
SMP_TIME(1, _5),
|
||||
SMP_TIME(2, S_5),
|
||||
SMP_TIME(8, S_5),
|
||||
SMP_TIME(16, S_5),
|
||||
SMP_TIME(32, S_5),
|
||||
SMP_TIME(64, S_5),
|
||||
SMP_TIME(387, S_5),
|
||||
SMP_TIME(810, S_5),
|
||||
};
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32U5X)
|
||||
static const uint16_t acq_time_tbl[8] = {5, 6, 12, 20, 36, 68, 391, 814};
|
||||
static const uint32_t table_samp_time[] = {
|
||||
SMP_TIME(5,),
|
||||
SMP_TIME(6, S),
|
||||
SMP_TIME(12, S),
|
||||
SMP_TIME(20, S),
|
||||
SMP_TIME(36, S),
|
||||
SMP_TIME(68, S),
|
||||
SMP_TIME(391, S_5),
|
||||
SMP_TIME(814, S),
|
||||
};
|
||||
#endif
|
||||
|
||||
/* External channels (maximum). */
|
||||
#define STM32_CHANNEL_COUNT 20
|
||||
|
||||
/* Number of different sampling time values */
|
||||
#define STM32_NB_SAMPLING_TIME 8
|
||||
|
||||
#ifdef CONFIG_ADC_STM32_DMA
|
||||
struct stream {
|
||||
const struct device *dma_dev;
|
||||
|
@ -254,12 +137,7 @@ struct adc_stm32_data {
|
|||
uint32_t channels;
|
||||
uint8_t channel_count;
|
||||
uint8_t samples_count;
|
||||
#if defined(CONFIG_SOC_SERIES_STM32C0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32F0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32G0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32L0X)
|
||||
int8_t acq_time_index;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ADC_STM32_DMA
|
||||
volatile int dma_error;
|
||||
|
@ -272,6 +150,8 @@ struct adc_stm32_cfg {
|
|||
void (*irq_cfg_func)(void);
|
||||
struct stm32_pclken pclken;
|
||||
const struct pinctrl_dev_config *pcfg;
|
||||
const uint16_t sampling_time_table[STM32_NB_SAMPLING_TIME];
|
||||
int8_t num_sampling_time_common_channels;
|
||||
int8_t temp_channel;
|
||||
int8_t vref_channel;
|
||||
int8_t vbat_channel;
|
||||
|
@ -1212,80 +1092,81 @@ static int adc_stm32_read_async(const struct device *dev,
|
|||
}
|
||||
#endif
|
||||
|
||||
static int adc_stm32_check_acq_time(uint16_t acq_time)
|
||||
static int adc_stm32_check_acq_time(const struct device *dev, uint16_t acq_time)
|
||||
{
|
||||
if (acq_time == ADC_ACQ_TIME_MAX) {
|
||||
return ARRAY_SIZE(acq_time_tbl) - 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (acq_time == ADC_ACQ_TIME(ADC_ACQ_TIME_TICKS,
|
||||
acq_time_tbl[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
const struct adc_stm32_cfg *config =
|
||||
(const struct adc_stm32_cfg *)dev->config;
|
||||
|
||||
if (acq_time == ADC_ACQ_TIME_DEFAULT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (acq_time == ADC_ACQ_TIME_MAX) {
|
||||
return STM32_NB_SAMPLING_TIME - 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < STM32_NB_SAMPLING_TIME; i++) {
|
||||
if (acq_time == ADC_ACQ_TIME(ADC_ACQ_TIME_TICKS,
|
||||
config->sampling_time_table[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERR("Conversion time not supported.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void adc_stm32_setup_speed(const struct device *dev, uint8_t id,
|
||||
static int adc_stm32_setup_speed(const struct device *dev, uint8_t id,
|
||||
uint8_t acq_time_index)
|
||||
{
|
||||
const struct adc_stm32_cfg *config =
|
||||
(const struct adc_stm32_cfg *)dev->config;
|
||||
ADC_TypeDef *adc = config->base;
|
||||
|
||||
#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32L0X)
|
||||
LL_ADC_SetSamplingTimeCommonChannels(adc,
|
||||
table_samp_time[acq_time_index]);
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32C0X)
|
||||
LL_ADC_SetSamplingTimeCommonChannels(adc, LL_ADC_SAMPLINGTIME_COMMON_1,
|
||||
table_samp_time[acq_time_index]);
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32G0X)
|
||||
/* Errata ES0418 and more: ADC sampling time might be one cycle longer */
|
||||
if (acq_time_index < 2) {
|
||||
acq_time_index = 2;
|
||||
}
|
||||
LL_ADC_SetSamplingTimeCommonChannels(adc, LL_ADC_SAMPLINGTIME_COMMON_1,
|
||||
table_samp_time[acq_time_index]);
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32WLX)
|
||||
LL_ADC_SetChannelSamplingTime(adc,
|
||||
__LL_ADC_DECIMAL_NB_TO_CHANNEL(id),
|
||||
LL_ADC_SAMPLINGTIME_COMMON_1);
|
||||
LL_ADC_SetSamplingTimeCommonChannels(adc,
|
||||
__LL_ADC_DECIMAL_NB_TO_CHANNEL(id),
|
||||
table_samp_time[acq_time_index]);
|
||||
#elif defined(CONFIG_SOC_SERIES_STM32U5X)
|
||||
if (adc != ADC4) {
|
||||
/*
|
||||
* For all series we use the fact that the macros LL_ADC_SAMPLINGTIME_*
|
||||
* that should be passed to the set functions are all coded on 3 bits
|
||||
* with 0 shift (ie 0 to 7). So acq_time_index is equivalent to the
|
||||
* macro we would use for the desired sampling time.
|
||||
*/
|
||||
switch (config->num_sampling_time_common_channels) {
|
||||
case 0:
|
||||
#if ANY_NUM_COMMON_SAMPLING_TIME_CHANNELS_IS(0)
|
||||
LL_ADC_SetChannelSamplingTime(adc,
|
||||
__LL_ADC_DECIMAL_NB_TO_CHANNEL(id),
|
||||
table_samp_time[acq_time_index]);
|
||||
} else {
|
||||
LL_ADC_SetSamplingTimeCommonChannels(adc,
|
||||
LL_ADC_SAMPLINGTIME_COMMON_1,
|
||||
table_samp_time[acq_time_index]);
|
||||
}
|
||||
#else
|
||||
LL_ADC_SetChannelSamplingTime(adc,
|
||||
__LL_ADC_DECIMAL_NB_TO_CHANNEL(id),
|
||||
table_samp_time[acq_time_index]);
|
||||
__LL_ADC_DECIMAL_NB_TO_CHANNEL(id),
|
||||
acq_time_index);
|
||||
#endif
|
||||
break;
|
||||
case 1:
|
||||
#if ANY_NUM_COMMON_SAMPLING_TIME_CHANNELS_IS(1)
|
||||
LL_ADC_SetSamplingTimeCommonChannels(adc,
|
||||
acq_time_index);
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
#if ANY_NUM_COMMON_SAMPLING_TIME_CHANNELS_IS(2)
|
||||
LL_ADC_SetChannelSamplingTime(adc,
|
||||
__LL_ADC_DECIMAL_NB_TO_CHANNEL(id),
|
||||
LL_ADC_SAMPLINGTIME_COMMON_1);
|
||||
LL_ADC_SetSamplingTimeCommonChannels(adc,
|
||||
LL_ADC_SAMPLINGTIME_COMMON_1,
|
||||
acq_time_index);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Number of common sampling time channels not supported");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adc_stm32_channel_setup(const struct device *dev,
|
||||
const struct adc_channel_cfg *channel_cfg)
|
||||
{
|
||||
#if defined(CONFIG_SOC_SERIES_STM32C0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32F0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32G0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32L0X)
|
||||
const struct adc_stm32_cfg *config =
|
||||
(const struct adc_stm32_cfg *)dev->config;
|
||||
|
||||
struct adc_stm32_data *data = dev->data;
|
||||
#endif
|
||||
int acq_time_index;
|
||||
|
||||
if (channel_cfg->channel_id >= STM32_CHANNEL_COUNT) {
|
||||
|
@ -1293,24 +1174,24 @@ static int adc_stm32_channel_setup(const struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
acq_time_index = adc_stm32_check_acq_time(
|
||||
acq_time_index = adc_stm32_check_acq_time(dev,
|
||||
channel_cfg->acquisition_time);
|
||||
if (acq_time_index < 0) {
|
||||
return acq_time_index;
|
||||
}
|
||||
#if defined(CONFIG_SOC_SERIES_STM32C0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32F0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32G0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32L0X)
|
||||
if (data->acq_time_index == -1) {
|
||||
data->acq_time_index = acq_time_index;
|
||||
} else {
|
||||
/* All channels of F0/L0 must have identical acquisition time.*/
|
||||
if (acq_time_index != data->acq_time_index) {
|
||||
return -EINVAL;
|
||||
if (config->num_sampling_time_common_channels) {
|
||||
if (data->acq_time_index == -1) {
|
||||
data->acq_time_index = acq_time_index;
|
||||
} else {
|
||||
/*
|
||||
* All families that use common channel must have
|
||||
* identical acquisition time.
|
||||
*/
|
||||
if (acq_time_index != data->acq_time_index) {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (channel_cfg->differential) {
|
||||
LOG_ERR("Differential channels are not supported");
|
||||
|
@ -1327,8 +1208,11 @@ static int adc_stm32_channel_setup(const struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
adc_stm32_setup_speed(dev, channel_cfg->channel_id,
|
||||
acq_time_index);
|
||||
if (adc_stm32_setup_speed(dev, channel_cfg->channel_id,
|
||||
acq_time_index) != 0) {
|
||||
LOG_ERR("Invalid sampling time");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
LOG_DBG("Channel setup succeeded!");
|
||||
|
||||
|
@ -1351,19 +1235,17 @@ static int adc_stm32_init(const struct device *dev)
|
|||
}
|
||||
|
||||
data->dev = dev;
|
||||
#if defined(CONFIG_SOC_SERIES_STM32C0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32F0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32G0X) || \
|
||||
defined(CONFIG_SOC_SERIES_STM32L0X)
|
||||
|
||||
/*
|
||||
* All conversion time for all channels on one ADC instance for F0 and
|
||||
* L0 series chips has to be the same. For C0 and G0 currently only one
|
||||
* For series that use common channels for sampling time, all
|
||||
* conversion time for all channels on one ADC instance has to
|
||||
* be the same.
|
||||
* For series that use two common channels, currently only one
|
||||
* of the two available common channel conversion times is used.
|
||||
* This additional variable is for checking if the conversion time
|
||||
* selection of all channels on one ADC instance is the same.
|
||||
*/
|
||||
data->acq_time_index = -1;
|
||||
#endif
|
||||
|
||||
if (clock_control_on(clk,
|
||||
(clock_control_subsys_t) &config->pclken) != 0) {
|
||||
|
@ -1692,6 +1574,9 @@ static const struct adc_stm32_cfg adc_stm32_cfg_##index = { \
|
|||
.temp_channel = DT_INST_PROP_OR(index, temp_channel, 0xFF), \
|
||||
.vref_channel = DT_INST_PROP_OR(index, vref_channel, 0xFF), \
|
||||
.vbat_channel = DT_INST_PROP_OR(index, vbat_channel, 0xFF), \
|
||||
.sampling_time_table = DT_INST_PROP(index, sampling_times), \
|
||||
.num_sampling_time_common_channels = \
|
||||
DT_INST_PROP_OR(index, num_sampling_time_common_channels, 0),\
|
||||
.res_table_size = DT_INST_PROP_LEN(index, resolutions), \
|
||||
.res_table = DT_INST_PROP(index, resolutions), \
|
||||
}; \
|
||||
|
|
Loading…
Reference in a new issue