diff --git a/CODEOWNERS b/CODEOWNERS index 76391c6a846..7a625e5b2f8 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -100,6 +100,7 @@ /drivers/*/*stm32* @erwango /drivers/*/*native_posix* @aescolar /drivers/adc/ @anangl +/drivers/adc/adc_stm32.c @cybertale /drivers/bluetooth/ @joerchan @jhedberg @Vudentz /drivers/can/ @alexanderwachter /drivers/can/*mcp2515* @karstenkoenig @@ -155,6 +156,7 @@ /dts/riscv32/rv32m1* @MaureenHelm /dts/bindings/ @galak /dts/bindings/can/ @alexanderwachter +/dts/bindings/iio/adc/st,stm32-adc.yaml @cybertale /dts/bindings/serial/ns16550.yaml @gnuless /dts/bindings/*/nordic* @anangl /dts/bindings/*/nxp* @MaureenHelm diff --git a/drivers/adc/CMakeLists.txt b/drivers/adc/CMakeLists.txt index 2654b3a0896..8193a14d36a 100644 --- a/drivers/adc/CMakeLists.txt +++ b/drivers/adc/CMakeLists.txt @@ -9,4 +9,5 @@ zephyr_library_sources_ifdef(CONFIG_ADC_NRFX_SAADC adc_nrfx_saadc.c) zephyr_library_sources_ifdef(CONFIG_ADC_INTEL_QUARK_SE_C1000_SS adc_intel_quark_se_c1000_ss.c) zephyr_library_sources_ifdef(CONFIG_ADC_INTEL_QUARK_D2000 adc_intel_quark_d2000.c) zephyr_library_sources_ifdef(CONFIG_ADC_SAM0 adc_sam0.c) +zephyr_library_sources_ifdef(CONFIG_ADC_STM32 adc_stm32.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE adc_handlers.c) diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index b981b8499da..65230269110 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -57,4 +57,6 @@ source "drivers/adc/Kconfig.intel_quark" source "drivers/adc/Kconfig.sam0" +source "drivers/adc/Kconfig.stm32" + endif # ADC diff --git a/drivers/adc/Kconfig.stm32 b/drivers/adc/Kconfig.stm32 new file mode 100644 index 00000000000..49fd2ba40f4 --- /dev/null +++ b/drivers/adc/Kconfig.stm32 @@ -0,0 +1,25 @@ +# Kconfig - ADC configuration options + +# +# Copyright (c) 2019 Intel Corporation +# Copyright (c) 2019 Endre Karlson +# Copyright (c) 2019 Song Qiang +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig ADC_STM32 + bool "STM32 ADC driver" + depends on SOC_FAMILY_STM32 + help + Enable the driver implementation for the stm32xx ADC + +if ADC_STM32 + +config ADC_1 + bool "ADC1" + default y + help + Enable ADC1 + +endif # ADC_STM32 diff --git a/drivers/adc/adc_stm32.c b/drivers/adc/adc_stm32.c new file mode 100644 index 00000000000..e96ccaf728f --- /dev/null +++ b/drivers/adc/adc_stm32.c @@ -0,0 +1,640 @@ +/* + * Copyright (c) 2018 Kokoon Technology Limited + * Copyright (c) 2019 Song Qiang + * Copyright (c) 2019 Endre Karlson + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include + +#define ADC_CONTEXT_USES_KERNEL_TIMER +#include "adc_context.h" + +#define LOG_LEVEL CONFIG_ADC_LOG_LEVEL +#include +LOG_MODULE_REGISTER(adc_stm32); + +#include + +#if !defined(CONFIG_SOC_SERIES_STM32F0X) && \ + !defined(CONFIG_SOC_SERIES_STM32L0X) +#define RANK(n) LL_ADC_REG_RANK_##n +static const u32_t table_rank[] = { + RANK(1), + RANK(2), + RANK(3), + RANK(4), + RANK(5), + RANK(6), + RANK(7), + RANK(8), + RANK(9), + RANK(10), + RANK(11), + RANK(12), + RANK(13), + RANK(14), + RANK(15), + RANK(16), +}; + +#define SEQ_LEN(n) LL_ADC_REG_SEQ_SCAN_ENABLE_##n##RANKS +static const u32_t table_seq_len[] = { + LL_ADC_REG_SEQ_SCAN_DISABLE, + SEQ_LEN(2), + SEQ_LEN(3), + SEQ_LEN(4), + SEQ_LEN(5), + SEQ_LEN(6), + SEQ_LEN(7), + SEQ_LEN(8), + SEQ_LEN(9), + SEQ_LEN(10), + SEQ_LEN(11), + SEQ_LEN(12), + SEQ_LEN(13), + SEQ_LEN(14), + SEQ_LEN(15), + SEQ_LEN(16), +}; +#endif + +#define RES(n) LL_ADC_RESOLUTION_##n##B +static const u32_t table_resolution[] = { +#if !defined(CONFIG_SOC_SERIES_STM32F1X) + RES(6), + RES(8), + RES(10), +#endif + RES(12), +}; + +#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 u16_t acq_time_tbl[8] = {2, 8, 14, 29, 42, 56, 72, 240}; +static const u32_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 u16_t acq_time_tbl[8] = {3, 15, 28, 56, 84, 112, 144, 480}; +static const u32_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 u16_t acq_time_tbl[8] = {2, 3, 5, 8, 20, 62, 182, 602}; +static const u32_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 u16_t acq_time_tbl[8] = {2, 8, 14, 29, 42, 56, 72, 240}; +static const u32_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_STM32L0X) +static const u16_t acq_time_tbl[8] = {2, 4, 8, 13, 20, 40, 80, 161}; +static const u32_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) +static const u16_t acq_time_tbl[8] = {3, 7, 13, 25, 48, 93, 248, 641}; +static const u32_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), +}; +#endif + +/* 16 external channels. */ +#define STM32_CHANNEL_COUNT 16 + +struct adc_stm32_data { + struct adc_context ctx; + struct device *dev; + u16_t *buffer; + u16_t *repeat_buffer; + + u8_t resolution; + u8_t channel_count; +#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32L0X) + s8_t acq_time_index; +#endif +}; + +struct adc_stm32_cfg { + ADC_TypeDef *base; + + void (*irq_cfg_func)(void); + + struct stm32_pclken pclken; + struct device *p_dev; +}; + +static int check_buffer_size(const struct adc_sequence *sequence, + u8_t active_channels) +{ + size_t needed_buffer_size; + + needed_buffer_size = active_channels * sizeof(u16_t); + + if (sequence->options) { + needed_buffer_size *= (1 + sequence->options->extra_samplings); + } + + if (sequence->buffer_size < needed_buffer_size) { + LOG_ERR("Provided buffer is too small (%u/%u)", + sequence->buffer_size, needed_buffer_size); + return -ENOMEM; + } + + return 0; +} + +static void adc_stm32_start_conversion(struct device *dev) +{ + const struct adc_stm32_cfg *config = dev->config->config_info; + ADC_TypeDef *adc = (ADC_TypeDef *)config->base; + + LOG_DBG("Starting conversion"); + +#if defined(CONFIG_SOC_SERIES_STM32F0X) || \ + defined(CONFIG_SOC_SERIES_STM32F3X) || \ + defined(CONFIG_SOC_SERIES_STM32L0X) || \ + defined(CONFIG_SOC_SERIES_STM32L4X) + LL_ADC_REG_StartConversion(adc); +#else + LL_ADC_REG_StartConversionSWStart(adc); +#endif +} + +static int start_read(struct device *dev, const struct adc_sequence *sequence) +{ + const struct adc_stm32_cfg *config = dev->config->config_info; + struct adc_stm32_data *data = dev->driver_data; + ADC_TypeDef *adc = (ADC_TypeDef *)config->base; + u8_t resolution; + int err; + + switch (sequence->resolution) { +#if !defined(CONFIG_SOC_SERIES_STM32F1X) + case 6: + resolution = table_resolution[0]; + break; + case 8: + resolution = table_resolution[1]; + break; + case 10: + resolution = table_resolution[2]; + break; +#endif + case 12: + resolution = table_resolution[3]; + break; + default: + LOG_ERR("Invalid resolution"); + return -EINVAL; + } + + u32_t channels = sequence->channels; + + data->buffer = sequence->buffer; + u8_t index; + + index = find_lsb_set(channels) - 1; + u32_t channel = __LL_ADC_DECIMAL_NB_TO_CHANNEL(index); +#if defined(CONFIG_SOC_SERIES_STM32F0X) || \ + defined(CONFIG_SOC_SERIES_STM32L0X) + LL_ADC_REG_SetSequencerChannels(adc, channel); +#else + LL_ADC_REG_SetSequencerRanks(adc, table_rank[0], channel); + LL_ADC_REG_SetSequencerLength(adc, table_seq_len[0]); +#endif + data->channel_count = 1; + + err = check_buffer_size(sequence, data->channel_count); + if (err) { + return err; + } + +#if !defined(CONFIG_SOC_SERIES_STM32F1X) + LL_ADC_SetResolution(adc, resolution); +#endif + +#if defined(CONFIG_SOC_SERIES_STM32F0X) || \ + defined(CONFIG_SOC_SERIES_STM32F3X) || \ + defined(CONFIG_SOC_SERIES_STM32L0X) || \ + defined(CONFIG_SOC_SERIES_STM32L4X) + LL_ADC_EnableIT_EOC(adc); +#elif defined(CONFIG_SOC_SERIES_STM32F1X) + LL_ADC_EnableIT_EOS(adc); +#else + LL_ADC_EnableIT_EOCS(adc); +#endif + + adc_context_start_read(&data->ctx, sequence); + + return adc_context_wait_for_completion(&data->ctx); +} + +static void adc_context_start_sampling(struct adc_context *ctx) +{ + struct adc_stm32_data *data = + CONTAINER_OF(ctx, struct adc_stm32_data, ctx); + + data->repeat_buffer = data->buffer; + + adc_stm32_start_conversion(data->dev); +} + +static void adc_context_update_buffer_pointer(struct adc_context *ctx, + bool repeat_sampling) +{ + struct adc_stm32_data *data = + CONTAINER_OF(ctx, struct adc_stm32_data, ctx); + + if (repeat_sampling) { + data->buffer = data->repeat_buffer; + } +} + +static void adc_stm32_isr(void *arg) +{ + struct device *dev = (struct device *)arg; + struct adc_stm32_data *data = (struct adc_stm32_data *)dev->driver_data; + struct adc_stm32_cfg *config = + (struct adc_stm32_cfg *)dev->config->config_info; + ADC_TypeDef *adc = config->base; + + *data->buffer++ = LL_ADC_REG_ReadConversionData32(adc); + + adc_context_on_sampling_done(&data->ctx, dev); + + LOG_DBG("ISR triggered."); +} + +static int adc_stm32_read(struct device *dev, + const struct adc_sequence *sequence) +{ + struct adc_stm32_data *data = dev->driver_data; + int error; + + adc_context_lock(&data->ctx, false, NULL); + error = start_read(dev, sequence); + adc_context_release(&data->ctx, error); + + return error; +} + +#ifdef CONFIG_ADC_ASYNC +static int adc_stm32_read_async(struct device *dev, + const struct adc_sequence *sequence, + struct k_poll_signal *async) +{ + struct adc_stm32_data *data = dev->driver_data; + int error; + + adc_context_lock(&data->ctx, true, async); + error = start_read(dev, sequence); + adc_context_release(&data->ctx, error); + + return error; +} +#endif + +static int adc_stm32_check_acq_time(u16_t acq_time) +{ + for (int i = 0; i < 8; i++) { + if (acq_time == ADC_ACQ_TIME(ADC_ACQ_TIME_TICKS, + acq_time_tbl[i])) { + return i; + } + } + + if (acq_time == ADC_ACQ_TIME_DEFAULT) { + return 0; + } + + LOG_ERR("Conversion time not supportted."); + return -EINVAL; +} + +static void adc_stm32_setup_speed(struct device *dev, u8_t id, + u8_t acq_time_index) +{ + struct adc_stm32_cfg *config = + (struct adc_stm32_cfg *)dev->config->config_info; + 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]); +#else + LL_ADC_SetChannelSamplingTime(adc, + __LL_ADC_DECIMAL_NB_TO_CHANNEL(id), + table_samp_time[acq_time_index]); +#endif +} + +static int adc_stm32_channel_setup(struct device *dev, + const struct adc_channel_cfg *channel_cfg) +{ +#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32L0X) + struct adc_stm32_data *data = dev->driver_data; +#endif + int acq_time_index; + + if (channel_cfg->channel_id >= STM32_CHANNEL_COUNT) { + LOG_ERR("Channel %d is not valid", channel_cfg->channel_id); + return -EINVAL; + } + + acq_time_index = adc_stm32_check_acq_time( + channel_cfg->acquisition_time); + if (acq_time_index < 0) { + return acq_time_index; + } +#if defined(CONFIG_SOC_SERIES_STM32F0X) || 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; + } + } +#endif + + if (channel_cfg->differential) { + LOG_ERR("Differential channels are not supported"); + return -EINVAL; + } + + if (channel_cfg->gain != ADC_GAIN_1) { + LOG_ERR("Invalid channel gain"); + return -EINVAL; + } + + if (channel_cfg->reference != ADC_REF_INTERNAL) { + LOG_ERR("Invalid channel reference"); + return -EINVAL; + } + + adc_stm32_setup_speed(dev, channel_cfg->channel_id, + acq_time_index); + + LOG_DBG("Channel setup succeeded!"); + + return 0; +} + +#if !defined(CONFIG_SOC_SERIES_STM32F2X) && \ + !defined(CONFIG_SOC_SERIES_STM32F4X) && \ + !defined(CONFIG_SOC_SERIES_STM32F7X) && \ + !defined(CONFIG_SOC_SERIES_STM32F1X) +static void adc_stm32_calib(struct device *dev) +{ + struct adc_stm32_cfg *config = + (struct adc_stm32_cfg *)dev->config->config_info; + ADC_TypeDef *adc = config->base; + +#if defined(CONFIG_SOC_SERIES_STM32F3X) || \ + defined(CONFIG_SOC_SERIES_STM32L4X) + LL_ADC_StartCalibration(adc, LL_ADC_SINGLE_ENDED); +#elif defined(CONFIG_SOC_SERIES_STM32F0X) || \ + defined(CONFIG_SOC_SERIES_STM32L0X) + LL_ADC_StartCalibration(adc); +#endif + while (LL_ADC_IsCalibrationOnGoing(adc)) + ; +} +#endif + +static int adc_stm32_init(struct device *dev) +{ + struct adc_stm32_data *data = dev->driver_data; + const struct adc_stm32_cfg *config = dev->config->config_info; + struct device *clk = + device_get_binding(STM32_CLOCK_CONTROL_NAME); + ADC_TypeDef *adc = (ADC_TypeDef *)config->base; + + LOG_DBG("Initializing...."); + + data->dev = dev; +#if defined(CONFIG_SOC_SERIES_STM32F0X) || 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. 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) { + return -EIO; + } + +#if defined(CONFIG_SOC_SERIES_STM32L4X) + /* + * L4 series STM32 needs to be awaken from deep sleep mode, and restore + * its calibration parameters if there are some previously stored + * calibration parameters. + */ + LL_ADC_DisableDeepPowerDown(adc); +#endif + /* + * F3 and L4 ADC modules need some time to be stabilized before + * performing any enable or calibration actions. + */ +#if defined(CONFIG_SOC_SERIES_STM32F3X) || \ + defined(CONFIG_SOC_SERIES_STM32L4X) + LL_ADC_EnableInternalRegulator(adc); + k_busy_wait(LL_ADC_DELAY_INTERNAL_REGUL_STAB_US); +#endif + +#if defined(CONFIG_SOC_SERIES_STM32F0X) || \ + defined(CONFIG_SOC_SERIES_STM32L0X) + LL_ADC_SetClock(adc, LL_ADC_CLOCK_SYNC_PCLK_DIV4); +#elif defined(CONFIG_SOC_SERIES_STM32F3X) || \ + defined(CONFIG_SOC_SERIES_STM32L4X) + LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(), + LL_ADC_CLOCK_SYNC_PCLK_DIV4); +#endif + +#if !defined(CONFIG_SOC_SERIES_STM32F2X) && \ + !defined(CONFIG_SOC_SERIES_STM32F4X) && \ + !defined(CONFIG_SOC_SERIES_STM32F7X) && \ + !defined(CONFIG_SOC_SERIES_STM32F1X) + /* + * Calibration of F1 series has to be started after ADC Module is + * enabled. + */ + adc_stm32_calib(dev); +#endif + +#if defined(CONFIG_SOC_SERIES_STM32F0X) || \ + defined(CONFIG_SOC_SERIES_STM32L0X) + if (LL_ADC_IsActiveFlag_ADRDY(adc)) { + LL_ADC_ClearFlag_ADRDY(adc); + } + + /* + * These two series STM32 has one internal voltage reference source + * to be enabled. + */ + LL_ADC_SetCommonPathInternalCh(ADC, LL_ADC_PATH_INTERNAL_VREFINT); +#endif + +#if defined(CONFIG_SOC_SERIES_STM32F0X) || \ + defined(CONFIG_SOC_SERIES_STM32F3X) || \ + defined(CONFIG_SOC_SERIES_STM32L0X) || \ + defined(CONFIG_SOC_SERIES_STM32L4X) + /* + * ADC modules on these series have to wait for some cycles to be + * enabled. + */ + u32_t adc_rate, wait_cycles; + + if (clock_control_get_rate(clk, + (clock_control_subsys_t *) &config->pclken, &adc_rate) < 0) { + LOG_ERR("ADC clock rate get error."); + } + + wait_cycles = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / adc_rate * + LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES; + + for (int i = wait_cycles; i >= 0; i--) + ; +#endif + + LL_ADC_Enable(adc); + +#ifdef CONFIG_SOC_SERIES_STM32L4X + /* + * Enabling ADC modules in L4 series may fail if they are still not + * stabilized, this will wait for a short time to ensure ADC modules + * are properly enabled. + */ + u32_t countTimeout = 0; + + while (LL_ADC_IsActiveFlag_ADRDY(adc) == 0) { + if (LL_ADC_IsEnabled(adc) == 0UL) { + LL_ADC_Enable(adc); + countTimeout++; + if (countTimeout == 10) { + return -ETIMEDOUT; + } + } + } +#endif + + config->irq_cfg_func(); + +#ifdef CONFIG_SOC_SERIES_STM32F1X + /* Calibration of F1 must starts after two cycles after ADON is set. */ + LL_ADC_StartCalibration(adc); + LL_ADC_REG_SetTriggerSource(adc, LL_ADC_REG_TRIG_SOFTWARE); +#endif + adc_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +static const struct adc_driver_api api_stm32_driver_api = { + .channel_setup = adc_stm32_channel_setup, + .read = adc_stm32_read, +#ifdef CONFIG_ADC_ASYNC + .read_async = adc_stm32_read_async, +#endif +}; + +#define STM32_ADC_INIT(index) \ + \ +static void adc_stm32_cfg_func_##index(void); \ + \ +static const struct adc_stm32_cfg adc_stm32_cfg_##index = { \ + .base = (ADC_TypeDef *)DT_ADC_##index##_BASE_ADDRESS, \ + .irq_cfg_func = adc_stm32_cfg_func_##index, \ + .pclken = { \ + .enr = DT_ADC_##index##_CLOCK_BITS, \ + .bus = DT_ADC_##index##_CLOCK_BUS, \ + }, \ +}; \ +static struct adc_stm32_data adc_stm32_data_##index = { \ + ADC_CONTEXT_INIT_TIMER(adc_stm32_data_##index, ctx), \ + ADC_CONTEXT_INIT_LOCK(adc_stm32_data_##index, ctx), \ + ADC_CONTEXT_INIT_SYNC(adc_stm32_data_##index, ctx), \ +}; \ + \ +DEVICE_AND_API_INIT(adc_##index, DT_ADC_##index##_NAME, &adc_stm32_init,\ + &adc_stm32_data_##index, &adc_stm32_cfg_##index, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ + &api_stm32_driver_api); \ + \ +static void adc_stm32_cfg_func_##index(void) \ +{ \ + IRQ_CONNECT(DT_ADC_##index##_IRQ, DT_ADC_##index##_IRQ_PRI, \ + adc_stm32_isr, DEVICE_GET(adc_##index), 0); \ + irq_enable(DT_ADC_##index##_IRQ); \ +} + +#ifdef CONFIG_ADC_1 +STM32_ADC_INIT(1) +#endif /* CONFIG_ADC_1 */ diff --git a/soc/arm/st_stm32/common/Kconfig.defconfig.series b/soc/arm/st_stm32/common/Kconfig.defconfig.series index dfc364b4ef0..6349e2c16d3 100644 --- a/soc/arm/st_stm32/common/Kconfig.defconfig.series +++ b/soc/arm/st_stm32/common/Kconfig.defconfig.series @@ -95,4 +95,11 @@ config CAN_STM32 endif +if ADC + +config ADC_STM32 + default y + +endif # ADC + endif # SOC_FAMILY_STM32 diff --git a/soc/arm/st_stm32/stm32f0/soc.h b/soc/arm/st_stm32/stm32f0/soc.h index c57965f789c..9e838d1ceb4 100644 --- a/soc/arm/st_stm32/stm32f0/soc.h +++ b/soc/arm/st_stm32/stm32f0/soc.h @@ -59,6 +59,10 @@ #include #endif +#ifdef CONFIG_ADC_STM32 +#include +#endif + #endif /* !_ASMLANGUAGE */ #endif /* _STM32F0_SOC_H_ */ diff --git a/soc/arm/st_stm32/stm32f1/soc.h b/soc/arm/st_stm32/stm32f1/soc.h index b12f359b507..5a69f5f1c0e 100644 --- a/soc/arm/st_stm32/stm32f1/soc.h +++ b/soc/arm/st_stm32/stm32f1/soc.h @@ -59,6 +59,10 @@ #include #endif +#ifdef CONFIG_ADC_STM32 +#include +#endif + #endif /* !_ASMLANGUAGE */ #endif /* _STM32F1_SOC_H_ */ diff --git a/soc/arm/st_stm32/stm32f2/soc.h b/soc/arm/st_stm32/stm32f2/soc.h index 2582b565648..f2fdfa4f044 100644 --- a/soc/arm/st_stm32/stm32f2/soc.h +++ b/soc/arm/st_stm32/stm32f2/soc.h @@ -50,6 +50,10 @@ #include #endif +#ifdef CONFIG_ADC_STM32 +#include +#endif + #endif /* !_ASMLANGUAGE */ #endif /* _STM32F2_SOC_H_ */ diff --git a/soc/arm/st_stm32/stm32f3/soc.h b/soc/arm/st_stm32/stm32f3/soc.h index 47f3a938b68..eb0202cd3a6 100644 --- a/soc/arm/st_stm32/stm32f3/soc.h +++ b/soc/arm/st_stm32/stm32f3/soc.h @@ -66,6 +66,10 @@ #include #endif +#ifdef CONFIG_ADC_STM32 +#include +#endif + #endif /* !_ASMLANGUAGE */ #endif /* _STM32F3_SOC_H_ */ diff --git a/soc/arm/st_stm32/stm32f4/soc.h b/soc/arm/st_stm32/stm32f4/soc.h index d0af3973850..5f00892031d 100644 --- a/soc/arm/st_stm32/stm32f4/soc.h +++ b/soc/arm/st_stm32/stm32f4/soc.h @@ -69,6 +69,10 @@ #include #endif +#ifdef CONFIG_ADC_STM32 +#include +#endif + #endif /* !_ASMLANGUAGE */ #endif /* _STM32F4_SOC_H_ */ diff --git a/soc/arm/st_stm32/stm32f7/soc.h b/soc/arm/st_stm32/stm32f7/soc.h index 287be586bcf..2c33c4e1b07 100644 --- a/soc/arm/st_stm32/stm32f7/soc.h +++ b/soc/arm/st_stm32/stm32f7/soc.h @@ -68,6 +68,10 @@ #include #endif +#ifdef CONFIG_ADC_STM32 +#include +#endif + #endif /* !_ASMLANGUAGE */ #endif /* _STM32F7_SOC_H_ */ diff --git a/soc/arm/st_stm32/stm32l0/soc.h b/soc/arm/st_stm32/stm32l0/soc.h index 4f8d826667a..4fbbdb3cb84 100644 --- a/soc/arm/st_stm32/stm32l0/soc.h +++ b/soc/arm/st_stm32/stm32l0/soc.h @@ -60,6 +60,10 @@ #include #endif +#ifdef CONFIG_ADC_STM32 +#include +#endif + #endif /* !_ASMLANGUAGE */ #endif /* _STM32L0_SOC_H_ */ diff --git a/soc/arm/st_stm32/stm32l4/soc.h b/soc/arm/st_stm32/stm32l4/soc.h index 19321ca5620..12b10cec60e 100644 --- a/soc/arm/st_stm32/stm32l4/soc.h +++ b/soc/arm/st_stm32/stm32l4/soc.h @@ -83,6 +83,10 @@ #include #endif +#ifdef CONFIG_ADC_STM32 +#include +#endif + #endif /* !_ASMLANGUAGE */ #endif /* _STM32L4X_SOC_H_ */