diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig index 0a918c1ccd3..633ffd2dd26 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig @@ -24,6 +24,116 @@ if BSP_USING_USBD # "ULPI: UTMI+ Low Pin Interface" endif +menuconfig BSP_USING_ADC_V2 + bool "Enable ADC V2" + select RT_USING_ADC + select RT_USING_ADC_V2 + default n + +if BSP_USING_ADC_V2 + config BSP_USING_ADC1 + bool "Enable ADC1" + default n + + config BSP_USING_ADC2 + bool "Enable ADC2" + depends on (SOC_SERIES_STM32F1 || SOC_SERIES_STM32F2 || SOC_SERIES_STM32F3 || \ + SOC_SERIES_STM32F4 || SOC_SERIES_STM32G4 || SOC_SERIES_STM32F7 || \ + SOC_SERIES_STM32H5 || SOC_SERIES_STM32H7 || SOC_SERIES_STM32H7RS || \ + SOC_SERIES_STM32L4 || SOC_SERIES_STM32L5 || SOC_SERIES_STM32MP1 || \ + SOC_SERIES_STM32U5) + default n + + config BSP_USING_ADC3 + bool "Enable ADC3" + depends on (SOC_SERIES_STM32F1 || SOC_SERIES_STM32F2 || SOC_SERIES_STM32F3 || \ + SOC_SERIES_STM32F4 || SOC_SERIES_STM32G4 || SOC_SERIES_STM32F7 || \ + SOC_SERIES_STM32H7 || SOC_SERIES_STM32L4 || SOC_SERIES_STM32MP1) + default n + + config BSP_USING_ADC4 + bool "Enable ADC4" + depends on (SOC_SERIES_STM32F3 || SOC_SERIES_STM32G4 || SOC_SERIES_STM32U5) + default n + + config BSP_ADC_USING_TRIGGER + bool "Enable ADC V2 trigger backend" + select RT_ADC_USING_TRIGGER + default n + help + Enable STM32 ADC V2 trigger selector validation and backend + encoding. The ADC backend maps the framework-cached trigger to STM32 + HAL ADC selector fields. Trigger-source frequency and lifecycle are + owned by the ADC trigger framework and timer trigger backend. + + config BSP_ADC_USING_TIMER_TRIGGER + bool "Enable ADC V2 timer trigger selector backend" + depends on BSP_ADC_USING_TRIGGER + depends on BSP_USING_TIM + depends on RT_USING_CLOCK_TIME + select RT_ADC_TRIGGER_USING_TIMER + select RT_USING_CLOCK_TIMER_TRIGGER + default n + help + Enable STM32 TIMx update/TRGO and compare event to ADC external + trigger selector mapping for ADC V2 stream pacing. Timer frequency, + TRGO/compare setup, and lifecycle are handled through the clock + timer trigger backend during ADC stream start and stop. + + config BSP_ADC_USING_ANALOG_COMPARE_TRIGGER + bool "Enable ADC V2 analog comparator trigger selector backend" + depends on BSP_ADC_USING_TRIGGER + select RT_ADC_TRIGGER_USING_COMPARE + default n + help + Enable STM32 COMPx_OUT to ADC external trigger selector mapping for + ADC V2. Comparator input, threshold, polarity, and enable state are + owned by board code, application code, or a comparator driver. + + config BSP_ADC_USING_STREAM_DMA + bool + + config BSP_ADC1_USING_DMA + bool "Enable ADC1 stream DMA backend" + depends on BSP_USING_ADC1 + select RT_ADC_USING_STREAM + select BSP_ADC_USING_STREAM_DMA + default n + help + Enable the STM32 ADC1 DMA backend for ADC V2 stream sessions. + + This option only enables the board-level DMA backend. The stream + framework and buffering policies are controlled by RT_ADC_USING_STREAM, + RT_ADC_STREAM_USING_LATEST, and RT_ADC_STREAM_USING_FIFO. + + config BSP_ADC2_USING_DMA + bool "Enable ADC2 stream DMA backend" + depends on BSP_USING_ADC2 + select RT_ADC_USING_STREAM + select BSP_ADC_USING_STREAM_DMA + default n + help + Enable the STM32 ADC2 DMA backend for ADC V2 stream sessions. + + config BSP_ADC3_USING_DMA + bool "Enable ADC3 stream DMA backend" + depends on BSP_USING_ADC3 + select RT_ADC_USING_STREAM + select BSP_ADC_USING_STREAM_DMA + default n + help + Enable the STM32 ADC3 DMA backend for ADC V2 stream sessions. + + config BSP_ADC4_USING_DMA + bool "Enable ADC4 stream DMA backend" + depends on BSP_USING_ADC4 + select RT_ADC_USING_STREAM + select BSP_ADC_USING_STREAM_DMA + default n + help + Enable the STM32 ADC4 DMA backend for ADC V2 stream sessions. +endif + config BSP_USING_CRC bool "Enable CRC (CRC-32 0x04C11DB7 Polynomial)" select RT_USING_HWCRYPTO @@ -59,4 +169,3 @@ config BSP_USING_UDID bool "Enable UDID (Unique Device Identifier)" select RT_USING_HWCRYPTO default n - diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript index 9c5ab5c4aee..be974a8bc8f 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript @@ -46,9 +46,18 @@ if GetDepend(['RT_USING_I2C']): if GetDepend(['BSP_USING_ETH', 'RT_USING_LWIP']) and not GetDepend(['SOC_STM32H750_ARTPI']): src += ['drv_eth.c'] -if GetDepend(['RT_USING_ADC']): +if GetDepend(['RT_USING_ADC']) and not GetDepend(['RT_USING_ADC_V2']): src += ['drv_adc.c'] +if GetDepend(['BSP_USING_ADC_V2']): + src += ['drv_adc_v2.c'] + + if GetDepend(['BSP_ADC_USING_TRIGGER']): + src += ['drv_adc_v2_trigger.c'] + + if GetDepend(['RT_USING_FINSH', 'RT_ADC_V2_USING_MSH']): + src += ['drv_adc_v2_msh.c'] + if GetDepend(['RT_USING_DAC']): src += ['drv_dac.c'] diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/f0/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f0/adc_config_v2.h new file mode 100644 index 00000000000..c1e0fa87320 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f0/adc_config_v2.h @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32f0 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32F0 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32F0. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32F0. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32F0. */ +#if defined(ADC_SAMPLETIME_71CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_71CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_71CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32F0 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +/** @brief STM32F0 legacy internal ADC source logical channel overrides. */ +#if !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_TEMP_LOGICAL_OVERRIDE 16 +#define STM32_ADC_VREF_LOGICAL_OVERRIDE 17 +#define STM32_ADC_VBAT_LOGICAL_OVERRIDE 18 +#endif /* !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32F0 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32F0 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32F0 ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/f1/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f1/adc_config_v2.h new file mode 100644 index 00000000000..7632d2b2d69 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f1/adc_config_v2.h @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32f1 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32F1 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32F1. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32F1. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32F1. */ +#if defined(ADC_SAMPLETIME_55CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_55CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_55CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32F1 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +/** @brief STM32F1 legacy internal ADC source logical channel overrides. */ +#if !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_TEMP_LOGICAL_OVERRIDE 16 +#define STM32_ADC_VREF_LOGICAL_OVERRIDE 17 +#define STM32_ADC_VBAT_LOGICAL_OVERRIDE 18 +#endif /* !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32F1 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32F1 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32F1 ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/f2/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f2/adc_config_v2.h new file mode 100644 index 00000000000..994405a8596 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f2/adc_config_v2.h @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32f2 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32F2 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32F2. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32F2. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32F2. */ +#if defined(ADC_SAMPLETIME_112CYCLES) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_112CYCLES +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_112CYCLES) */ + + +/** @brief Maximum regular sequence length supported by the STM32F2 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +/** @brief STM32F2 legacy internal ADC source logical channel overrides. */ +#if !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_TEMP_LOGICAL_OVERRIDE 16 +#define STM32_ADC_VREF_LOGICAL_OVERRIDE 17 +#define STM32_ADC_VBAT_LOGICAL_OVERRIDE 18 +#endif /* !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#define STM32_ADC_HAS_CONFIG_OFFSET 1 + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32F2 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32F2 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32F2 ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/f3/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f3/adc_config_v2.h new file mode 100644 index 00000000000..778fec24bbc --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f3/adc_config_v2.h @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32f3 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32F3 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32F3. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32F3. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32F3. */ +#if defined(ADC_SAMPLETIME_181CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_181CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_181CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32F3 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +/** @brief STM32F3 legacy internal ADC source logical channel overrides. */ +#if !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_TEMP_LOGICAL_OVERRIDE 16 +#define STM32_ADC_VREF_LOGICAL_OVERRIDE 17 +#define STM32_ADC_VBAT_LOGICAL_OVERRIDE 18 +#endif /* !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) */ + +#if defined(ADC_CHANNEL_VREFINT) +/** @brief STM32F3 VREFINT HAL ADC channel for the multi-instance route. */ +#define STM32_ADC_VREF_HAL_CHANNEL ADC_CHANNEL_VREFINT +/** @brief STM32F3 ADC instances that can sample VREFINT. */ +#define STM32_ADC_VREF_INSTANCE_MASK ((1UL << 0) | (1UL << 1) | (1UL << 2) | (1UL << 3)) +#endif /* defined(ADC_CHANNEL_VREFINT) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32F3 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32F3 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32F3 ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef BSP_USING_ADC4 +/** @brief Default STM32F3 ADC4 V2 object initializer. */ +#define ADC4_V2_CONFIG \ + { \ + .name = "adc4", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC4, \ + }, \ + ADC4_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC4 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/f4/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f4/adc_config_v2.h new file mode 100644 index 00000000000..d4849e22131 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f4/adc_config_v2.h @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32f4 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32F4 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32F4. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32F4. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32F4. */ +#if defined(ADC_SAMPLETIME_112CYCLES) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_112CYCLES +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_112CYCLES) */ + + +/** @brief Maximum regular sequence length supported by the STM32F4 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +/** @brief STM32F4 legacy internal ADC source logical channel overrides. */ +#if !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_TEMP_LOGICAL_OVERRIDE 16 +#define STM32_ADC_VREF_LOGICAL_OVERRIDE 17 +#define STM32_ADC_VBAT_LOGICAL_OVERRIDE 18 +#endif /* !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#define STM32_ADC_HAS_CONFIG_OFFSET 1 + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32F4 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32F4 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32F4 ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/f4/dma_config.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f4/dma_config.h index 33caf71a2be..abe3fcf2e65 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/config/f4/dma_config.h +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f4/dma_config.h @@ -211,7 +211,13 @@ extern "C" { #endif /* DMA2 stream0 */ -#if defined(BSP_ADC1_USING_DMA) && !defined(ADC1_DMA_INSTANCE) +#if defined(BSP_SPI1_RX_USING_DMA) && !defined(SPI1_RX_DMA_INSTANCE) +#define SPI1_DMA_RX_IRQHandler DMA2_Stream0_IRQHandler +#define SPI1_RX_DMA_RCC RCC_AHB1ENR_DMA2EN +#define SPI1_RX_DMA_INSTANCE DMA2_Stream0 +#define SPI1_RX_DMA_CHANNEL DMA_CHANNEL_3 +#define SPI1_RX_DMA_IRQ DMA2_Stream0_IRQn +#elif defined(BSP_ADC1_USING_DMA) && !defined(ADC1_DMA_INSTANCE) #define ADC1_DMA_IRQHandler DMA2_Stream0_IRQHandler #define ADC1_DMA_RCC RCC_AHB1ENR_DMA2EN #define ADC1_DMA_INSTANCE DMA2_Stream0 @@ -223,12 +229,6 @@ extern "C" { #define ADC3_DMA_INSTANCE DMA2_Stream0 #define ADC3_DMA_CHANNEL DMA_CHANNEL_2 #define ADC3_DMA_IRQ DMA2_Stream0_IRQn -#elif defined(BSP_SPI1_RX_USING_DMA) && !defined(SPI1_RX_DMA_INSTANCE) -#define SPI1_DMA_RX_IRQHandler DMA2_Stream0_IRQHandler -#define SPI1_RX_DMA_RCC RCC_AHB1ENR_DMA2EN -#define SPI1_RX_DMA_INSTANCE DMA2_Stream0 -#define SPI1_RX_DMA_CHANNEL DMA_CHANNEL_3 -#define SPI1_RX_DMA_IRQ DMA2_Stream0_IRQn #elif defined(BSP_SPI4_RX_USING_DMA) && !defined(SPI4_RX_DMA_INSTANCE) #define SPI4_DMA_RX_IRQHandler DMA2_Stream0_IRQHandler #define SPI4_RX_DMA_RCC RCC_AHB1ENR_DMA2EN @@ -283,18 +283,18 @@ extern "C" { #define MEMTOMEM2_DMA_INSTANCE DMA2_Stream2 #define MEMTOMEM2_DMA_CHANNEL DMA_CHANNEL_2 #define MEMTOMEM2_DMA_IRQ DMA2_Stream2_IRQn -#elif defined(BSP_SPI1_RX_USING_DMA) && !defined(SPI1_RX_DMA_INSTANCE) -#define SPI1_DMA_RX_IRQHandler DMA2_Stream2_IRQHandler -#define SPI1_RX_DMA_RCC RCC_AHB1ENR_DMA2EN -#define SPI1_RX_DMA_INSTANCE DMA2_Stream2 -#define SPI1_RX_DMA_CHANNEL DMA_CHANNEL_3 -#define SPI1_RX_DMA_IRQ DMA2_Stream2_IRQn #elif defined(BSP_UART1_RX_USING_DMA) && !defined(UART1_RX_DMA_INSTANCE) #define UART1_DMA_RX_IRQHandler DMA2_Stream2_IRQHandler #define UART1_RX_DMA_RCC RCC_AHB1ENR_DMA2EN #define UART1_RX_DMA_INSTANCE DMA2_Stream2 #define UART1_RX_DMA_CHANNEL DMA_CHANNEL_4 #define UART1_RX_DMA_IRQ DMA2_Stream2_IRQn +#elif defined(BSP_SPI1_RX_USING_DMA) && !defined(SPI1_RX_DMA_INSTANCE) +#define SPI1_DMA_RX_IRQHandler DMA2_Stream2_IRQHandler +#define SPI1_RX_DMA_RCC RCC_AHB1ENR_DMA2EN +#define SPI1_RX_DMA_INSTANCE DMA2_Stream2 +#define SPI1_RX_DMA_CHANNEL DMA_CHANNEL_3 +#define SPI1_RX_DMA_IRQ DMA2_Stream2_IRQn #elif defined(BSP_UART6_RX_USING_DMA) && !defined(UART6_RX_DMA_INSTANCE) #define UART6_DMA_RX_IRQHandler DMA2_Stream2_IRQHandler #define UART6_RX_DMA_RCC RCC_AHB1ENR_DMA2EN diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/f7/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f7/adc_config_v2.h new file mode 100644 index 00000000000..7273dafb92c --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f7/adc_config_v2.h @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32f7 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32F7 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32F7. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32F7. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32F7. */ +#if defined(ADC_SAMPLETIME_112CYCLES) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_112CYCLES +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_112CYCLES) */ + + +/** @brief Maximum regular sequence length supported by the STM32F7 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +/** @brief STM32F7 legacy internal ADC source logical channel overrides. */ +#if !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_TEMP_LOGICAL_OVERRIDE 16 +#define STM32_ADC_VREF_LOGICAL_OVERRIDE 17 +#define STM32_ADC_VBAT_LOGICAL_OVERRIDE 18 +#endif /* !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#define STM32_ADC_HAS_CONFIG_OFFSET 1 + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32F7 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32F7 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32F7 ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/g0/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/g0/adc_config_v2.h new file mode 100644 index 00000000000..9ea98c58648 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/g0/adc_config_v2.h @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-05-27 wdfk-prog add stm32g0 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32G0 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32G0. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32G0. */ +#if defined(ADC_DATAALIGN_RIGHT) +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT +#else +#define ADC_DEFAULT_DATA_ALIGN 0U +#endif /* defined(ADC_DATAALIGN_RIGHT) */ + +/** @brief Default ADC resolution for STM32G0. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32G0. */ +#if defined(ADC_SAMPLETIME_160CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_160CYCLES_5 +#elif defined(ADC_SAMPLETIME_79CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_79CYCLES_5 +#elif defined(ADC_SAMPLETIME_39CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_39CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_160CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32G0 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32G0 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/g4/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/g4/adc_config_v2.h new file mode 100644 index 00000000000..3556ee03473 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/g4/adc_config_v2.h @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32g4 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32G4 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32G4. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32G4. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32G4. */ +#if defined(ADC_SAMPLETIME_247CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_247CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_247CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32G4 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +#if defined(ADC_CHANNEL_VBAT) +/** @brief STM32G4 VBAT HAL ADC channel for the multi-instance route. */ +#define STM32_ADC_VBAT_HAL_CHANNEL ADC_CHANNEL_VBAT +/** @brief STM32G4 ADC instances that can sample VBAT. */ +#define STM32_ADC_VBAT_INSTANCE_MASK ((1UL << 0) | (1UL << 2) | (1UL << 4)) +#endif /* defined(ADC_CHANNEL_VBAT) */ + +#if defined(ADC_CHANNEL_VREFINT) +/** @brief STM32G4 VREFINT HAL ADC channel for the multi-instance route. */ +#define STM32_ADC_VREF_HAL_CHANNEL ADC_CHANNEL_VREFINT +/** @brief STM32G4 ADC instances that can sample VREFINT. */ +#define STM32_ADC_VREF_INSTANCE_MASK ((1UL << 0) | (1UL << 2) | (1UL << 3) | (1UL << 4)) +#endif /* defined(ADC_CHANNEL_VREFINT) */ + +#if defined(ADC_CHANNEL_TEMPSENSOR_ADC5) +/** @brief STM32G4 alternate temperature sensor HAL ADC channel. */ +#define STM32_ADC_TEMP_ALT_HAL_CHANNEL ADC_CHANNEL_TEMPSENSOR_ADC5 +/** @brief STM32G4 ADC instances that can sample the alternate temperature sensor channel. */ +#define STM32_ADC_TEMP_ALT_INSTANCE_MASK (1UL << 4) +#endif /* defined(ADC_CHANNEL_TEMPSENSOR_ADC5) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32G4 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32G4 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32G4 ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef BSP_USING_ADC4 +/** @brief Default STM32G4 ADC4 V2 object initializer. */ +#define ADC4_V2_CONFIG \ + { \ + .name = "adc4", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC4, \ + }, \ + ADC4_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC4 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/h5/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/h5/adc_config_v2.h new file mode 100644 index 00000000000..eca8588e7ea --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/h5/adc_config_v2.h @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-05-27 wdfk-prog add stm32h5 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32H5 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32H5. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32H5. */ +#if defined(ADC_DATAALIGN_RIGHT) +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT +#else +#define ADC_DEFAULT_DATA_ALIGN 0U +#endif /* defined(ADC_DATAALIGN_RIGHT) */ + +/** @brief Default ADC resolution for STM32H5. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32H5. */ +#if defined(ADC_SAMPLETIME_814CYCLES) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_814CYCLES +#elif defined(ADC_SAMPLETIME_810CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_810CYCLES_5 +#elif defined(ADC_SAMPLETIME_247CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_247CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_814CYCLES) */ + + +/** @brief Maximum regular sequence length supported by the STM32H5 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +#if defined(ADC_CHANNEL_VBAT) +/** @brief STM32H5 VBAT HAL ADC channel for the series-specific route. */ +#define STM32_ADC_VBAT_HAL_CHANNEL ADC_CHANNEL_VBAT +#if defined(ADC2) +/** @brief STM32H5 ADC instances that can sample VBAT. */ +#define STM32_ADC_VBAT_INSTANCE_MASK (1UL << 1) +#else +/** @brief STM32H5 ADC instances that can sample VBAT. */ +#define STM32_ADC_VBAT_INSTANCE_MASK (1UL << 0) +#endif /* defined(ADC2) */ +#endif /* defined(ADC_CHANNEL_VBAT) */ + +#if defined(ADC_CHANNEL_VBAT_ADC4) +/** @brief STM32H5 alternate VBAT HAL ADC channel. */ +#define STM32_ADC_VBAT_ALT_HAL_CHANNEL ADC_CHANNEL_VBAT_ADC4 +/** @brief STM32H5 ADC instances that can sample the alternate VBAT channel. */ +#define STM32_ADC_VBAT_ALT_INSTANCE_MASK (1UL << 2) +#endif /* defined(ADC_CHANNEL_VBAT_ADC4) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32H5 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ +#ifdef BSP_USING_ADC2 +/** @brief Default STM32H5 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/h7/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/h7/adc_config_v2.h new file mode 100644 index 00000000000..707fc29d2d5 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/h7/adc_config_v2.h @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32h7 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32H7 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32H7. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32H7. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32H7. */ +#if defined(ADC_SAMPLETIME_810CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_810CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_810CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32H7 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +#if defined(ADC3) +/** @brief STM32H7 default internal ADC source instance mask. */ +#define STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK (1UL << 2) +#else +/** @brief STM32H7 default internal ADC source instance mask. */ +#define STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK 0UL +#endif /* defined(ADC3) */ + +#if defined(ADC_CHANNEL_TEMPSENSOR) +/** @brief STM32H7 temperature sensor HAL ADC channel for the default internal route. */ +#define STM32_ADC_TEMP_HAL_CHANNEL ADC_CHANNEL_TEMPSENSOR +#endif /* defined(ADC_CHANNEL_TEMPSENSOR) */ + +#if defined(ADC_CHANNEL_VBAT) +/** @brief STM32H7 VBAT HAL ADC channel for the default internal route. */ +#define STM32_ADC_VBAT_HAL_CHANNEL ADC_CHANNEL_VBAT +#endif /* defined(ADC_CHANNEL_VBAT) */ + +#if defined(ADC_CHANNEL_VREFINT) +/** @brief STM32H7 VREFINT HAL ADC channel for the default internal route. */ +#define STM32_ADC_VREF_HAL_CHANNEL ADC_CHANNEL_VREFINT +#endif /* defined(ADC_CHANNEL_VREFINT) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32H7 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32H7 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32H7 ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/h7rs/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/h7rs/adc_config_v2.h new file mode 100644 index 00000000000..9909efa3e71 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/h7rs/adc_config_v2.h @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-05-27 wdfk-prog add stm32h7rs adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32H7RS ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32H7RS. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32H7RS. */ +#if defined(ADC_DATAALIGN_RIGHT) +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT +#else +#define ADC_DEFAULT_DATA_ALIGN 0U +#endif /* defined(ADC_DATAALIGN_RIGHT) */ + +/** @brief Default ADC resolution for STM32H7RS. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32H7RS. */ +#if defined(ADC_SAMPLETIME_810CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_810CYCLES_5 +#elif defined(ADC_SAMPLETIME_814CYCLES) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_814CYCLES +#elif defined(ADC_SAMPLETIME_387CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_387CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_810CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32H7RS driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32H7RS ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ +#ifdef BSP_USING_ADC2 +/** @brief Default STM32H7RS ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ +#ifdef BSP_USING_ADC3 +/** @brief Default STM32H7RS ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/l0/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/l0/adc_config_v2.h new file mode 100644 index 00000000000..437dcb17537 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/l0/adc_config_v2.h @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-05-27 wdfk-prog add stm32l0 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32L0 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32L0. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32L0. */ +#if defined(ADC_DATAALIGN_RIGHT) +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT +#else +#define ADC_DEFAULT_DATA_ALIGN 0U +#endif /* defined(ADC_DATAALIGN_RIGHT) */ + +/** @brief Default ADC resolution for STM32L0. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32L0. */ +#if defined(ADC_SAMPLETIME_160CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_160CYCLES_5 +#elif defined(ADC_SAMPLETIME_79CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_79CYCLES_5 +#elif defined(ADC_SAMPLETIME_39CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_39CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_160CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32L0 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +/** @brief STM32L0 legacy internal ADC source logical channel overrides. */ +#if !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_TEMP_LOGICAL_OVERRIDE 16 +#define STM32_ADC_VREF_LOGICAL_OVERRIDE 17 +#define STM32_ADC_VBAT_LOGICAL_OVERRIDE 18 +#endif /* !defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) && !defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32L0 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/l4/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/l4/adc_config_v2.h new file mode 100644 index 00000000000..98d9e621369 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/l4/adc_config_v2.h @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32l4 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32L4 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32L4. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32L4. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32L4. */ +#if defined(ADC_SAMPLETIME_247CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_247CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_247CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32L4 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +#if defined(ADC_CHANNEL_TEMPSENSOR) +/** @brief STM32L4 temperature sensor HAL ADC channel for the multi-instance route. */ +#define STM32_ADC_TEMP_HAL_CHANNEL ADC_CHANNEL_TEMPSENSOR +/** @brief STM32L4 ADC instances that can sample temperature sensor. */ +#define STM32_ADC_TEMP_INSTANCE_MASK ((1UL << 0) | (1UL << 2)) +#endif /* defined(ADC_CHANNEL_TEMPSENSOR) */ + +#if defined(ADC_CHANNEL_VBAT) +/** @brief STM32L4 VBAT HAL ADC channel for the multi-instance route. */ +#define STM32_ADC_VBAT_HAL_CHANNEL ADC_CHANNEL_VBAT +/** @brief STM32L4 ADC instances that can sample VBAT. */ +#define STM32_ADC_VBAT_INSTANCE_MASK ((1UL << 0) | (1UL << 2)) +#endif /* defined(ADC_CHANNEL_VBAT) */ + +#if defined(ADC_CHANNEL_VREFINT) +/** @brief STM32L4 VREFINT HAL ADC channel for the multi-instance route. */ +#define STM32_ADC_VREF_HAL_CHANNEL ADC_CHANNEL_VREFINT +/** @brief STM32L4 ADC instances that can sample VREFINT. */ +#define STM32_ADC_VREF_INSTANCE_MASK ((1UL << 0) | (1UL << 1) | (1UL << 2)) +#endif /* defined(ADC_CHANNEL_VREFINT) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#define STM32_ADC_HAS_SIMPLE_CALIBRATION 1 + + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32L4 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32L4 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32L4 ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/l5/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/l5/adc_config_v2.h new file mode 100644 index 00000000000..88fbfdbea99 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/l5/adc_config_v2.h @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-05-27 wdfk-prog add stm32l5 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32L5 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32L5. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32L5. */ +#if defined(ADC_DATAALIGN_RIGHT) +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT +#else +#define ADC_DEFAULT_DATA_ALIGN 0U +#endif /* defined(ADC_DATAALIGN_RIGHT) */ + +/** @brief Default ADC resolution for STM32L5. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32L5. */ +#if defined(ADC_SAMPLETIME_247CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_247CYCLES_5 +#elif defined(ADC_SAMPLETIME_640CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_640CYCLES_5 +#elif defined(ADC_SAMPLETIME_160CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_160CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_247CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32L5 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#define STM32_ADC_HAS_SIMPLE_CALIBRATION 1 + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32L5 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ +#ifdef BSP_USING_ADC2 +/** @brief Default STM32L5 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/mp1/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/mp1/adc_config_v2.h new file mode 100644 index 00000000000..1789573e4dd --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/mp1/adc_config_v2.h @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32mp1 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32MP1 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32MP1. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32MP1. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32MP1. */ +#if defined(ADC_SAMPLETIME_810CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_810CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_810CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32MP1 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +#if defined(ADC_CHANNEL_VBAT) +/** @brief STM32MP1 VBAT HAL ADC channel for the ADC2 route. */ +#define STM32_ADC_VBAT_HAL_CHANNEL ADC_CHANNEL_VBAT +/** @brief STM32MP1 ADC instances that can sample VBAT. */ +#define STM32_ADC_VBAT_INSTANCE_MASK (1UL << 1) +#endif /* defined(ADC_CHANNEL_VBAT) */ + +#if defined(ADC_CHANNEL_VREFINT) +/** @brief STM32MP1 VREFINT HAL ADC channel for the ADC2 route. */ +#define STM32_ADC_VREF_HAL_CHANNEL ADC_CHANNEL_VREFINT +/** @brief STM32MP1 ADC instances that can sample VREFINT. */ +#define STM32_ADC_VREF_INSTANCE_MASK (1UL << 1) +#endif /* defined(ADC_CHANNEL_VREFINT) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32MP1 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32MP1 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32MP1 ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/u5/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/u5/adc_config_v2.h new file mode 100644 index 00000000000..fbc97bc98f5 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/u5/adc_config_v2.h @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32u5 adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32U5 ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32U5. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32U5. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32U5. */ +#if defined(ADC_SAMPLETIME_814CYCLES) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_814CYCLES +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_814CYCLES) */ + + +/** @brief Maximum regular sequence length supported by the STM32U5 driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 internal-channel routing policy for this STM32 series. */ +/** @brief STM32U5 default internal ADC source instance mask. */ +#define STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK ((1UL << 0) | (1UL << 1)) + +#if defined(ADC_CHANNEL_TEMPSENSOR) +/** @brief STM32U5 temperature sensor HAL ADC channel for the default internal route. */ +#define STM32_ADC_TEMP_HAL_CHANNEL ADC_CHANNEL_TEMPSENSOR +#endif /* defined(ADC_CHANNEL_TEMPSENSOR) */ + +#if defined(ADC_CHANNEL_VBAT) +/** @brief STM32U5 VBAT HAL ADC channel for the default internal route. */ +#define STM32_ADC_VBAT_HAL_CHANNEL ADC_CHANNEL_VBAT +#endif /* defined(ADC_CHANNEL_VBAT) */ + +#if defined(ADC_CHANNEL_VREFINT) +/** @brief STM32U5 VREFINT HAL ADC channel for the multi-instance route. */ +#define STM32_ADC_VREF_HAL_CHANNEL ADC_CHANNEL_VREFINT +/** @brief STM32U5 ADC instances that can sample VREFINT. */ +#define STM32_ADC_VREF_INSTANCE_MASK ((1UL << 0) | (1UL << 1) | (1UL << 3)) +#endif /* defined(ADC_CHANNEL_VREFINT) */ + +#if defined(ADC_CHANNEL_TEMPSENSOR_ADC4) +/** @brief STM32U5 alternate temperature sensor HAL ADC channel. */ +#define STM32_ADC_TEMP_ALT_HAL_CHANNEL ADC_CHANNEL_TEMPSENSOR_ADC4 +/** @brief STM32U5 ADC instances that can sample the alternate temperature sensor channel. */ +#define STM32_ADC_TEMP_ALT_INSTANCE_MASK (1UL << 3) +#endif /* defined(ADC_CHANNEL_TEMPSENSOR_ADC4) */ + +#if defined(ADC_CHANNEL_VBAT_ADC4) +/** @brief STM32U5 alternate VBAT HAL ADC channel. */ +#define STM32_ADC_VBAT_ALT_HAL_CHANNEL ADC_CHANNEL_VBAT_ADC4 +/** @brief STM32U5 ADC instances that can sample the alternate VBAT channel. */ +#define STM32_ADC_VBAT_ALT_INSTANCE_MASK (1UL << 3) +#endif /* defined(ADC_CHANNEL_VBAT_ADC4) */ + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#define STM32_ADC_NEEDS_ANALOG_SUPPLY 1 +#define STM32_ADC_VREF_NEEDS_INSTANCE 1 + + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32U5 ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32U5 ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32U5 ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef BSP_USING_ADC4 +/** @brief Default STM32U5 ADC4 V2 object initializer. */ +#define ADC4_V2_CONFIG \ + { \ + .name = "adc4", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC4, \ + }, \ + ADC4_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC4 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/wb/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/wb/adc_config_v2.h new file mode 100644 index 00000000000..6895ecae0c4 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/wb/adc_config_v2.h @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32wb adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32WB ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32WB. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32WB. */ +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT + +/** @brief Default ADC resolution for STM32 ADC V2. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32WB. */ +#if defined(ADC_SAMPLETIME_2CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_2CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_2CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32WB driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#define STM32_ADC_HAS_SIMPLE_CALIBRATION 1 + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32WB ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef BSP_USING_ADC2 +/** @brief Default STM32WB ADC2 V2 object initializer. */ +#define ADC2_V2_CONFIG \ + { \ + .name = "adc2", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC2, \ + }, \ + ADC2_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC2 */ + +#ifdef BSP_USING_ADC3 +/** @brief Default STM32WB ADC3 V2 object initializer. */ +#define ADC3_V2_CONFIG \ + { \ + .name = "adc3", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC3, \ + }, \ + ADC3_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC3 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/config/wl/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/wl/adc_config_v2.h new file mode 100644 index 00000000000..3be4a47f759 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/wl/adc_config_v2.h @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-05-27 wdfk-prog add stm32wl adc v2 configuration + */ + +/** + * @file adc_config_v2.h + * @brief STM32WL ADC V2 configuration defaults. + */ + +#ifndef __ADC_CONFIG_V2_H__ +#define __ADC_CONFIG_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @brief Default ADC clock prescaler for STM32WL. */ +#if defined(ADC_CLOCK_SYNC_PCLK_DIV4) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_SYNC_PCLK_DIV4 +#elif defined(ADC_CLOCK_ASYNC_DIV1) +#define ADC_DEFAULT_CLOCK_PRESCALER ADC_CLOCK_ASYNC_DIV1 +#endif /* defined(ADC_CLOCK_SYNC_PCLK_DIV4) */ + +/** @brief Default ADC data alignment for STM32WL. */ +#if defined(ADC_DATAALIGN_RIGHT) +#define ADC_DEFAULT_DATA_ALIGN ADC_DATAALIGN_RIGHT +#else +#define ADC_DEFAULT_DATA_ALIGN 0U +#endif /* defined(ADC_DATAALIGN_RIGHT) */ + +/** @brief Default ADC resolution for STM32WL. */ +#ifdef ADC_RESOLUTION_12B +#define ADC_DEFAULT_RESOLUTION ADC_RESOLUTION_12B +#else +#define ADC_DEFAULT_RESOLUTION 0U +#endif /* ADC_RESOLUTION_12B */ + +/** @brief Default ADC sampling time for STM32WL. */ +#if defined(ADC_SAMPLETIME_160CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_160CYCLES_5 +#elif defined(ADC_SAMPLETIME_247CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_247CYCLES_5 +#elif defined(ADC_SAMPLETIME_640CYCLES_5) +#define ADC_DEFAULT_SAMPLING_TIME ADC_SAMPLETIME_640CYCLES_5 +#else +#define ADC_DEFAULT_SAMPLING_TIME 0U +#endif /* defined(ADC_SAMPLETIME_160CYCLES_5) */ + + +/** @brief Maximum regular sequence length supported by the STM32WL driver. */ +#define STM32_ADC_MAX_SEQUENCE 16 + +/** @brief Whether sequence mode is compiled in. */ +#define STM32_ADC_USING_SEQUENCE 1 + +/** @brief Whether any ADC instance requests a stream DMA backend. */ +#if defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || \ + defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) +#define STM32_ADC_HAS_STREAM_DMA_BSP 1 +#else +#define STM32_ADC_HAS_STREAM_DMA_BSP 0 +#endif /* defined(BSP_ADC1_USING_DMA) || defined(BSP_ADC2_USING_DMA) || defined(BSP_ADC3_USING_DMA) || defined(BSP_ADC4_USING_DMA) */ + +/** @brief Whether stream mode is compiled in through the STM32 DMA-backed backend. */ +#if defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP +#define STM32_ADC_USING_STREAM 1 +#else +#define STM32_ADC_USING_STREAM 0 +#endif /* defined(RT_ADC_USING_STREAM) && defined(HAL_DMA_MODULE_ENABLED) && STM32_ADC_HAS_STREAM_DMA_BSP */ + +/** @brief Whether the compiled STM32 ADC stream backend uses DMA transport. */ +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM + +#if STM32_ADC_USING_STREAM +#if defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) +#if defined(ADC1_DMA_REQUEST) +#define STM32_ADC1_DMA_REQUEST_VALUE ADC1_DMA_REQUEST +#else +#define STM32_ADC1_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC1_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_CHANNEL) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + ADC1_DMA_CHANNEL, + STM32_ADC1_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC1_DMA_REQUEST) +#define ADC1_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC1_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC1_DMA_INSTANCE, + ADC1_DMA_RCC, + ADC1_DMA_IRQ, + 0U, + ADC1_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC1_DMA_REQUEST) */ +#endif /* defined(BSP_ADC1_USING_DMA) && defined(ADC1_DMA_INSTANCE) && defined(ADC1_DMA_RCC) && defined(ADC1_DMA_IRQ) */ + +#if defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) +#if defined(ADC2_DMA_REQUEST) +#define STM32_ADC2_DMA_REQUEST_VALUE ADC2_DMA_REQUEST +#else +#define STM32_ADC2_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC2_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_CHANNEL) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + ADC2_DMA_CHANNEL, + STM32_ADC2_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC2_DMA_REQUEST) +#define ADC2_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC2_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC2_DMA_INSTANCE, + ADC2_DMA_RCC, + ADC2_DMA_IRQ, + 0U, + ADC2_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC2_DMA_REQUEST) */ +#endif /* defined(BSP_ADC2_USING_DMA) && defined(ADC2_DMA_INSTANCE) && defined(ADC2_DMA_RCC) && defined(ADC2_DMA_IRQ) */ + +#if defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) +#if defined(ADC3_DMA_REQUEST) +#define STM32_ADC3_DMA_REQUEST_VALUE ADC3_DMA_REQUEST +#else +#define STM32_ADC3_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC3_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_CHANNEL) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + ADC3_DMA_CHANNEL, + STM32_ADC3_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC3_DMA_REQUEST) +#define ADC3_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC3_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC3_DMA_INSTANCE, + ADC3_DMA_RCC, + ADC3_DMA_IRQ, + 0U, + ADC3_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC3_DMA_REQUEST) */ +#endif /* defined(BSP_ADC3_USING_DMA) && defined(ADC3_DMA_INSTANCE) && defined(ADC3_DMA_RCC) && defined(ADC3_DMA_IRQ) */ + +#if defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) +#if defined(ADC4_DMA_REQUEST) +#define STM32_ADC4_DMA_REQUEST_VALUE ADC4_DMA_REQUEST +#else +#define STM32_ADC4_DMA_REQUEST_VALUE 0U +#endif /* defined(ADC4_DMA_REQUEST) */ + +#if defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_CHANNEL) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + ADC4_DMA_CHANNEL, + STM32_ADC4_DMA_REQUEST_VALUE, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#elif defined(ADC4_DMA_REQUEST) +#define ADC4_V2_HAS_DMA_CONFIG 1 +static const struct stm32_dma_config ADC4_DMA_CONFIG = + STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(ADC4_DMA_INSTANCE, + ADC4_DMA_RCC, + ADC4_DMA_IRQ, + 0U, + ADC4_DMA_REQUEST, + STM32_DMA_DEFAULT_PRIORITY, + STM32_DMA_DEFAULT_PREEMPT_PRIORITY, + STM32_DMA_DEFAULT_SUB_PRIORITY); +#endif /* defined(STM32_DMA_USES_GPDMA) && defined(ADC4_DMA_REQUEST) */ +#endif /* defined(BSP_ADC4_USING_DMA) && defined(ADC4_DMA_INSTANCE) && defined(ADC4_DMA_RCC) && defined(ADC4_DMA_IRQ) */ + +#endif /* STM32_ADC_USING_STREAM */ + +#if defined(ADC1_V2_HAS_DMA_CONFIG) +#define ADC1_V2_DMA_CONFIG_FIELD .dma_rx = &ADC1_DMA_CONFIG, +#else +#define ADC1_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC1_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC2_V2_HAS_DMA_CONFIG) +#define ADC2_V2_DMA_CONFIG_FIELD .dma_rx = &ADC2_DMA_CONFIG, +#else +#define ADC2_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC2_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC3_V2_HAS_DMA_CONFIG) +#define ADC3_V2_DMA_CONFIG_FIELD .dma_rx = &ADC3_DMA_CONFIG, +#else +#define ADC3_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC3_V2_HAS_DMA_CONFIG) */ + +#if defined(ADC4_V2_HAS_DMA_CONFIG) +#define ADC4_V2_DMA_CONFIG_FIELD .dma_rx = &ADC4_DMA_CONFIG, +#else +#define ADC4_V2_DMA_CONFIG_FIELD +#endif /* defined(ADC4_V2_HAS_DMA_CONFIG) */ + + + +/* ADC V2 HAL feature policy for this STM32 series. */ +#if defined(ADC_DEFAULT_DATA_ALIGN) +#define STM32_ADC_HAS_INIT_DATA_ALIGN 1 +#endif /* defined(ADC_DEFAULT_DATA_ALIGN) */ + +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) +#define STM32_ADC_HAS_INIT_EXT_TRIG_EDGE 1 +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + +#define STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS 1 + +#define STM32_ADC_HAS_INIT_NBR_OF_CONVERSION 1 +#define STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION 1 + +#if defined(ADC_EOC_SINGLE_CONV) +#define STM32_ADC_HAS_INIT_EOC_SELECTION 1 +#endif /* defined(ADC_EOC_SINGLE_CONV) */ + +#define STM32_ADC_HAS_SIMPLE_CALIBRATION 1 + +#ifdef BSP_USING_ADC1 +/** @brief Default STM32WL ADC1 V2 object initializer. */ +#define ADC1_V2_CONFIG \ + { \ + .name = "adc1", \ + .config = \ + { \ + .sampling_time = ADC_DEFAULT_SAMPLING_TIME, \ + .resolution = ADC_DEFAULT_RESOLUTION, \ + .data_align = ADC_DEFAULT_DATA_ALIGN, \ + .input_modes = RT_ADC_INPUT_MODE_SINGLE_ENDED, \ + .oversampling_ratio = 0U, \ + .oversampling_right_shift = 0U, \ + }, \ + .handle = \ + { \ + .Instance = ADC1, \ + }, \ + ADC1_V2_DMA_CONFIG_FIELD \ + } +#endif /* BSP_USING_ADC1 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __ADC_CONFIG_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c new file mode 100644 index 00000000000..6c3c8bb5284 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c @@ -0,0 +1,2231 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32 adc v2 driver implementation + */ + +/** + * @file drv_adc_v2.c + * @brief STM32 ADC V2 driver implementation. + */ +#include + +#if defined(RT_USING_ADC_V2) + +#include "drv_config.h" +#include "drv_adc_v2_private.h" + +#if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) || defined(BSP_USING_ADC4) + +#define DRV_DEBUG +#define LOG_TAG "drv.adc" +#include + +/** + * @brief Apply the STM32 private oversampling configuration to the ADC init structure. + * @param adc Pointer to the STM32 ADC device object. + * @return Operation status. + */ +static rt_err_t stm32_adc_apply_oversampling(struct stm32_adc *adc) +{ +#if defined(STM32_ADC_HAS_HW_OVERSAMPLING) + if (adc->config.oversampling_ratio == 0U) + { + adc->handle.Init.OversamplingMode = DISABLE; + return RT_EOK; + } + + adc->handle.Init.OversamplingMode = ENABLE; + adc->handle.Init.Oversampling.Ratio = adc->config.oversampling_ratio; + adc->handle.Init.Oversampling.RightBitShift = adc->config.oversampling_right_shift; + adc->handle.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER; + adc->handle.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE; + return RT_EOK; +#else + return (adc->config.oversampling_ratio == 0U) ? RT_EOK : -RT_ENOSYS; +#endif /* defined(STM32_ADC_HAS_HW_OVERSAMPLING) */ +} + +/** + * @brief STM32 ADC object indexes. + */ +enum stm32_adc_index +{ +#ifdef BSP_USING_ADC1 + ADC1_INDEX, +#endif /* BSP_USING_ADC1 */ +#ifdef BSP_USING_ADC2 + ADC2_INDEX, +#endif /* BSP_USING_ADC2 */ +#ifdef BSP_USING_ADC3 + ADC3_INDEX, +#endif /* BSP_USING_ADC3 */ +#ifdef BSP_USING_ADC4 + ADC4_INDEX, +#endif /* BSP_USING_ADC4 */ +}; + +/** + * @brief STM32 ADC device table. + */ +static struct stm32_adc stm32_adc_obj[] = { +#ifdef BSP_USING_ADC1 + ADC1_V2_CONFIG, +#endif /* BSP_USING_ADC1 */ +#ifdef BSP_USING_ADC2 + ADC2_V2_CONFIG, +#endif /* BSP_USING_ADC2 */ +#ifdef BSP_USING_ADC3 + ADC3_V2_CONFIG, +#endif /* BSP_USING_ADC3 */ +#ifdef BSP_USING_ADC4 + ADC4_V2_CONFIG, +#endif /* BSP_USING_ADC4 */ +}; + +/** + * @brief ADC hardware channel mapping table. + */ +static const uint32_t stm32_adc_channel_table[STM32_ADC_MAX_CHANNELS] = { + ADC_CHANNEL_0, + ADC_CHANNEL_1, + ADC_CHANNEL_2, + ADC_CHANNEL_3, + ADC_CHANNEL_4, + ADC_CHANNEL_5, + ADC_CHANNEL_6, + ADC_CHANNEL_7, + ADC_CHANNEL_8, + ADC_CHANNEL_9, + ADC_CHANNEL_10, + ADC_CHANNEL_11, + ADC_CHANNEL_12, + ADC_CHANNEL_13, + ADC_CHANNEL_14, + ADC_CHANNEL_15, +#if STM32_ADC_MAX_CHANNELS > 16 + STM32_ADC_CHANNEL_16, +#endif /* STM32_ADC_MAX_CHANNELS > 16 */ +#if STM32_ADC_MAX_CHANNELS > 17 + STM32_ADC_CHANNEL_17, +#endif /* STM32_ADC_MAX_CHANNELS > 17 */ +#if STM32_ADC_MAX_CHANNELS > 18 + STM32_ADC_CHANNEL_18, +#endif /* STM32_ADC_MAX_CHANNELS > 18 */ +#if STM32_ADC_MAX_CHANNELS > 19 + STM32_ADC_CHANNEL_19, +#endif /* STM32_ADC_MAX_CHANNELS > 19 */ +#if STM32_ADC_MAX_CHANNELS > 20 + STM32_ADC_CHANNEL_20, +#endif /* STM32_ADC_MAX_CHANNELS > 20 */ +#if STM32_ADC_MAX_CHANNELS > 21 + STM32_ADC_CHANNEL_21, +#endif /* STM32_ADC_MAX_CHANNELS > 21 */ +#if STM32_ADC_MAX_CHANNELS > 22 + STM32_ADC_CHANNEL_22, +#endif /* STM32_ADC_MAX_CHANNELS > 22 */ +#if STM32_ADC_MAX_CHANNELS > 23 + STM32_ADC_CHANNEL_23, +#endif /* STM32_ADC_MAX_CHANNELS > 23 */ +#if STM32_ADC_MAX_CHANNELS > 24 + STM32_ADC_CHANNEL_24, +#endif /* STM32_ADC_MAX_CHANNELS > 24 */ +#if STM32_ADC_MAX_CHANNELS > 25 + STM32_ADC_CHANNEL_25, +#endif /* STM32_ADC_MAX_CHANNELS > 25 */ +#if STM32_ADC_MAX_CHANNELS > 26 + STM32_ADC_CHANNEL_26, +#endif /* STM32_ADC_MAX_CHANNELS > 26 */ +#if STM32_ADC_MAX_CHANNELS > 27 + STM32_ADC_CHANNEL_27, +#endif /* STM32_ADC_MAX_CHANNELS > 27 */ +#if STM32_ADC_MAX_CHANNELS > 28 + STM32_ADC_CHANNEL_28, +#endif /* STM32_ADC_MAX_CHANNELS > 28 */ +#if STM32_ADC_MAX_CHANNELS > 29 + STM32_ADC_CHANNEL_29, +#endif /* STM32_ADC_MAX_CHANNELS > 29 */ +#if STM32_ADC_MAX_CHANNELS > 30 + STM32_ADC_CHANNEL_30, +#endif /* STM32_ADC_MAX_CHANNELS > 30 */ +#if STM32_ADC_MAX_CHANNELS > 31 + STM32_ADC_CHANNEL_31, +#endif /* STM32_ADC_MAX_CHANNELS > 31 */ +}; + +/** + * @brief STM32 internal ADC channel capability entry. + */ +struct stm32_adc_internal_channel +{ + int logical_channel; /**< RT-Thread logical channel number, or negative if unsupported. */ + uint32_t hal_channel; /**< Primary HAL channel identifier. */ + rt_uint32_t instance_mask; /**< ADC instances that can use the primary HAL channel. */ + uint32_t alternate_hal_channel; /**< Alternate HAL channel identifier for instance-specific mappings. */ + rt_uint32_t alternate_instance_mask; /**< ADC instances that can use the alternate HAL channel. */ +}; + +/** + * @brief STM32 internal ADC channel capability table. + */ +static const struct stm32_adc_internal_channel stm32_adc_internal_channels[] = { + { STM32_ADC_TEMP_CHANNEL, STM32_ADC_TEMP_HAL_CHANNEL, STM32_ADC_TEMP_INSTANCE_MASK, + STM32_ADC_TEMP_ALT_HAL_CHANNEL, STM32_ADC_TEMP_ALT_INSTANCE_MASK }, + { STM32_ADC_VBAT_CHANNEL, STM32_ADC_VBAT_HAL_CHANNEL, STM32_ADC_VBAT_INSTANCE_MASK, + STM32_ADC_VBAT_ALT_HAL_CHANNEL, STM32_ADC_VBAT_ALT_INSTANCE_MASK }, + { STM32_ADC_VREF_CHANNEL, STM32_ADC_VREF_HAL_CHANNEL, STM32_ADC_VREF_INSTANCE_MASK, + STM32_ADC_VREF_ALT_HAL_CHANNEL, STM32_ADC_VREF_ALT_INSTANCE_MASK }, +}; + +/** + * @brief Check whether an ADC channel is a valid HAL channel identifier. + * @param hal_channel HAL channel identifier. + * @return RT_TRUE if valid, otherwise RT_FALSE. + */ +static rt_bool_t stm32_adc_hal_channel_valid(uint32_t hal_channel) +{ + return (hal_channel != STM32_ADC_INVALID_CHANNEL) ? RT_TRUE : RT_FALSE; +} + +/** + * @brief Check whether an ADC peripheral instance matches an instance mask. + * @param instance ADC peripheral instance. + * @param mask STM32_ADC_INSTANCE_MASK_x bit mask. + * @return RT_TRUE if the instance is included, otherwise RT_FALSE. + */ +rt_bool_t stm32_adc_instance_match(ADC_TypeDef *instance, rt_uint32_t mask) +{ +#ifdef ADC1 + if ((instance == ADC1) && ((mask & STM32_ADC_INSTANCE_MASK_ADC1) != 0U)) + { + return RT_TRUE; + } +#endif /* ADC1 */ + +#ifdef ADC2 + if ((instance == ADC2) && ((mask & STM32_ADC_INSTANCE_MASK_ADC2) != 0U)) + { + return RT_TRUE; + } +#endif /* ADC2 */ + +#ifdef ADC3 + if ((instance == ADC3) && ((mask & STM32_ADC_INSTANCE_MASK_ADC3) != 0U)) + { + return RT_TRUE; + } +#endif /* ADC3 */ + +#ifdef ADC4 + if ((instance == ADC4) && ((mask & STM32_ADC_INSTANCE_MASK_ADC4) != 0U)) + { + return RT_TRUE; + } +#endif /* ADC4 */ + +#ifdef ADC5 + if ((instance == ADC5) && ((mask & STM32_ADC_INSTANCE_MASK_ADC5) != 0U)) + { + return RT_TRUE; + } +#endif /* ADC5 */ + + return RT_FALSE; +} + +/** + * @brief Check whether one internal HAL channel is supported by the current ADC instance. + * @param adc Pointer to the STM32 ADC device object. + * @param hal_channel HAL ADC channel identifier. + * @param instance_mask ADC instance mask allowed to access this internal channel. + * @return RT_TRUE if the channel is available on the current ADC instance, otherwise RT_FALSE. + */ +static rt_bool_t stm32_adc_internal_channel_supported(struct stm32_adc *adc, uint32_t hal_channel, rt_uint32_t instance_mask) +{ + if ((stm32_adc_hal_channel_valid(hal_channel) != RT_TRUE)) + { + return RT_FALSE; + } + + return stm32_adc_instance_match(adc->handle.Instance, instance_mask); +} + +/** + * @brief Find the internal ADC channel capability entry by logical channel. + * @param channel RT-Thread logical ADC channel identifier. + * @return Pointer to the internal-channel entry, or RT_NULL if the channel is not internal. + */ +static const struct stm32_adc_internal_channel *stm32_adc_find_internal_channel(rt_uint8_t channel) +{ + rt_size_t index; + + for (index = 0U; index < RT_ARRAY_SIZE(stm32_adc_internal_channels); index++) + { + if ((stm32_adc_internal_channels[index].logical_channel >= 0) && + ((rt_uint8_t)stm32_adc_internal_channels[index].logical_channel == channel)) + { + return &stm32_adc_internal_channels[index]; + } + } + + return RT_NULL; +} + +/** + * @brief Get an instance-aware HAL channel identifier for an ADC channel. + * @param adc Pointer to the STM32 ADC device object. + * @param channel RT-Thread logical ADC channel identifier. + * @param hal_channel Pointer to the output HAL ADC channel identifier. + * @return Operation status. + */ +static rt_err_t stm32_adc_get_channel_for_instance(struct stm32_adc *adc, rt_uint8_t channel, uint32_t *hal_channel) +{ + const struct stm32_adc_internal_channel *internal_channel; + rt_err_t result; + + internal_channel = stm32_adc_find_internal_channel(channel); + if (internal_channel != RT_NULL) + { + if (stm32_adc_internal_channel_supported(adc, internal_channel->hal_channel, internal_channel->instance_mask) == RT_TRUE) + { + *hal_channel = internal_channel->hal_channel; + return RT_EOK; + } + + if (stm32_adc_internal_channel_supported(adc, internal_channel->alternate_hal_channel, + internal_channel->alternate_instance_mask) == RT_TRUE) + { + *hal_channel = internal_channel->alternate_hal_channel; + return RT_EOK; + } + + return -RT_ENOSYS; + } + + result = stm32_adc_get_channel(channel, hal_channel); + if ((result == RT_EOK) && (stm32_adc_hal_channel_valid(*hal_channel) != RT_TRUE)) + { + return -RT_EINVAL; + } + + return result; +} + +/** + * @brief Get the HAL ADC channel identifier. + * @param channel RT-Thread ADC channel identifier. + * @param hal_channel Pointer to the output HAL channel identifier. + * @return Operation status. + */ +rt_err_t stm32_adc_get_channel(rt_uint8_t channel, uint32_t *hal_channel) +{ + if (((rt_size_t)channel >= RT_ARRAY_SIZE(stm32_adc_channel_table)) || + (stm32_adc_hal_channel_valid(stm32_adc_channel_table[(rt_size_t)channel]) != RT_TRUE)) + { + return -RT_EINVAL; + } + + *hal_channel = stm32_adc_channel_table[(rt_size_t)channel]; + return RT_EOK; +} + +/** + * @brief Get the logical channel used to sample STM32 VREF. + * @param adc Pointer to the STM32 ADC device object. + * @param channel Pointer to the output logical VREFINT channel. + * @return Operation status. + */ +rt_err_t stm32_adc_get_vref_logical_channel(struct stm32_adc *adc, rt_uint8_t *channel) +{ + uint32_t hal_channel; + rt_err_t result; + + if (STM32_ADC_VREF_CHANNEL < 0) + { + return -RT_ENOSYS; + } + + result = stm32_adc_get_channel_for_instance(adc, (rt_uint8_t)STM32_ADC_VREF_CHANNEL, &hal_channel); + if (result != RT_EOK) + { + return result; + } + + RT_UNUSED(hal_channel); + *channel = (rt_uint8_t)STM32_ADC_VREF_CHANNEL; + return RT_EOK; +} + +/** + * @brief Get the logical channel used to sample STM32 internal temperature sensor. + * @param adc Pointer to the STM32 ADC device object. + * @param channel Pointer to the output logical temperature-sensor channel. + * @return Operation status. + */ +rt_err_t stm32_adc_get_tempsensor_logical_channel(struct stm32_adc *adc, rt_uint8_t *channel) +{ + uint32_t hal_channel; + rt_err_t result; + + if (STM32_ADC_TEMP_CHANNEL < 0) + { + return -RT_ENOSYS; + } + + result = stm32_adc_get_channel_for_instance(adc, (rt_uint8_t)STM32_ADC_TEMP_CHANNEL, &hal_channel); + if (result != RT_EOK) + { + return result; + } + + RT_UNUSED(hal_channel); + *channel = (rt_uint8_t)STM32_ADC_TEMP_CHANNEL; + return RT_EOK; +} + +/** + * @brief Get the logical channel used to sample STM32 internal VBAT divider. + * @param adc Pointer to the STM32 ADC device object. + * @param channel Pointer to the output logical VBAT channel. + * @return Operation status. + */ +rt_err_t stm32_adc_get_vbat_logical_channel(struct stm32_adc *adc, rt_uint8_t *channel) +{ + uint32_t hal_channel; + rt_err_t result; + + if (STM32_ADC_VBAT_CHANNEL < 0) + { + return -RT_ENOSYS; + } + + result = stm32_adc_get_channel_for_instance(adc, (rt_uint8_t)STM32_ADC_VBAT_CHANNEL, &hal_channel); + if (result != RT_EOK) + { + return result; + } + + RT_UNUSED(hal_channel); + *channel = (rt_uint8_t)STM32_ADC_VBAT_CHANNEL; + return RT_EOK; +} + +/** + * @brief Get the current ADC resolution in bits. + * @param adc Pointer to the STM32 ADC device object. + * @return Resolution in bits, or 12 when it cannot be determined. + */ +rt_uint8_t stm32_adc_get_resolution_bits(const struct stm32_adc *adc) +{ +#if defined(STM32_ADC_HAS_CONFIGURABLE_RESOLUTION) + switch (adc->handle.Init.Resolution) + { +#ifdef ADC_RESOLUTION_16B + case ADC_RESOLUTION_16B: + return 16U; +#endif /* ADC_RESOLUTION_16B */ +#ifdef ADC_RESOLUTION_14B + case ADC_RESOLUTION_14B: + return 14U; +#endif /* ADC_RESOLUTION_14B */ +#ifdef ADC_RESOLUTION_12B + case ADC_RESOLUTION_12B: + return 12U; +#endif /* ADC_RESOLUTION_12B */ +#ifdef ADC_RESOLUTION_10B + case ADC_RESOLUTION_10B: + return 10U; +#endif /* ADC_RESOLUTION_10B */ +#ifdef ADC_RESOLUTION_8B + case ADC_RESOLUTION_8B: + return 8U; +#endif /* ADC_RESOLUTION_8B */ +#ifdef ADC_RESOLUTION_6B + case ADC_RESOLUTION_6B: + return 6U; +#endif /* ADC_RESOLUTION_6B */ + default: + return 12U; + } +#else + RT_UNUSED(adc); + return 12U; +#endif /* defined(STM32_ADC_HAS_CONFIGURABLE_RESOLUTION) */ +} + +#if defined(STM32_ADC_HAS_LL_TEMPERATURE_CALC) +/** + * @brief Convert an ADC resolution in bits to the HAL resolution token. + * @param resolution_bits ADC conversion resolution in bits. + * @param hal_resolution Pointer to the output HAL resolution token. + * @return Operation status. + */ +static rt_err_t stm32_adc_get_hal_resolution(rt_uint8_t resolution_bits, uint32_t *hal_resolution) +{ + if (hal_resolution == RT_NULL) + { + return -RT_EINVAL; + } + + switch (resolution_bits) + { +#ifdef ADC_RESOLUTION_16B + case 16U: + *hal_resolution = ADC_RESOLUTION_16B; + return RT_EOK; +#endif /* ADC_RESOLUTION_16B */ +#ifdef ADC_RESOLUTION_14B + case 14U: + *hal_resolution = ADC_RESOLUTION_14B; + return RT_EOK; +#endif /* ADC_RESOLUTION_14B */ +#ifdef ADC_RESOLUTION_12B + case 12U: + *hal_resolution = ADC_RESOLUTION_12B; + return RT_EOK; +#endif /* ADC_RESOLUTION_12B */ +#ifdef ADC_RESOLUTION_10B + case 10U: + *hal_resolution = ADC_RESOLUTION_10B; + return RT_EOK; +#endif /* ADC_RESOLUTION_10B */ +#ifdef ADC_RESOLUTION_8B + case 8U: + *hal_resolution = ADC_RESOLUTION_8B; + return RT_EOK; +#endif /* ADC_RESOLUTION_8B */ +#ifdef ADC_RESOLUTION_6B + case 6U: + *hal_resolution = ADC_RESOLUTION_6B; + return RT_EOK; +#endif /* ADC_RESOLUTION_6B */ + default: + return -RT_EINVAL; + } +} +#endif /* defined(STM32_ADC_HAS_LL_TEMPERATURE_CALC) */ + +#if defined(STM32_ADC_HAS_TEMPSENSOR_CALIBRATION_DATA) +/** + * @brief Normalize a raw ADC sample to the 12-bit temperature calibration scale. + * @param raw_value Raw ADC sample value. + * @param resolution_bits ADC conversion resolution used for @p raw_value. + * @param raw_12b Pointer to the output sample normalized to 12-bit scale. + * @return Operation status. + */ +rt_err_t stm32_adc_normalize_to_12b(rt_uint32_t raw_value, rt_uint8_t resolution_bits, rt_uint32_t *raw_12b) +{ + if ((raw_12b == RT_NULL) || (resolution_bits == 0U) || (resolution_bits > 16U)) + { + return -RT_EINVAL; + } + + if (resolution_bits > 12U) + { + *raw_12b = raw_value >> (resolution_bits - 12U); + } + else + { + *raw_12b = raw_value << (12U - resolution_bits); + } + + return RT_EOK; +} +#endif /* defined(STM32_ADC_HAS_TEMPSENSOR_CALIBRATION_DATA) */ + +/** + * @brief Calculate STM32 internal temperature sensor value in degrees Celsius. + * @param device ADC device handle. + * @param raw_value Raw ADC sample value from the temperature sensor channel. + * @param vref_mv Current analog reference voltage in millivolts. + * @param resolution_bits ADC conversion resolution used for @p raw_value. + * @param temperature_c Pointer to the output temperature in degrees Celsius. + * @return Operation status. + */ +rt_err_t stm32_adc_calc_temperature(rt_adc_device_t device, rt_uint32_t raw_value, + rt_uint32_t vref_mv, rt_uint8_t resolution_bits, + rt_int32_t *temperature_c) +{ +#if defined(STM32_ADC_HAS_LL_TEMPERATURE_CALC) + struct stm32_adc *adc; + uint32_t hal_resolution; + rt_err_t result; + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + result = stm32_adc_get_hal_resolution(resolution_bits, &hal_resolution); + if (result != RT_EOK) + { + return result; + } + + *temperature_c = (rt_int32_t)STM32_ADC_CALC_TEMPERATURE(adc, vref_mv, raw_value, hal_resolution); + return RT_EOK; +#elif defined(STM32_ADC_HAS_TEMPSENSOR_CALIBRATION_DATA) + struct stm32_adc *adc; + rt_uint32_t raw_12b; + rt_uint32_t raw_calibrated; + rt_int32_t cal1; + rt_int32_t cal2; + rt_int32_t denominator; + rt_int64_t numerator; + rt_err_t result; + + if ((device == RT_NULL) || (vref_mv == 0U) || (temperature_c == RT_NULL)) + { + return -RT_EINVAL; + } + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + result = stm32_adc_normalize_to_12b(raw_value, resolution_bits, &raw_12b); + if (result != RT_EOK) + { + return result; + } + + raw_calibrated = (rt_uint32_t)(((rt_uint64_t)raw_12b * (rt_uint64_t)vref_mv + + (TEMPSENSOR_CAL_VREFANALOG / 2U)) / TEMPSENSOR_CAL_VREFANALOG); + cal1 = (rt_int32_t)(*TEMPSENSOR_CAL1_ADDR); + cal2 = (rt_int32_t)(*TEMPSENSOR_CAL2_ADDR); + denominator = cal2 - cal1; + if (denominator == 0) + { + return -RT_EINVAL; + } + + numerator = ((rt_int64_t)((rt_int32_t)raw_calibrated - cal1) * + (rt_int64_t)(TEMPSENSOR_CAL2_TEMP - TEMPSENSOR_CAL1_TEMP)); + if (numerator >= 0) + { + numerator += denominator / 2; + } + else + { + numerator -= denominator / 2; + } + + *temperature_c = (rt_int32_t)(numerator / denominator) + TEMPSENSOR_CAL1_TEMP; + return RT_EOK; +#else + RT_UNUSED(device); + RT_UNUSED(raw_value); + RT_UNUSED(vref_mv); + RT_UNUSED(resolution_bits); + RT_UNUSED(temperature_c); + + return -RT_ENOSYS; +#endif /* defined(STM32_ADC_HAS_LL_TEMPERATURE_CALC) */ +} + +#if defined(STM32_ADC_HAS_ENUM_RANK) +/** + * @brief STM32 ADC regular-rank mapping entry. + */ +struct stm32_adc_rank_map +{ + rt_bool_t valid; /**< Whether this logical rank is supported by HAL. */ + uint32_t hal_rank; /**< HAL regular-rank enumeration value. */ +}; + +/** + * @brief HAL regular-rank values indexed by logical rank. + */ +static const struct stm32_adc_rank_map stm32_adc_rank_table[] = { + { RT_FALSE, 0U }, +#ifdef ADC_REGULAR_RANK_1 + { RT_TRUE, ADC_REGULAR_RANK_1 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_1 */ +#ifdef ADC_REGULAR_RANK_2 + { RT_TRUE, ADC_REGULAR_RANK_2 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_2 */ +#ifdef ADC_REGULAR_RANK_3 + { RT_TRUE, ADC_REGULAR_RANK_3 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_3 */ +#ifdef ADC_REGULAR_RANK_4 + { RT_TRUE, ADC_REGULAR_RANK_4 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_4 */ +#ifdef ADC_REGULAR_RANK_5 + { RT_TRUE, ADC_REGULAR_RANK_5 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_5 */ +#ifdef ADC_REGULAR_RANK_6 + { RT_TRUE, ADC_REGULAR_RANK_6 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_6 */ +#ifdef ADC_REGULAR_RANK_7 + { RT_TRUE, ADC_REGULAR_RANK_7 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_7 */ +#ifdef ADC_REGULAR_RANK_8 + { RT_TRUE, ADC_REGULAR_RANK_8 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_8 */ +#ifdef ADC_REGULAR_RANK_9 + { RT_TRUE, ADC_REGULAR_RANK_9 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_9 */ +#ifdef ADC_REGULAR_RANK_10 + { RT_TRUE, ADC_REGULAR_RANK_10 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_10 */ +#ifdef ADC_REGULAR_RANK_11 + { RT_TRUE, ADC_REGULAR_RANK_11 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_11 */ +#ifdef ADC_REGULAR_RANK_12 + { RT_TRUE, ADC_REGULAR_RANK_12 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_12 */ +#ifdef ADC_REGULAR_RANK_13 + { RT_TRUE, ADC_REGULAR_RANK_13 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_13 */ +#ifdef ADC_REGULAR_RANK_14 + { RT_TRUE, ADC_REGULAR_RANK_14 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_14 */ +#ifdef ADC_REGULAR_RANK_15 + { RT_TRUE, ADC_REGULAR_RANK_15 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_15 */ +#ifdef ADC_REGULAR_RANK_16 + { RT_TRUE, ADC_REGULAR_RANK_16 }, +#else + { RT_FALSE, 0U }, +#endif /* ADC_REGULAR_RANK_16 */ +}; +#endif /* defined(STM32_ADC_HAS_ENUM_RANK) */ + +/** + * @brief Convert one STM32 HAL status code to an RT-Thread error code. + * @param status STM32 HAL operation status. + * @return RT-Thread operation status. + */ +static rt_err_t stm32_hal_status_to_rt_err(HAL_StatusTypeDef status) +{ + switch (status) + { + case HAL_OK: + return RT_EOK; + + case HAL_BUSY: + return -RT_EBUSY; + + case HAL_TIMEOUT: + return -RT_ETIMEOUT; + + case HAL_ERROR: + default: + return -RT_ERROR; + } +} + +/** + * @brief Get one HAL rank value from a logical rank index. + * @param rank Logical rank index starting from 1. + * @param hal_rank Pointer to the output HAL rank value. + * @return Operation status. + */ +static rt_err_t stm32_adc_get_rank_value(rt_uint32_t rank, uint32_t *hal_rank) +{ +#if defined(STM32_ADC_HAS_ENUM_RANK) + if ((rank >= RT_ARRAY_SIZE(stm32_adc_rank_table)) || (stm32_adc_rank_table[rank].valid != RT_TRUE)) + { + return -RT_EINVAL; + } + + *hal_rank = stm32_adc_rank_table[rank].hal_rank; +#elif defined(STM32_ADC_HAS_CHANNEL_NUMBER_RANK) + RT_UNUSED(rank); + *hal_rank = ADC_RANK_CHANNEL_NUMBER; +#else + *hal_rank = rank; +#endif /* defined(STM32_ADC_HAS_ENUM_RANK) */ + + return RT_EOK; +} + +/** + * @brief Enable ADC analog support required by a specific series. + */ +static void stm32_adc_enable_analog_support(void) +{ +#if defined(STM32_ADC_NEEDS_ANALOG_SUPPLY) + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWREx_EnableVddA(); +#endif /* defined(STM32_ADC_NEEDS_ANALOG_SUPPLY) */ +} + +#if defined(STM32_ADC_HAS_CALIBRATION) +/** + * @brief Get the input-mode mask from STM32 private configuration. + * @param cfg Pointer to the STM32 backend private configuration. + * @return RT_ADC_INPUT_MODE_* mask used by calibration. + */ +static rt_uint8_t stm32_adc_get_input_modes(const struct stm32_adc_private_cfg *cfg) +{ + if (cfg->input_modes == 0U) + { + return RT_ADC_INPUT_MODE_SINGLE_ENDED; + } + + return cfg->input_modes; +} + +/** + * @brief Run one calibration pass for a selected ADC input mode. + * @param adc Pointer to the STM32 ADC device object. + * @param calibration_mode HAL calibration mode selector. + * @param input_mode HAL single-ended or differential selector. + * @return Operation status. + */ +static rt_err_t stm32_adc_run_calibration_pass(struct stm32_adc *adc, uint32_t calibration_mode, uint32_t input_mode) +{ + HAL_StatusTypeDef status; +#if defined(STM32_ADC_HAS_SIMPLE_CALIBRATION) + RT_UNUSED(calibration_mode); + status = HAL_ADCEx_Calibration_Start(&adc->handle, input_mode); + if (status != HAL_OK) + { + LOG_E("%s calibration failed", adc->name); + return stm32_hal_status_to_rt_err(status); + } + return RT_EOK; +#elif defined(STM32_ADC_HAS_LINEAR_CALIBRATION) + status = HAL_ADCEx_Calibration_Start(&adc->handle, calibration_mode, input_mode); + if (status != HAL_OK) + { + LOG_E("%s calibration failed", adc->name); + return stm32_hal_status_to_rt_err(status); + } + return RT_EOK; +#else + RT_UNUSED(status); + RT_UNUSED(calibration_mode); + RT_UNUSED(input_mode); + return -RT_ENOSYS; +#endif /* calibration feature buckets */ +} + +/** + * @brief Run one series-specific ADC calibration from STM32 private configuration. + * @param adc Pointer to the STM32 ADC device object. + * @param private_cfg Pointer to the STM32 backend private configuration. + * @return Operation status. + */ +static rt_err_t stm32_adc_run_calibration(struct stm32_adc *adc, const struct stm32_adc_private_cfg *private_cfg) +{ + rt_err_t result; + rt_uint8_t requested_input_modes; +#if defined(STM32_ADC_HAS_LINEAR_CALIBRATION) && defined(ADC_CALIB_OFFSET) + rt_bool_t single_ended_calibrated; +#endif /* defined(STM32_ADC_HAS_LINEAR_CALIBRATION) && defined(ADC_CALIB_OFFSET) */ + + requested_input_modes = stm32_adc_get_input_modes(private_cfg); + LOG_D("%s calibration request: modes=0x%02x", adc->name, requested_input_modes); + +#if defined(STM32_ADC_HAS_SIMPLE_CALIBRATION) + if ((requested_input_modes & RT_ADC_INPUT_MODE_SINGLE_ENDED) != 0U) + { + result = stm32_adc_run_calibration_pass(adc, 0U, STM32_ADC_SINGLE_ENDED_VALUE); + if (result != RT_EOK) + { + return result; + } + LOG_I("%s single-ended calibration done", adc->name); + } + if ((requested_input_modes & RT_ADC_INPUT_MODE_DIFFERENTIAL) != 0U) + { + result = stm32_adc_run_calibration_pass(adc, 0U, STM32_ADC_DIFFERENTIAL_VALUE); + if (result != RT_EOK) + { + return result; + } + LOG_I("%s differential calibration done", adc->name); + } + return RT_EOK; +#elif defined(STM32_ADC_HAS_LINEAR_CALIBRATION) +#if defined(ADC_CALIB_OFFSET) + single_ended_calibrated = RT_FALSE; +#endif /* defined(ADC_CALIB_OFFSET) */ + if ((requested_input_modes & RT_ADC_INPUT_MODE_SINGLE_ENDED) != 0U) + { + result = stm32_adc_run_calibration_pass(adc, ADC_CALIB_OFFSET_LINEARITY, STM32_ADC_SINGLE_ENDED_VALUE); + if (result != RT_EOK) + { + return result; + } +#if defined(ADC_CALIB_OFFSET) + single_ended_calibrated = RT_TRUE; +#endif /* defined(ADC_CALIB_OFFSET) */ + LOG_I("%s single-ended calibration done", adc->name); + } + if ((requested_input_modes & RT_ADC_INPUT_MODE_DIFFERENTIAL) != 0U) + { + result = stm32_adc_run_calibration_pass(adc, +#if defined(ADC_CALIB_OFFSET) + (single_ended_calibrated == RT_TRUE) ? ADC_CALIB_OFFSET : ADC_CALIB_OFFSET_LINEARITY, +#else + ADC_CALIB_OFFSET_LINEARITY, +#endif /* defined(ADC_CALIB_OFFSET) */ + STM32_ADC_DIFFERENTIAL_VALUE); + if (result != RT_EOK) + { + return result; + } + LOG_I("%s differential calibration done", adc->name); + } + return RT_EOK; +#else + RT_UNUSED(requested_input_modes); + return -RT_ENOSYS; +#endif /* calibration feature buckets */ +} + +#endif /* defined(STM32_ADC_HAS_CALIBRATION) */ + +/** + * @brief Fill the HAL ADC initialization structure from the device object. + * @param adc Pointer to the STM32 ADC device object. + * @return Operation status. + */ +static rt_err_t stm32_adc_fill_init(struct stm32_adc *adc) +{ + ADC_TypeDef *instance; + + LOG_D("%s fill init", adc->name); + instance = adc->handle.Instance; + rt_memset(&adc->handle, 0, sizeof(adc->handle)); + adc->handle.Instance = instance; +#ifdef ADC_DEFAULT_CLOCK_PRESCALER + adc->handle.Init.ClockPrescaler = ADC_DEFAULT_CLOCK_PRESCALER; +#endif /* ADC_DEFAULT_CLOCK_PRESCALER */ +#if defined(STM32_ADC_HAS_INIT_DATA_ALIGN) + adc->handle.Init.DataAlign = (adc->config.data_align != 0U) ? adc->config.data_align : ADC_DEFAULT_DATA_ALIGN; +#endif /* defined(STM32_ADC_HAS_INIT_DATA_ALIGN) */ + adc->handle.Init.ScanConvMode = STM32_ADC_SCAN_MODE_DISABLE; +#if defined(STM32_ADC_HAS_INIT_EOC_SELECTION) + adc->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; +#endif /* defined(STM32_ADC_HAS_INIT_EOC_SELECTION) */ + adc->handle.Init.ContinuousConvMode = DISABLE; +#if defined(STM32_ADC_HAS_INIT_CONVERSION_DATA_MANAGEMENT) + adc->handle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; +#endif /* defined(STM32_ADC_HAS_INIT_CONVERSION_DATA_MANAGEMENT) */ +#if defined(STM32_ADC_HAS_INIT_NBR_OF_CONVERSION) + adc->handle.Init.NbrOfConversion = 1; +#endif /* defined(STM32_ADC_HAS_INIT_NBR_OF_CONVERSION) */ + adc->handle.Init.DiscontinuousConvMode = DISABLE; +#if defined(STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION) + adc->handle.Init.NbrOfDiscConversion = 1; +#endif /* defined(STM32_ADC_HAS_INIT_NBR_OF_DISC_CONVERSION) */ + adc->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; +#if defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) + adc->handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; +#endif /* defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) */ +#if defined(STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS) + adc->handle.Init.DMAContinuousRequests = DISABLE; +#endif /* defined(STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS) */ +#if defined(STM32_ADC_HAS_HW_OVERSAMPLING) + adc->handle.Init.OversamplingMode = DISABLE; + adc->handle.Init.Oversampling.Ratio = 0U; + adc->handle.Init.Oversampling.RightBitShift = 0U; + adc->handle.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER; + adc->handle.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE; +#endif /* defined(STM32_ADC_HAS_HW_OVERSAMPLING) */ + +#if defined(STM32_ADC_HAS_CONFIGURABLE_RESOLUTION) + adc->handle.Init.Resolution = (adc->config.resolution != 0U) ? adc->config.resolution : ADC_DEFAULT_RESOLUTION; +#else + if (adc->config.resolution != 0U) + { + return -RT_ENOSYS; + } +#endif /* defined(STM32_ADC_HAS_CONFIGURABLE_RESOLUTION) */ + + return RT_EOK; +} + +/** + * @brief Force one ADC device back to regular polling conversion mode. + * @param adc Pointer to the STM32 ADC device object. + * + * Sequence reads use HAL_ADC_Start() and HAL_ADC_PollForConversion(), so any + * DMA request state left by board initialization must be cleared before + * starting a polling conversion. + */ +static void stm32_adc_force_poll_mode(struct stm32_adc *adc) +{ +#if defined(ADC_CR2_DMA) + CLEAR_BIT(adc->handle.Instance->CR2, ADC_CR2_DMA); +#endif /* defined(ADC_CR2_DMA) */ + +#if defined(ADC_CR2_DDS) + CLEAR_BIT(adc->handle.Instance->CR2, ADC_CR2_DDS); +#endif /* defined(ADC_CR2_DDS) */ + +#if defined(STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS) + adc->handle.Init.DMAContinuousRequests = DISABLE; +#endif /* defined(STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS) */ + +#if defined(STM32_ADC_HAS_INIT_CONVERSION_DATA_MANAGEMENT) + adc->handle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; +#endif /* defined(STM32_ADC_HAS_INIT_CONVERSION_DATA_MANAGEMENT) */ +} + +/** + * @brief Open one STM32 ADC device. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ +static rt_err_t stm32_adc_open(struct rt_adc_device *device) +{ + struct stm32_adc *adc; + HAL_StatusTypeDef status; + rt_err_t result; + + if (device == RT_NULL) + { + return -RT_EINVAL; + } + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + LOG_D("%s open start", adc->name); + stm32_adc_enable_analog_support(); + result = stm32_adc_fill_init(adc); + if (result != RT_EOK) + { + return result; + } + result = stm32_adc_apply_oversampling(adc); + if (result != RT_EOK) + { + return result; + } + status = HAL_ADC_Init(&adc->handle); + if (status != HAL_OK) + { + LOG_E("%s init failed", adc->name); + return stm32_hal_status_to_rt_err(status); + } +#if defined(STM32_ADC_HAS_CALIBRATION) + result = stm32_adc_run_calibration(adc, &adc->config); + if (result != RT_EOK) + { + return result; + } +#endif /* defined(STM32_ADC_HAS_CALIBRATION) */ + LOG_I("%s opened", adc->name); + return RT_EOK; +} + +/** + * @brief Close one STM32 ADC device. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ +static rt_err_t stm32_adc_close(struct rt_adc_device *device) +{ + struct stm32_adc *adc; + HAL_StatusTypeDef status; + + if (device == RT_NULL) + { + return -RT_EINVAL; + } + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + status = HAL_ADC_Stop(&adc->handle); + if (status != HAL_OK) + { + LOG_W("%s stop during close failed", adc->name); + } + status = HAL_ADC_DeInit(&adc->handle); + if (status != HAL_OK) + { + LOG_W("%s deinit during close failed", adc->name); + return -RT_ERROR; + } + LOG_I("%s closed", adc->name); + return RT_EOK; +} + +#if defined(STM32_ADC_HAS_SINGLE_DIFF_FIELDS) +/** + * @brief Get the HAL single-ended/differential selector from private configuration. + * @param cfg Pointer to the STM32 backend private configuration. + * @param single_diff Pointer to the output HAL single-ended or differential selector. + * @return Operation status. + */ +static rt_err_t stm32_adc_get_single_diff(const struct stm32_adc_private_cfg *cfg, uint32_t *single_diff) +{ + *single_diff = ((cfg->input_modes & RT_ADC_INPUT_MODE_DIFFERENTIAL) != 0U) ? + STM32_ADC_DIFFERENTIAL_VALUE : STM32_ADC_SINGLE_ENDED_VALUE; + return RT_EOK; +} +#endif /* defined(STM32_ADC_HAS_SINGLE_DIFF_FIELDS) */ + +/** + * @brief Get one HAL sampling-time value from STM32 private configuration. + * @param cfg Pointer to the STM32 backend private configuration. + * @param sampling_time Pointer to the output HAL sampling-time value. + * @return Operation status. + */ +rt_err_t stm32_adc_get_sampling_time(const struct stm32_adc_private_cfg *cfg, uint32_t *sampling_time) +{ + if ((cfg == RT_NULL) || (sampling_time == RT_NULL)) + { + return -RT_EINVAL; + } + + *sampling_time = (cfg->sampling_time != 0U) ? cfg->sampling_time : ADC_DEFAULT_SAMPLING_TIME; + return RT_EOK; +} + +/** + * @brief Configure one ADC regular rank. + * @param adc Pointer to the STM32 ADC device object. + * @param channel RT-Thread ADC channel identifier. + * @param rank Logical regular rank index. + * @return Operation status. + */ +static rt_err_t stm32_adc_configure_rank(struct stm32_adc *adc, rt_uint8_t channel, rt_uint32_t rank) +{ + ADC_ChannelConfTypeDef config; + HAL_StatusTypeDef status; + uint32_t hal_channel; + uint32_t hal_rank; + uint32_t sampling_time; + rt_err_t result; + + result = stm32_adc_get_channel_for_instance(adc, channel, &hal_channel); + if (result != RT_EOK) + { + return result; + } + + result = stm32_adc_get_rank_value(rank, &hal_rank); + if (result != RT_EOK) + { + return result; + } + + result = stm32_adc_get_sampling_time(&adc->config, &sampling_time); + if (result != RT_EOK) + { + return result; + } + + rt_memset(&config, 0, sizeof(config)); + config.Channel = hal_channel; + config.Rank = hal_rank; + config.SamplingTime = sampling_time; +#if defined(STM32_ADC_HAS_CONFIG_OFFSET) + config.Offset = 0; +#endif /* defined(STM32_ADC_HAS_CONFIG_OFFSET) */ +#if defined(STM32_ADC_HAS_CONFIG_OFFSET_NUMBER) + config.OffsetNumber = ADC_OFFSET_NONE; +#endif /* defined(STM32_ADC_HAS_CONFIG_OFFSET_NUMBER) */ +#if defined(STM32_ADC_HAS_SINGLE_DIFF_FIELDS) + result = stm32_adc_get_single_diff(&adc->config, &config.SingleDiff); + if ((result != RT_EOK) && (result != -RT_ENOSYS)) + { + return result; + } +#endif /* defined(STM32_ADC_HAS_SINGLE_DIFF_FIELDS) */ + + status = HAL_ADC_ConfigChannel(&adc->handle, &config); + if (status != HAL_OK) + { + LOG_E("%s configure rank failed", adc->name); + return stm32_hal_status_to_rt_err(status); + } + + return RT_EOK; +} + +/** + * @brief Clear backend ADC channel/rank configuration explicitly. + * @param adc Pointer to the STM32 ADC device object. + * @return Operation status. + * + * This operation is intentionally not called from normal session configuration. + * It is an explicit escape hatch for users that need to clear stale + * channel-number rank configuration before rebuilding a conversion session. + */ +static rt_err_t stm32_adc_clear_channel_config(struct stm32_adc *adc) +{ +#if defined(STM32_ADC_HAS_CHANNEL_NUMBER_RANK) && defined(ADC_RANK_NONE) + ADC_ChannelConfTypeDef config; + HAL_StatusTypeDef status; + rt_uint8_t channel; + uint32_t hal_channel; + uint32_t sampling_time; + rt_err_t result; + + result = stm32_adc_get_sampling_time(&adc->config, &sampling_time); + if (result != RT_EOK) + { + return result; + } + + for (channel = 0U; channel < STM32_ADC_MAX_CHANNELS; channel++) + { + result = stm32_adc_get_channel_for_instance(adc, channel, &hal_channel); + if (result != RT_EOK) + { + continue; + } + + rt_memset(&config, 0, sizeof(config)); + config.Channel = hal_channel; + config.Rank = ADC_RANK_NONE; + config.SamplingTime = sampling_time; +#if defined(STM32_ADC_HAS_CONFIG_OFFSET) + config.Offset = 0; +#endif /* defined(STM32_ADC_HAS_CONFIG_OFFSET) */ +#if defined(STM32_ADC_HAS_CONFIG_OFFSET_NUMBER) + config.OffsetNumber = ADC_OFFSET_NONE; +#endif /* defined(STM32_ADC_HAS_CONFIG_OFFSET_NUMBER) */ +#if defined(STM32_ADC_HAS_SINGLE_DIFF_FIELDS) + result = stm32_adc_get_single_diff(&adc->config, &config.SingleDiff); + if ((result != RT_EOK) && (result != -RT_ENOSYS)) + { + return result; + } +#endif /* defined(STM32_ADC_HAS_SINGLE_DIFF_FIELDS) */ + + status = HAL_ADC_ConfigChannel(&adc->handle, &config); + if (status != HAL_OK) + { + LOG_E("%s clear channel config failed: channel=%u", adc->name, (unsigned int)channel); + return stm32_hal_status_to_rt_err(status); + } + } + + LOG_D("%s channel config cleared", adc->name); + return RT_EOK; +#else + RT_UNUSED(adc); + return -RT_ENOSYS; +#endif /* defined(STM32_ADC_HAS_CHANNEL_NUMBER_RANK) && defined(ADC_RANK_NONE) */ +} + +/** + * @brief Configure all regular ADC ranks for one session. + * @param adc Pointer to the STM32 ADC device object. + * @param channels ADC channel selection mask. + * @return Operation status. + */ +static rt_err_t stm32_adc_configure_session_ranks(struct stm32_adc *adc, rt_uint32_t channels) +{ + rt_uint32_t rank; + rt_uint8_t channel; + rt_err_t result; + + rank = 1U; + while (channels != 0U) + { + if (rank > STM32_ADC_MAX_SEQUENCE) + { + return -RT_EINVAL; + } + + channel = rt_adc_channel_mask_take_lsb(&channels); + result = stm32_adc_configure_rank(adc, channel, rank); + if (result != RT_EOK) + { + LOG_E("%s rank config failed: channel=%u rank=%lu result=%d", + adc->name, (unsigned int)channel, (unsigned long)rank, result); + return result; + } + rank++; + } + + return RT_EOK; +} + +/** + * @brief Apply one complete regular ADC configuration to STM32 HAL. + * @param adc Pointer to the STM32 ADC device object. + * @param channels ADC channel selection mask. + * @return Operation status. + */ +static rt_err_t stm32_adc_apply_regular_config(struct stm32_adc *adc, rt_uint32_t channels) +{ + HAL_StatusTypeDef status; + rt_size_t channel_count; + rt_err_t result; + + channel_count = rt_adc_channel_mask_count(channels); + if ((channel_count == 0U) || (channel_count > STM32_ADC_MAX_SEQUENCE)) + { + return -RT_EINVAL; + } + + result = stm32_adc_fill_init(adc); + if (result != RT_EOK) + { + return result; + } + + result = stm32_adc_apply_oversampling(adc); + if (result != RT_EOK) + { + return result; + } + + adc->handle.Init.ScanConvMode = (channel_count > 1U) ? STM32_ADC_SCAN_MODE_ENABLE : STM32_ADC_SCAN_MODE_DISABLE; +#if defined(STM32_ADC_HAS_INIT_NBR_OF_CONVERSION) + adc->handle.Init.NbrOfConversion = channel_count; +#endif /* defined(STM32_ADC_HAS_INIT_NBR_OF_CONVERSION) */ + +#if defined(STM32_ADC_HAS_INIT_EOC_SELECTION) + adc->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; +#endif /* defined(STM32_ADC_HAS_INIT_EOC_SELECTION) */ + + /* + * Multi-rank polling must not let one HAL_ADC_Start() drain the whole + * regular sequence, otherwise DR can be overwritten before the CPU reads it. + * Discontinuous mode makes each HAL_ADC_Start() convert one rank only. + */ + adc->handle.Init.DiscontinuousConvMode = (channel_count > 1U) ? ENABLE : DISABLE; + + stm32_adc_force_poll_mode(adc); + + status = HAL_ADC_Init(&adc->handle); + if (status != HAL_OK) + { + LOG_E("%s regular init failed", adc->name); + return stm32_hal_status_to_rt_err(status); + } + return stm32_adc_configure_session_ranks(adc, channels); +} + +#if STM32_ADC_USING_DMA_STREAM +/** + * @brief Apply one complete regular ADC configuration for circular DMA stream mode. + * @param adc Pointer to the STM32 ADC device object. + * @param channels ADC channel selection mask. + * @return Operation status. + */ +static rt_err_t stm32_adc_apply_stream_regular_config(struct stm32_adc *adc, rt_uint32_t channels) +{ + HAL_StatusTypeDef status; + rt_size_t channel_count; + rt_err_t result; + + channel_count = rt_adc_channel_mask_count(channels); + if ((channel_count == 0U) || (channel_count > STM32_ADC_MAX_SEQUENCE)) + { + return -RT_EINVAL; + } + + result = stm32_adc_fill_init(adc); + if (result != RT_EOK) + { + return result; + } + + result = stm32_adc_apply_oversampling(adc); + if (result != RT_EOK) + { + return result; + } + +#if defined(STM32_ADC_USING_TRIGGER) + struct stm32_adc_trigger_fields trigger_fields; + if (adc->prepared_trigger_valid == RT_TRUE) + { + trigger_fields = adc->prepared_trigger; + } + else + { + result = stm32_adc_trigger_fields_get(adc, RT_NULL, &trigger_fields); + if (result != RT_EOK) + { + return result; + } + } +#endif /* defined(STM32_ADC_USING_TRIGGER) */ + + adc->handle.Init.ScanConvMode = (channel_count > 1U) ? STM32_ADC_SCAN_MODE_ENABLE : STM32_ADC_SCAN_MODE_DISABLE; +#if defined(STM32_ADC_HAS_INIT_NBR_OF_CONVERSION) + adc->handle.Init.NbrOfConversion = channel_count; +#endif /* defined(STM32_ADC_HAS_INIT_NBR_OF_CONVERSION) */ +#if defined(STM32_ADC_HAS_INIT_EOC_SELECTION) && defined(ADC_EOC_SEQ_CONV) + adc->handle.Init.EOCSelection = ADC_EOC_SEQ_CONV; +#elif defined(STM32_ADC_HAS_INIT_EOC_SELECTION) + adc->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; +#endif /* defined(STM32_ADC_HAS_INIT_EOC_SELECTION) && defined(ADC_EOC_SEQ_CONV) */ +#if defined(STM32_ADC_HAS_INIT_CONVERSION_DATA_MANAGEMENT) + adc->handle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; +#endif /* defined(STM32_ADC_HAS_INIT_CONVERSION_DATA_MANAGEMENT) */ +#if defined(STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS) + adc->handle.Init.DMAContinuousRequests = ENABLE; +#endif /* defined(STM32_ADC_HAS_INIT_DMA_CONT_REQUESTS) */ +#if defined(STM32_ADC_USING_TRIGGER) + adc->handle.Init.ContinuousConvMode = (trigger_fields.selector == ADC_SOFTWARE_START) ? ENABLE : DISABLE; + adc->handle.Init.ExternalTrigConv = trigger_fields.selector; +#if defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) + adc->handle.Init.ExternalTrigConvEdge = trigger_fields.edge; +#endif /* defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) */ +#else + adc->handle.Init.ContinuousConvMode = ENABLE; +#endif /* defined(STM32_ADC_USING_TRIGGER) */ + + status = HAL_ADC_Init(&adc->handle); + if (status != HAL_OK) + { + LOG_E("%s stream regular init failed", adc->name); + return stm32_hal_status_to_rt_err(status); + } + + return stm32_adc_configure_session_ranks(adc, channels); +} +#endif /* STM32_ADC_USING_DMA_STREAM */ + +/** + * @brief Configure one ADC conversion session on one STM32 ADC device. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @return Operation status. + */ +static rt_err_t stm32_adc_session_config(struct rt_adc_device *device, rt_uint32_t channels) +{ + struct stm32_adc *adc; + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + return stm32_adc_apply_regular_config(adc, channels); +} + +/** + * @brief Start one STM32 ADC finite sequence session. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the ADC sequence request object. + * @return Operation status. + */ +static rt_err_t stm32_adc_sequence_start(struct rt_adc_device *device, rt_uint32_t channels, + const struct rt_adc_sequence_cfg *cfg) +{ + RT_UNUSED(device); + RT_UNUSED(channels); + RT_UNUSED(cfg); + + return RT_EOK; +} + +/** + * @brief Read one sample from one STM32 ADC sequence session. + * @param device Pointer to the ADC device object. + * @param value Pointer to the output sample value. + * @param timeout_ms Read timeout in milliseconds. + * @return Operation status. + */ +static rt_err_t stm32_adc_sequence_read(struct rt_adc_device *device, rt_uint32_t *value, rt_int32_t timeout_ms) +{ + struct stm32_adc *adc; + HAL_StatusTypeDef status; + uint32_t timeout; + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + status = HAL_ADC_Start(&adc->handle); + if (status != HAL_OK) + { + goto fail; + } + + timeout = (timeout_ms < 0) ? HAL_MAX_DELAY : (uint32_t)timeout_ms; + status = HAL_ADC_PollForConversion(&adc->handle, timeout); + if (status != HAL_OK) + { + goto fail; + } + + *value = (rt_uint32_t)HAL_ADC_GetValue(&adc->handle); + LOG_D("%s sample read: value=%lu", adc->name, (unsigned long)*value); + + return RT_EOK; + +fail: + LOG_E("%s sequence read failed: status=%d state=0x%08lx error=0x%08lx", + adc->name, (int)status, (unsigned long)adc->handle.State, (unsigned long)adc->handle.ErrorCode); + + return stm32_hal_status_to_rt_err(status); +} +/** + * @brief Stop one STM32 ADC sequence session. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ +static rt_err_t stm32_adc_sequence_stop(struct rt_adc_device *device) +{ + struct stm32_adc *adc; + HAL_StatusTypeDef status; + rt_err_t result; + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + LOG_D("%s sequence stop", adc->name); + result = RT_EOK; + + status = HAL_ADC_Stop(&adc->handle); + if (status != HAL_OK) + { + LOG_W("%s sequence stop failed", adc->name); + return stm32_hal_status_to_rt_err(status); + } + + return result; +} + +#if STM32_ADC_USING_DMA_STREAM +#if defined(STM32_ADC_NEEDS_DMA_CACHE_MAINTENANCE) +/** @brief STM32 Cortex-M7 D-Cache line size used by DMA buffers. */ +#define STM32_ADC_DMA_CACHE_LINE_SIZE 32U + +/** + * @brief Release any cache-aligned ADC stream DMA buffer owned by the driver. + * @param adc Pointer to the STM32 ADC device object. + */ +static void stm32_adc_stream_release_cache_buffer(struct stm32_adc *adc) +{ + if ((adc != RT_NULL) && (adc->cache_dma_buffer != RT_NULL)) + { + LOG_D("%s stream cache buffer release: buffer=%p", adc->name, adc->cache_dma_buffer); + rt_free_align(adc->cache_dma_buffer); + adc->cache_dma_buffer = RT_NULL; + } +} + +/** + * @brief Select a D-Cache-safe DMA buffer for one ADC stream session. + * @param adc Pointer to the STM32 ADC device object. + * @param cfg Pointer to the stream configuration object. + * @param dma_buffer Pointer to the selected DMA buffer output. + * @return Operation status. + */ +static rt_err_t stm32_adc_stream_prepare_cache_buffer(struct stm32_adc *adc, const struct rt_adc_stream_cfg *cfg, + rt_uint32_t **dma_buffer) +{ + rt_size_t bytes; + rt_size_t cache_bytes; + + bytes = cfg->dma_buffer_length * sizeof(rt_uint32_t); + cache_bytes = RT_ALIGN(bytes, STM32_ADC_DMA_CACHE_LINE_SIZE); + stm32_adc_stream_release_cache_buffer(adc); + + if (RT_IS_ALIGN((rt_ubase_t)cfg->dma_buffer, STM32_ADC_DMA_CACHE_LINE_SIZE) && + RT_IS_ALIGN(bytes, STM32_ADC_DMA_CACHE_LINE_SIZE)) + { + *dma_buffer = cfg->dma_buffer; + LOG_D("%s stream cache buffer direct: buffer=%p bytes=%u", adc->name, *dma_buffer, (unsigned int)bytes); + } + else + { + adc->cache_dma_buffer = (rt_uint32_t *)rt_malloc_align(cache_bytes, STM32_ADC_DMA_CACHE_LINE_SIZE); + if (adc->cache_dma_buffer == RT_NULL) + { + LOG_E("%s stream cache buffer alloc failed: bytes=%u aligned=%u", + adc->name, (unsigned int)bytes, (unsigned int)cache_bytes); + return -RT_ENOMEM; + } + + *dma_buffer = adc->cache_dma_buffer; + LOG_W("%s stream cache buffer fallback: caller=%p dma=%p bytes=%u", + adc->name, cfg->dma_buffer, *dma_buffer, (unsigned int)bytes); + } + + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, *dma_buffer, cache_bytes); + adc->device.stream_ctrl.dma_buffer = *dma_buffer; + + return RT_EOK; +} + +/** + * @brief Invalidate a completed ADC stream DMA RX sample range. + * @param device Pointer to the ADC device object. + * @param sample_buffer Pointer to the sample buffer to synchronize. + * @param sample_count Number of samples to synchronize. + * @return Operation status. + */ +static rt_err_t stm32_adc_stream_sync(struct rt_adc_device *device, const rt_uint32_t *sample_buffer, rt_size_t sample_count) +{ + rt_ubase_t start; + rt_ubase_t end; + rt_ubase_t aligned_start; + rt_ubase_t aligned_end; + + if ((device == RT_NULL) || (sample_buffer == RT_NULL) || (sample_count == 0U)) + { + return -RT_EINVAL; + } + + start = (rt_ubase_t)sample_buffer; + end = start + sample_count * sizeof(rt_uint32_t); + aligned_start = RT_ALIGN_DOWN(start, STM32_ADC_DMA_CACHE_LINE_SIZE); + aligned_end = RT_ALIGN(end, STM32_ADC_DMA_CACHE_LINE_SIZE); + rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, (void *)aligned_start, aligned_end - aligned_start); + + return RT_EOK; +} +#else +/** + * @brief Release any cache-aligned ADC stream DMA buffer owned by the driver. + * @param adc Pointer to the STM32 ADC device object. + */ +static void stm32_adc_stream_release_cache_buffer(struct stm32_adc *adc) +{ + RT_UNUSED(adc); +} + +/** + * @brief Select the caller-owned DMA buffer for one ADC stream session. + * @param adc Pointer to the STM32 ADC device object. + * @param cfg Pointer to the stream configuration object. + * @param dma_buffer Pointer to the selected DMA buffer output. + * @return Operation status. + */ +static rt_err_t stm32_adc_stream_prepare_cache_buffer(struct stm32_adc *adc, const struct rt_adc_stream_cfg *cfg, + rt_uint32_t **dma_buffer) +{ + RT_UNUSED(adc); + + *dma_buffer = cfg->dma_buffer; + return RT_EOK; +} + +/** + * @brief Synchronize a backend DMA sample range before CPU access. + * @param device Pointer to the ADC device object. + * @param sample_buffer Pointer to the DMA sample buffer. + * @param sample_count Number of samples to synchronize. + * @return Operation status. + */ +static rt_err_t stm32_adc_stream_sync(struct rt_adc_device *device, const rt_uint32_t *sample_buffer, rt_size_t sample_count) +{ + RT_UNUSED(device); + RT_UNUSED(sample_buffer); + RT_UNUSED(sample_count); + + return RT_EOK; +} +#endif /* defined(STM32_ADC_NEEDS_DMA_CACHE_MAINTENANCE) */ + +/** + * @brief Configure STM32 DMA transfer event interrupts for one stream session. + * @param dma_handle Pointer to the DMA handle linked to the ADC stream. + * @param mode Effective ADC stream DMA event mode. + */ +static void stm32_adc_stream_configure_dma_events(DMA_HandleTypeDef *dma_handle, enum rt_adc_stream_dma_event_mode mode) +{ + if (dma_handle == RT_NULL) + { + return; + } + + if (mode == RT_ADC_STREAM_DMA_EVENT_NONE) + { + __HAL_DMA_DISABLE_IT(dma_handle, DMA_IT_HT); + __HAL_DMA_DISABLE_IT(dma_handle, DMA_IT_TC); + } + else if (mode == RT_ADC_STREAM_DMA_EVENT_FULL_ONLY) + { + __HAL_DMA_DISABLE_IT(dma_handle, DMA_IT_HT); + __HAL_DMA_ENABLE_IT(dma_handle, DMA_IT_TC); + } + else + { + __HAL_DMA_ENABLE_IT(dma_handle, DMA_IT_HT); + __HAL_DMA_ENABLE_IT(dma_handle, DMA_IT_TC); + } +} + +/** + * @brief Start one STM32 ADC stream session using circular DMA. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the stream configuration object. + * @return Operation status. + */ +static rt_err_t stm32_adc_stream_start(struct rt_adc_device *device, rt_uint32_t channels, const struct rt_adc_stream_cfg *cfg) +{ + struct stm32_adc *adc; + HAL_StatusTypeDef status; + rt_uint32_t *dma_buffer; + rt_err_t result; + + adc = RT_NULL; + dma_buffer = RT_NULL; + result = RT_EOK; + + adc = (struct stm32_adc *)device->parent.user_data; + if ((adc == RT_NULL) || (adc->dma_rx == RT_NULL)) + { + result = -RT_ENOSYS; + goto exit; + } + + result = stm32_adc_apply_stream_regular_config(adc, channels); + if (result != RT_EOK) + { + goto exit; + } + + result = stm32_adc_stream_prepare_cache_buffer(adc, cfg, &dma_buffer); + if (result != RT_EOK) + { + goto exit; + } + + result = stm32_dma_setup(&adc->dma_handle, &adc->handle, &adc->handle.DMA_Handle, adc->dma_rx); + if (result != RT_EOK) + { + goto exit; + } + status = HAL_ADC_Start_DMA(&adc->handle, dma_buffer, (uint32_t)cfg->dma_buffer_length); + if (status != HAL_OK) + { + result = stm32_hal_status_to_rt_err(status); + goto exit; + } + + stm32_adc_stream_configure_dma_events(&adc->dma_handle, adc->device.stream_ctrl.dma_event_mode); +exit: + if (result != RT_EOK) + { + LOG_E("%s stream startfailed: result=%d", adc->name, result); + } + + return result; +} + +/** + * @brief Stop one STM32 ADC stream session and release DMA resources. + * @param device Pointer to the ADC device object. + * @param hardware_stopped Pointer to the hardware-stop state output. + * @return Operation status. + */ +static rt_err_t stm32_adc_stream_stop(struct rt_adc_device *device, rt_bool_t *hardware_stopped) +{ + struct stm32_adc *adc; + HAL_StatusTypeDef status; + rt_bool_t hal_stopped; + rt_bool_t dma_attached; + rt_bool_t dma_released; + rt_err_t result; + + *hardware_stopped = RT_FALSE; + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + result = RT_EOK; + hal_stopped = RT_FALSE; + dma_released = RT_FALSE; + dma_attached = (adc->handle.DMA_Handle == &adc->dma_handle) ? RT_TRUE : RT_FALSE; + + if (dma_attached != RT_TRUE) + { + adc->handle.DMA_Handle = RT_NULL; + adc->dma_handle.Parent = RT_NULL; + stm32_adc_stream_release_cache_buffer(adc); + *hardware_stopped = RT_TRUE; + return RT_EOK; + } + + status = HAL_ADC_Stop_DMA(&adc->handle); + if (status == HAL_OK) + { + hal_stopped = RT_TRUE; + } + else + { + result = stm32_hal_status_to_rt_err(status); + LOG_W("%s stream DMA stop returned %d, continue cleanup", adc->name, result); + } + + if (adc->dma_rx != RT_NULL) + { + rt_err_t dma_result; + + dma_result = stm32_dma_deinit(&adc->dma_handle, adc->dma_rx, (hal_stopped == RT_TRUE) ? RT_FALSE : RT_TRUE); + if (dma_result == RT_EOK) + { + dma_released = RT_TRUE; + } + else + { + LOG_E("%s stream DMA cleanup failed after stop: result=%d", adc->name, dma_result); + if (result == RT_EOK) + { + result = dma_result; + } + } + } + else if (hal_stopped == RT_TRUE) + { + dma_released = RT_TRUE; + } + + if ((hal_stopped == RT_TRUE) || (dma_released == RT_TRUE)) + { + adc->handle.DMA_Handle = RT_NULL; + adc->dma_handle.Parent = RT_NULL; + stm32_adc_stream_release_cache_buffer(adc); + *hardware_stopped = RT_TRUE; + return result; + } + + return (result != RT_EOK) ? result : -RT_ERROR; +} + +/** + * @brief Check whether a HAL ADC handle belongs to an active stream DMA session. + * @param adc Pointer to the STM32 ADC device object. + * @param hadc Pointer to the HAL ADC handle. + * @return RT_TRUE when the handle is attached to the stream DMA backend. + */ +static rt_bool_t stm32_adc_stream_dma_is_active(const struct stm32_adc *adc, const ADC_HandleTypeDef *hadc) +{ + if (hadc->DMA_Handle != &adc->dma_handle) + { + return RT_FALSE; + } + + return (adc->device.stream_ctrl.active == RT_TRUE) ? RT_TRUE : RT_FALSE; +} + +#ifdef RT_ADC_STREAM_USING_FIFO +/** + * @brief Dispatch one ADC stream DMA completion event to the ADC framework. + * @param hadc Pointer to the HAL ADC handle. + * @param event DMA stream event to report. + */ +static void stm32_adc_stream_dma_callback(ADC_HandleTypeDef *hadc, enum rt_adc_stream_event event) +{ + struct stm32_adc *adc; + struct rt_adc_stream_ctrl *ctrl; + const rt_uint32_t *sample_buffer; + rt_size_t half; + rt_size_t sample_count; + rt_err_t result; + + RT_ASSERT(hadc != RT_NULL); + adc = (struct stm32_adc *)hadc; + if (stm32_adc_stream_dma_is_active(adc, hadc) != RT_TRUE) + { + return; + } + + ctrl = &adc->device.stream_ctrl; + sample_buffer = RT_NULL; + sample_count = 0U; + + if (ctrl->policy != RT_ADC_STREAM_POLICY_FIFO) + { + return; + } + + if (ctrl->dma_event_mode == RT_ADC_STREAM_DMA_EVENT_FULL_ONLY) + { + if (event != RT_ADC_STREAM_EVENT_DMA_DONE) + { + return; + } + sample_buffer = ctrl->dma_buffer; + sample_count = ctrl->dma_buffer_length; + } + else if (ctrl->dma_event_mode == RT_ADC_STREAM_DMA_EVENT_HALF_FULL) + { + half = ctrl->dma_buffer_length / 2U; + if (event == RT_ADC_STREAM_EVENT_DMA_DONE) + { + sample_buffer = &ctrl->dma_buffer[half]; + sample_count = ctrl->dma_buffer_length - half; + } + else + { + sample_buffer = ctrl->dma_buffer; + sample_count = half; + } + } + + if (sample_count == 0U) + { + return; + } + + result = stm32_adc_stream_sync(&adc->device, sample_buffer, sample_count); + if (result != RT_EOK) + { + rt_atomic_store(&ctrl->last_error, (rt_atomic_t)result); + event = RT_ADC_STREAM_EVENT_ERROR; + sample_buffer = RT_NULL; + sample_count = 0U; + } + + (void)rt_hw_adc_stream_isr(&adc->device, event, sample_buffer, sample_count); +} + +/** + * @brief HAL ADC DMA half-transfer callback. + * @param hadc Pointer to the HAL ADC handle. + */ +void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc) +{ + stm32_adc_stream_dma_callback(hadc, RT_ADC_STREAM_EVENT_DMA_HALF); +} + +/** + * @brief HAL ADC DMA transfer-complete callback. + * @param hadc Pointer to the HAL ADC handle. + */ +void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) +{ + stm32_adc_stream_dma_callback(hadc, RT_ADC_STREAM_EVENT_DMA_DONE); +} + +#else +/** + * @brief HAL ADC DMA half-transfer callback. + * @param hadc Pointer to the HAL ADC handle. + */ +void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc) +{ + RT_UNUSED(hadc); +} + +/** + * @brief HAL ADC DMA transfer-complete callback. + * @param hadc Pointer to the HAL ADC handle. + */ +void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) +{ + RT_UNUSED(hadc); +} +#endif /* RT_ADC_STREAM_USING_FIFO */ + +/** + * @brief HAL ADC error callback. + * @param hadc Pointer to the HAL ADC handle. + */ +void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc) +{ + struct stm32_adc *adc; + struct rt_adc_stream_ctrl *ctrl; + + RT_ASSERT(hadc != RT_NULL); + adc = (struct stm32_adc *)hadc; + if (stm32_adc_stream_dma_is_active(adc, hadc) != RT_TRUE) + { + return; + } + + ctrl = &adc->device.stream_ctrl; + rt_atomic_store(&ctrl->last_error, (rt_atomic_t)-RT_ERROR); + LOG_E("%s stream HAL ADC error: error_code=0x%08lx", adc->name, (unsigned long)hadc->ErrorCode); + (void)rt_hw_adc_stream_isr(&adc->device, RT_ADC_STREAM_EVENT_ERROR, RT_NULL, 0U); +} + +#if defined(BSP_USING_ADC1) && defined(BSP_ADC1_USING_DMA) +/** + * @brief ADC1 DMA interrupt handler. + */ +void ADC1_DMA_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_DMA_IRQHandler(&stm32_adc_obj[ADC1_INDEX].dma_handle); + rt_interrupt_leave(); +} +#endif /* defined(BSP_USING_ADC1) && defined(BSP_ADC1_USING_DMA) */ + +#if defined(BSP_USING_ADC2) && defined(BSP_ADC2_USING_DMA) +/** + * @brief ADC2 DMA interrupt handler. + */ +void ADC2_DMA_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_DMA_IRQHandler(&stm32_adc_obj[ADC2_INDEX].dma_handle); + rt_interrupt_leave(); +} +#endif /* defined(BSP_USING_ADC2) && defined(BSP_ADC2_USING_DMA) */ + +#if defined(BSP_USING_ADC3) && defined(BSP_ADC3_USING_DMA) +/** + * @brief ADC3 DMA interrupt handler. + */ +void ADC3_DMA_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_DMA_IRQHandler(&stm32_adc_obj[ADC3_INDEX].dma_handle); + rt_interrupt_leave(); +} +#endif /* defined(BSP_USING_ADC3) && defined(BSP_ADC3_USING_DMA) */ + +#if defined(BSP_USING_ADC4) && defined(BSP_ADC4_USING_DMA) +/** + * @brief ADC4 DMA interrupt handler. + */ +void ADC4_DMA_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_DMA_IRQHandler(&stm32_adc_obj[ADC4_INDEX].dma_handle); + rt_interrupt_leave(); +} +#endif /* defined(BSP_USING_ADC4) && defined(BSP_ADC4_USING_DMA) */ +#endif /* STM32_ADC_USING_DMA_STREAM */ + +#if defined(STM32_ADC_HAS_LL_VREF_CALC) +/** + * @brief Calculate the ADC reference voltage from a raw VREF sample. + * @param device Pointer to the ADC device object. + * @param vref_mv Pointer to the input raw VREF code and output VDDA in mV. + * @return Operation status. + */ +rt_err_t stm32_adc_calc_vref_mv(struct rt_adc_device *device, rt_uint32_t *vref_mv) +{ + struct stm32_adc *adc; + rt_uint32_t raw_value; + + if (*vref_mv == 0U) + { + return -RT_EINVAL; + } + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + raw_value = *vref_mv; + *vref_mv = (rt_uint32_t)STM32_ADC_CALC_VREF_MV(adc, raw_value); + if (*vref_mv == 0U) + { + return -RT_EINVAL; + } + + LOG_D("%s VREF calculated: raw=%lu vref=%lu mV", adc->name, (unsigned long)raw_value, (unsigned long)*vref_mv); + return RT_EOK; +} +#endif /* defined(STM32_ADC_HAS_LL_VREF_CALC) */ + +/** + * @brief Handle control commands on one STM32 ADC device. + * @param device Pointer to the ADC device object. + * @param cmd Control command. + * @param args Pointer to the control argument buffer. + * @return Operation status. + */ +static rt_err_t stm32_adc_control(struct rt_adc_device *device, int cmd, void *args) +{ + struct stm32_adc *adc; + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + LOG_D("%s control cmd=%d", adc->name, cmd); + switch (cmd) + { + case RT_ADC_CMD_GET_RESOLUTION: + if (args == RT_NULL) + { + return -RT_EINVAL; + } + *((rt_uint8_t *)args) = stm32_adc_get_resolution_bits(adc); + return RT_EOK; + + case RT_ADC_CMD_GET_VREF_CHANNEL: + if (args == RT_NULL) + { + return -RT_EINVAL; + } + return stm32_adc_get_vref_logical_channel(adc, (rt_uint8_t *)args); + + case RT_ADC_CMD_CALC_VREF: + if (args == RT_NULL) + { + return -RT_EINVAL; + } +#if defined(STM32_ADC_HAS_LL_VREF_CALC) + return stm32_adc_calc_vref_mv(device, (rt_uint32_t *)args); +#else + if (device->default_vref_mv == 0U) + { + return -RT_ENOSYS; + } + *((rt_uint32_t *)args) = device->default_vref_mv; + return RT_EOK; +#endif /* defined(STM32_ADC_HAS_LL_VREF_CALC) */ + + case RT_ADC_CMD_CALIBRATE: +#if defined(STM32_ADC_HAS_CALIBRATION) + return stm32_adc_run_calibration(adc, &adc->config); +#else + return -RT_ENOSYS; +#endif /* defined(STM32_ADC_HAS_CALIBRATION) */ + + case RT_ADC_CMD_SET_CONFIG: + if (args == RT_NULL) + { + return -RT_EINVAL; + } + + adc->config = *((const struct stm32_adc_private_cfg *)args); + return RT_EOK; + + case RT_ADC_CMD_GET_CONFIG: + if (args == RT_NULL) + { + return -RT_EINVAL; + } + *((struct stm32_adc_private_cfg *)args) = adc->config; + return RT_EOK; + + case RT_ADC_CMD_CLEAR_CHANNEL_CONFIG: + if (args != RT_NULL) + { + return -RT_EINVAL; + } + return stm32_adc_clear_channel_config(adc); + + default: + RT_UNUSED(args); + return -RT_ENOSYS; + } +} + +/** + * @brief STM32 ADC core operation table. + */ +static const struct rt_adc_core_ops stm32_adc_core_ops = { + .open = stm32_adc_open, + .close = stm32_adc_close, + .session_config = stm32_adc_session_config, +#if defined(STM32_ADC_USING_TRIGGER) + .trigger_prepare = stm32_adc_trigger_prepare, +#endif /* defined(STM32_ADC_USING_TRIGGER) */ + .control = stm32_adc_control, +}; + +/** + * @brief STM32 ADC sequence-session operation table. + */ +static const struct rt_adc_sequence_ops stm32_adc_sequence_ops = { + .start = stm32_adc_sequence_start, + .read = stm32_adc_sequence_read, + .stop = stm32_adc_sequence_stop, +}; + +#if STM32_ADC_USING_DMA_STREAM +/** + * @brief STM32 ADC stream-session operation table. + */ +static const struct rt_adc_stream_ops stm32_adc_stream_ops = { + .start = stm32_adc_stream_start, + .sync = stm32_adc_stream_sync, + .stop = stm32_adc_stream_stop, +}; +#endif /* STM32_ADC_USING_DMA_STREAM */ + +/** + * @brief STM32 ADC operation table. + */ +static const struct rt_adc_ops stm32_adc_ops = { + .core = &stm32_adc_core_ops, + .sequence = &stm32_adc_sequence_ops, +#if STM32_ADC_USING_DMA_STREAM + .stream = &stm32_adc_stream_ops, +#endif /* STM32_ADC_USING_DMA_STREAM */ +}; + +/** + * @brief Initialize and register STM32 ADC devices. + * @return Operation status. + */ +int stm32_adc_init(void) +{ + rt_size_t index; + int result; + + result = RT_EOK; + for (index = 0; index < RT_ARRAY_SIZE(stm32_adc_obj); index++) + { + rt_atomic_store(&stm32_adc_obj[index].device.state, RT_ADC_STATE_IDLE); + stm32_adc_obj[index].device.default_vref_mv = 0; + if (rt_hw_adc_register(&stm32_adc_obj[index].device, stm32_adc_obj[index].name, + &stm32_adc_ops, &stm32_adc_obj[index]) != RT_EOK) + { + result = -RT_ERROR; + continue; + } + } + + return result; +} +INIT_BOARD_EXPORT(stm32_adc_init); +#endif /* defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) || defined(BSP_USING_ADC4) */ + +#endif /* defined(RT_USING_ADC_V2) */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.h new file mode 100644 index 00000000000..a26f7a3aa3d --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add stm32 adc v2 driver declarations + */ + +/** + * @file drv_adc_v2.h + * @brief STM32 ADC V2 driver declarations. + */ + +#ifndef __DRV_ADC_V2_H__ +#define __DRV_ADC_V2_H__ + +#include + +#if defined(RT_USING_ADC_V2) +#include +#include +#include + +/** + * @brief STM32 ADC backend private device configuration. + * + * @note The fields map directly to STM32 HAL ADC initialization values. Use + * ADC_RESOLUTION_xxx, ADC_OVERSAMPLING_RATIO_xxx, and + * ADC_RIGHTBITSHIFT_xxx macros from the active STM32 HAL headers when + * the corresponding feature exists. The configuration should be updated + * before opening the ADC device. + */ +struct stm32_adc_private_cfg +{ + rt_uint32_t sampling_time; /**< HAL ADC sampling-time value; 0 uses ADC_DEFAULT_SAMPLING_TIME. */ + rt_uint32_t resolution; /**< HAL ADC resolution value; 0 uses ADC_DEFAULT_RESOLUTION. */ + rt_uint32_t data_align; /**< HAL ADC data-alignment value; 0 uses ADC_DEFAULT_DATA_ALIGN. */ + rt_uint8_t input_modes; /**< Bit mask of enum rt_adc_input_mode values; 0 uses single-ended input. */ + rt_uint8_t reserved[3]; /**< Reserved for alignment and future STM32 backend options. */ + rt_uint32_t oversampling_ratio; /**< HAL ADC oversampling ratio; 0 disables hardware oversampling. */ + rt_uint32_t oversampling_right_shift; /**< HAL ADC oversampling right shift; 0 uses no right shift. */ +}; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief Initialize and register STM32 ADC devices. + * @return Operation status. + */ +int stm32_adc_init(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __DRV_ADC_V2_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_msh.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_msh.c new file mode 100644 index 00000000000..fc86157418b --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_msh.c @@ -0,0 +1,810 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-05-24 wdfk-prog split stm32 adc v2 msh special commands + */ + +/** + * @file drv_adc_v2_msh.c + * @brief STM32 ADC V2 FinSH/MSH special-channel commands. + */ +#include + +#include + +#if defined(RT_USING_ADC_V2) + +#include "drv_adc_v2_private.h" + +#if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) || defined(BSP_USING_ADC4) + +#define DRV_DEBUG +#define LOG_TAG "drv.adc.msh" +#include + +#if defined(RT_USING_FINSH) && defined(RT_ADC_V2_USING_MSH) + +/** @brief Default timeout in milliseconds for STM32 ADC MSH special reads. */ +#define STM32_ADC_MSH_DEFAULT_READ_TIMEOUT_MS 1000 + +#if defined(STM32_ADC_HAS_LL_VREF_CALC) +#define STM32_ADC_MSH_HAS_VREF_READ 1 +#endif /* defined(STM32_ADC_HAS_LL_VREF_CALC) */ + +#if defined(STM32_ADC_HAS_LL_TEMPERATURE_CALC) || defined(STM32_ADC_HAS_TEMPSENSOR_CALIBRATION_DATA) +#define STM32_ADC_MSH_HAS_TEMPSENSOR_READ 1 +#endif /* defined(STM32_ADC_HAS_LL_TEMPERATURE_CALC) || defined(STM32_ADC_HAS_TEMPSENSOR_CALIBRATION_DATA) */ + +#define STM32_ADC_MSH_HAS_VBAT_READ 1 + +#if defined(STM32_ADC_MSH_HAS_VREF_READ) || defined(STM32_ADC_MSH_HAS_TEMPSENSOR_READ) || \ + defined(STM32_ADC_MSH_HAS_VBAT_READ) +#define STM32_ADC_MSH_HAS_SPECIAL_READ 1 +#endif /* defined(STM32_ADC_MSH_HAS_VREF_READ) || defined(STM32_ADC_MSH_HAS_TEMPSENSOR_READ) || defined(STM32_ADC_MSH_HAS_VBAT_READ) */ + +#if defined(STM32_ADC_MSH_HAS_SPECIAL_READ) +/** + * @brief Sample data read from one STM32 internal ADC channel. + */ +struct stm32_adc_special_sample +{ + rt_uint32_t raw_value; /**< Raw ADC sample of the requested channel. */ + rt_uint32_t vref_mv; /**< VDDA calculated from VREFINT, in millivolts. */ + rt_uint8_t resolution_bits; /**< ADC conversion resolution in bits. */ +}; +#endif /* defined(STM32_ADC_MSH_HAS_SPECIAL_READ) */ + +#if defined(STM32_ADC_MSH_HAS_SPECIAL_READ) +/** + * @brief Get VDDA in millivolts for STM32 ADC special-channel conversion. + * @param device Pointer to the ADC device object. + * @param samples Pointer to the ADC sample buffer containing VREFINT raw data. + * @param has_vref_sample Whether @p samples contains a valid VREFINT sample. + * @param vref_index Index of the VREFINT sample in @p samples. + * @param vref_mv Pointer to the output analog reference voltage in millivolts. + * @return Operation status. + * + * This helper prefers the sampled VREFINT path when a VREFINT sample is + * available. If dynamic VREF calculation is unavailable or VREFINT is not part + * of the current session, it falls back to the framework default_vref_mv. + */ +static rt_err_t stm32_adc_msh_get_vref_mv(rt_adc_device_t device, const rt_uint32_t *samples, rt_bool_t has_vref_sample, + rt_size_t vref_index, rt_uint32_t *vref_mv) +{ + if (has_vref_sample == RT_TRUE) + { +#if defined(STM32_ADC_HAS_LL_VREF_CALC) + rt_err_t result; + *vref_mv = samples[vref_index]; + result = stm32_adc_calc_vref_mv(device, vref_mv); + if (result == RT_EOK) + { + return RT_EOK; + } + + if (result != -RT_ENOSYS) + { + return result; + } +#else + RT_UNUSED(samples); + RT_UNUSED(vref_index); +#endif /* defined(STM32_ADC_HAS_LL_VREF_CALC) */ + } + + if (device->default_vref_mv != 0U) + { + *vref_mv = device->default_vref_mv; + return RT_EOK; + } + + return (has_vref_sample == RT_TRUE) ? -RT_ENOSYS : -RT_EINVAL; +} + +/** + * @brief Read one preconfigured STM32 internal ADC channel sample. + * @param device Pointer to the ADC device object. + * @param channel Logical ADC channel identifier. + * @param need_vref Whether the caller needs VDDA for value conversion. + * @param timeout_ms Per-sample timeout in milliseconds; negative means wait forever. + * @param sample Pointer to the output special-channel sample. + * @return Operation status. + * + * This helper reads using the currently configured framework session. The + * caller must first configure an active framework session containing the + * requested special channel. If @p need_vref is RT_TRUE, VDDA is calculated + * from VREFINT when VREFINT is present in the session; otherwise the configured + * default_vref_mv is used as the fallback reference voltage. + */ +static rt_err_t stm32_adc_read_special_sample(rt_adc_device_t device, rt_uint8_t channel, rt_bool_t need_vref, + rt_int32_t timeout_ms, struct stm32_adc_special_sample *sample) +{ + struct stm32_adc *adc; + struct rt_adc_sequence_cfg sequence_cfg; + rt_uint32_t samples[STM32_ADC_MAX_CHANNELS]; + rt_uint8_t vref_channel; + rt_bool_t has_vref_sample; + rt_size_t sample_count; + rt_size_t sample_index; + rt_size_t vref_index; + rt_size_t read_count; + rt_err_t result; + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + + if ((device->session_ctrl.configured != RT_TRUE) || (device->session_ctrl.channel_count == 0U) || + ((device->session_ctrl.channels & RT_ADC_CHANNEL_MASK(channel)) == 0U)) + { + return -RT_EINVAL; + } + + sample_count = device->session_ctrl.channel_count; + if (sample_count > RT_ARRAY_SIZE(samples)) + { + return -RT_EINVAL; + } + + result = rt_adc_session_channel_index(device->session_ctrl.channels, RT_ADC_CHANNEL_MASK(channel), &sample_index); + if (result != RT_EOK) + { + return result; + } + + vref_index = 0U; + has_vref_sample = RT_FALSE; + + if (need_vref == RT_TRUE) + { + result = stm32_adc_get_vref_logical_channel(adc, &vref_channel); + if (result == RT_EOK) + { + if ((device->session_ctrl.channels & RT_ADC_CHANNEL_MASK(vref_channel)) != 0U) + { + result = rt_adc_session_channel_index(device->session_ctrl.channels, + RT_ADC_CHANNEL_MASK(vref_channel), &vref_index); + if (result != RT_EOK) + { + return result; + } + + has_vref_sample = RT_TRUE; + } + else if (device->default_vref_mv == 0U) + { + return -RT_EINVAL; + } + } + else if (device->default_vref_mv == 0U) + { + return result; + } + } + + rt_memset(&sequence_cfg, 0, sizeof(sequence_cfg)); + rt_memset(samples, 0, sizeof(samples)); + sequence_cfg.buffer = samples; + sequence_cfg.buffer_length = sample_count; + sequence_cfg.timeout_ms = timeout_ms; + + result = rt_adc_read_sequence(device, device->session_ctrl.channels, &sequence_cfg, &read_count); + if (result != RT_EOK) + { + return result; + } + + if (read_count <= sample_index) + { + return -RT_ERROR; + } + + sample->raw_value = samples[sample_index]; + sample->vref_mv = 0U; + sample->resolution_bits = stm32_adc_get_resolution_bits(adc); + + if (need_vref == RT_TRUE) + { + if (sample->resolution_bits == 0U) + { + return -RT_EINVAL; + } + + result = stm32_adc_msh_get_vref_mv(device, samples, has_vref_sample, vref_index, &sample->vref_mv); + if (result != RT_EOK) + { + return result; + } + } + + return RT_EOK; +} +#endif /* defined(STM32_ADC_MSH_HAS_SPECIAL_READ) */ + +#if defined(STM32_ADC_MSH_HAS_TEMPSENSOR_READ) +/** + * @brief Check whether STM32 ADC MSH can provide VDDA for temperature conversion. + * @param adc Pointer to the STM32 ADC device object. + * @param device Pointer to the ADC device object. + * @return RT_TRUE if temperature conversion can obtain VDDA, otherwise RT_FALSE. + * + * Temperature conversion requires VDDA in millivolts. Dynamic VDDA calculation + * requires a supported VREFINT logical channel and LL VREF calculation support; + * otherwise the framework default_vref_mv must be configured. + */ +static rt_bool_t stm32_adc_msh_has_temperature_vref_source(struct stm32_adc *adc, rt_adc_device_t device) +{ + rt_uint8_t vref_channel; + + if ((adc == RT_NULL) || (device == RT_NULL)) + { + return RT_FALSE; + } + + if (device->default_vref_mv != 0U) + { + return RT_TRUE; + } + +#if defined(STM32_ADC_HAS_LL_VREF_CALC) + if (stm32_adc_get_vref_logical_channel(adc, &vref_channel) == RT_EOK) + { + return RT_TRUE; + } +#else + RT_UNUSED(vref_channel); +#endif /* defined(STM32_ADC_HAS_LL_VREF_CALC) */ + + return RT_FALSE; +} +#endif /* defined(STM32_ADC_MSH_HAS_TEMPSENSOR_READ) */ + +#if defined(STM32_ADC_MSH_HAS_VREF_READ) +/** + * @brief Read VREFINT and calculate VDDA in millivolts for STM32 ADC MSH. + * @param device Pointer to the ADC device object. + * @param timeout_ms Per-sample timeout in milliseconds; negative means wait forever. + * @param vref_mv Pointer to the output analog reference voltage in millivolts. + * @return Operation status. + * + * VREF read requires LL VREF calculation support. Without that support, the + * command is reported as unsupported instead of returning default_vref_mv. + */ +static rt_err_t stm32_adc_msh_read_vref(rt_adc_device_t device, rt_int32_t timeout_ms, rt_uint32_t *vref_mv) +{ + struct stm32_adc *adc; + struct stm32_adc_special_sample sample; + rt_uint8_t vref_channel; + rt_err_t result; + + if ((device == RT_NULL) || (vref_mv == RT_NULL)) + { + return -RT_EINVAL; + } + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + result = stm32_adc_get_vref_logical_channel(adc, &vref_channel); + if (result != RT_EOK) + { + return result; + } + + result = stm32_adc_read_special_sample(device, vref_channel, RT_FALSE, timeout_ms, &sample); + if (result != RT_EOK) + { + return result; + } + + return stm32_adc_msh_get_vref_mv(device, &sample.raw_value, RT_TRUE, 0U, vref_mv); +} +#endif /* defined(STM32_ADC_MSH_HAS_VREF_READ) */ + +#if defined(STM32_ADC_MSH_HAS_TEMPSENSOR_READ) +/** + * @brief Read the STM32 internal temperature sensor for ADC MSH. + * @param device Pointer to the ADC device object. + * @param timeout_ms Per-sample timeout in milliseconds; negative means wait forever. + * @param temperature_c Pointer to the output temperature in degrees Celsius. + * @return Operation status. + */ +static rt_err_t stm32_adc_msh_read_temperature(rt_adc_device_t device, rt_int32_t timeout_ms, rt_int32_t *temperature_c) +{ + struct stm32_adc *adc; + struct stm32_adc_special_sample sample; + rt_uint8_t tempsensor_channel; + rt_err_t result; + + if ((device == RT_NULL) || (temperature_c == RT_NULL)) + { + return -RT_EINVAL; + } + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + result = stm32_adc_get_tempsensor_logical_channel(adc, &tempsensor_channel); + if (result != RT_EOK) + { + return result; + } + + result = stm32_adc_read_special_sample(device, tempsensor_channel, RT_TRUE, timeout_ms, &sample); + if (result != RT_EOK) + { + return result; + } + + return stm32_adc_calc_temperature(device, sample.raw_value, sample.vref_mv, sample.resolution_bits, temperature_c); +} +#endif /* defined(STM32_ADC_MSH_HAS_TEMPSENSOR_READ) */ + +#if defined(STM32_ADC_MSH_HAS_VBAT_READ) +/** + * @brief Read raw VBAT ADC sample for STM32 ADC MSH. + * @param device Pointer to the ADC device object. + * @param timeout_ms Per-sample timeout in milliseconds; negative means wait forever. + * @param raw_value Pointer to the output raw VBAT ADC sample. + * @return Operation status. + */ +static rt_err_t stm32_adc_msh_read_vbat(rt_adc_device_t device, rt_int32_t timeout_ms, rt_uint32_t *raw_value) +{ + struct stm32_adc *adc; + struct stm32_adc_special_sample sample; + rt_uint8_t vbat_channel; + rt_err_t result; + + if ((device == RT_NULL) || (raw_value == RT_NULL)) + { + return -RT_EINVAL; + } + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + result = stm32_adc_get_vbat_logical_channel(adc, &vbat_channel); + if (result != RT_EOK) + { + return result; + } + + result = stm32_adc_read_special_sample(device, vbat_channel, RT_FALSE, timeout_ms, &sample); + if (result != RT_EOK) + { + return result; + } + + *raw_value = sample.raw_value; + return RT_EOK; +} +#endif /* defined(STM32_ADC_MSH_HAS_VBAT_READ) */ + +/** + * @brief Get one STM32 ADC special MSH item property. + * @param device Pointer to the ADC device object. + * @param name Pointer to the item name. + * @param channel Pointer to the output logical channel. + * @param need_vref Optional pointer to the output VREF requirement flag. + * @param unit Optional pointer to the output display unit string. + * @return Operation status. + */ +static rt_err_t stm32_adc_msh_get_item(rt_adc_device_t device, const char *name, rt_uint8_t *channel, + rt_bool_t *need_vref, const char **unit) +{ + struct stm32_adc *adc; + + if ((device == RT_NULL) || (name == RT_NULL) || (channel == RT_NULL)) + { + return -RT_EINVAL; + } + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + +#if defined(STM32_ADC_MSH_HAS_VREF_READ) + if (rt_strcmp(name, "vref") == 0) + { + if (need_vref != RT_NULL) + { + *need_vref = RT_FALSE; + } + if (unit != RT_NULL) + { + *unit = "mV"; + } + return stm32_adc_get_vref_logical_channel(adc, channel); + } +#endif /* defined(STM32_ADC_MSH_HAS_VREF_READ) */ + +#if defined(STM32_ADC_MSH_HAS_TEMPSENSOR_READ) + if (rt_strcmp(name, "temp") == 0) + { + if (stm32_adc_get_tempsensor_logical_channel(adc, channel) != RT_EOK) + { + return -RT_ENOSYS; + } + + if (stm32_adc_msh_has_temperature_vref_source(adc, device) != RT_TRUE) + { + return -RT_ENOSYS; + } + + if (need_vref != RT_NULL) + { + *need_vref = RT_TRUE; + } + if (unit != RT_NULL) + { + *unit = "C"; + } + return RT_EOK; + } +#endif /* defined(STM32_ADC_MSH_HAS_TEMPSENSOR_READ) */ + +#if defined(STM32_ADC_MSH_HAS_VBAT_READ) + if (rt_strcmp(name, "vbat") == 0) + { + if (stm32_adc_get_vbat_logical_channel(adc, channel) != RT_EOK) + { + return -RT_ENOSYS; + } + + if (need_vref != RT_NULL) + { + *need_vref = RT_FALSE; + } + if (unit != RT_NULL) + { + *unit = "raw"; + } + return RT_EOK; + } +#endif /* defined(STM32_ADC_MSH_HAS_VBAT_READ) */ + + return -RT_ENOSYS; +} + +/** + * @brief Print one supported STM32 ADC special MSH item if available. + * @param device Pointer to the ADC device object. + * @param name Pointer to the item name. + * @return RT_TRUE if the item was printed, otherwise RT_FALSE. + */ +static rt_bool_t stm32_adc_msh_print_item(rt_adc_device_t device, const char *name) +{ + struct stm32_adc *adc; + const char *unit; + rt_bool_t need_vref; + rt_bool_t has_vref_channel; + rt_uint8_t channel; + rt_uint8_t vref_channel; + rt_err_t result; + + if (stm32_adc_msh_get_item(device, name, &channel, &need_vref, &unit) != RT_EOK) + { + return RT_FALSE; + } + + has_vref_channel = RT_FALSE; + vref_channel = 0U; + + if (need_vref == RT_TRUE) + { + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return RT_FALSE; + } + + result = stm32_adc_get_vref_logical_channel(adc, &vref_channel); + if (result == RT_EOK) + { + has_vref_channel = RT_TRUE; + } + else if (device->default_vref_mv == 0U) + { + rt_kprintf(" %s: unsupported, missing vref/default_vref\n", name); + return RT_FALSE; + } + } + + rt_kprintf(" %s: channel=%u unit=%s", name, (unsigned int)channel, unit); + + if (need_vref == RT_TRUE) + { + if (has_vref_channel == RT_TRUE) + { + rt_kprintf(" needs=vref channel=%u", (unsigned int)vref_channel); + } + else + { + rt_kprintf(" needs=default_vref"); + } + } + + rt_kprintf("\n"); + + return RT_TRUE; +} +/** + * @brief Print supported STM32 ADC special MSH items for the selected device. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ +static rt_err_t stm32_adc_msh_special_list(rt_adc_device_t device) +{ + rt_bool_t has_temp; + rt_size_t count; + + count = 0U; + count += (stm32_adc_msh_print_item(device, "vref") == RT_TRUE) ? 1U : 0U; + has_temp = stm32_adc_msh_print_item(device, "temp"); + + count += (has_temp == RT_TRUE) ? 1U : 0U; + count += (stm32_adc_msh_print_item(device, "vbat") == RT_TRUE) ? 1U : 0U; + + if (count == 0U) + { + rt_kprintf(" no STM32 ADC special channels supported by current device\n"); + } + + return RT_EOK; +} + +/** + * @brief Print STM32 ADC special MSH command usage. + */ +static void stm32_adc_msh_special_usage(void) +{ + rt_kprintf("STM32 ADC special commands:\n"); + rt_kprintf(" adc special list\n"); + rt_kprintf(" adc special read [timeout_ms]\n"); + rt_kprintf(" timeout_ms defaults to 1000; negative means wait forever\n"); + rt_kprintf(" run adc special list first, then use the printed adc config command\n"); + rt_kprintf(" temp accuracy depends on datasheet sampling time; adc special list shows item notes\n"); +} + +/** + * @brief Print ADC config command for one STM32 ADC special MSH item. + * @param device Pointer to the ADC device object. + * @param name Pointer to the item name. + */ +static void stm32_adc_msh_print_config_hint(rt_adc_device_t device, const char *name) +{ + struct stm32_adc *adc; + rt_bool_t need_vref; + rt_uint8_t channel; + rt_uint8_t vref_channel; + + if ((device == RT_NULL) || (name == RT_NULL)) + { + return; + } + + if (stm32_adc_msh_get_item(device, name, &channel, &need_vref, RT_NULL) != RT_EOK) + { + return; + } + + if (need_vref != RT_TRUE) + { + rt_kprintf("configure with: adc config %u\n", (unsigned int)channel); + return; + } + + adc = (struct stm32_adc *)device->parent.user_data; + if ((adc != RT_NULL) && (stm32_adc_get_vref_logical_channel(adc, &vref_channel) == RT_EOK)) + { + rt_kprintf("configure with: adc config %u %u\n", (unsigned int)channel, (unsigned int)vref_channel); + } + else + { + rt_kprintf("configure with: adc config %u\n", (unsigned int)channel); + } +} + +/** + * @brief Parse one optional STM32 ADC special-read timeout argument. + * @param arg Pointer to the timeout argument string. + * @param timeout_ms Pointer to the output timeout in milliseconds. + * @return Operation status. + * + * A negative timeout keeps the ADC framework convention of waiting forever. + */ +static rt_err_t stm32_adc_msh_parse_timeout(const char *arg, rt_int32_t *timeout_ms) +{ + char *endptr; + long value; + + if ((arg == RT_NULL) || (timeout_ms == RT_NULL) || (*arg == '\0')) + { + return -RT_EINVAL; + } + + endptr = RT_NULL; + value = strtol(arg, &endptr, 0); + if ((endptr == arg) || (endptr == RT_NULL) || (*endptr != '\0')) + { + return -RT_EINVAL; + } + + if ((value > 2147483647L) || (value < (-2147483647L - 1L))) + { + return -RT_EINVAL; + } + + *timeout_ms = (rt_int32_t)value; + return RT_EOK; +} + +/** + * @brief Print and normalize one STM32 ADC special MSH command result. + * @param device Pointer to the ADC device object. + * @param name Pointer to the requested item name. + * @param action Pointer to the action name. + * @param result Operation status to normalize. + * @return Operation status for the framework-level command dispatcher. + */ +static rt_err_t stm32_adc_msh_finish_special_result(rt_adc_device_t device, const char *name, + const char *action, rt_err_t result) +{ + if (result == RT_EOK) + { + return RT_EOK; + } + + rt_kprintf("%s %s failed: %d\n", name, action, result); + + if (result == -RT_EINVAL) + { + rt_kprintf("run adc special list first or use the following command before reading\n"); + stm32_adc_msh_print_config_hint(device, name); + } + + return (result == -RT_ENOSYS) ? -RT_ERROR : result; +} + +/** + * @brief Handle one STM32 ADC special MSH read command. + * @param device Pointer to the ADC device object. + * @param argc Argument count excluding the top-level adc command. + * @param argv Argument vector excluding the top-level adc command. + * @return Operation status. + */ +static rt_err_t stm32_adc_msh_special_read(rt_adc_device_t device, int argc, char **argv) +{ + const char *name; + rt_uint8_t channel; + rt_int32_t timeout_ms; + rt_err_t result; + + if ((argc != 3) && (argc != 4)) + { + stm32_adc_msh_special_usage(); + return -RT_EINVAL; + } + + name = argv[2]; + timeout_ms = STM32_ADC_MSH_DEFAULT_READ_TIMEOUT_MS; + if ((argc == 4) && (stm32_adc_msh_parse_timeout(argv[3], &timeout_ms) != RT_EOK)) + { + rt_kprintf("invalid timeout_ms: %s\n", argv[3]); + return -RT_EINVAL; + } + + result = stm32_adc_msh_get_item(device, name, &channel, RT_NULL, RT_NULL); + if (result != RT_EOK) + { + rt_kprintf("%s is not supported by current STM32 ADC device\n", name); + return -RT_EINVAL; + } + +#if defined(STM32_ADC_MSH_HAS_VREF_READ) + if (rt_strcmp(name, "vref") == 0) + { + rt_uint32_t value_mv; + result = stm32_adc_msh_read_vref(device, timeout_ms, &value_mv); + if (result == RT_EOK) + { + rt_kprintf("vref: %lu mV\n", (unsigned long)value_mv); + } + return stm32_adc_msh_finish_special_result(device, name, "read", result); + } +#endif /* defined(STM32_ADC_MSH_HAS_VREF_READ) */ + +#if defined(STM32_ADC_MSH_HAS_TEMPSENSOR_READ) + if (rt_strcmp(name, "temp") == 0) + { + rt_int32_t temperature_c; + result = stm32_adc_msh_read_temperature(device, timeout_ms, &temperature_c); + if (result == RT_EOK) + { + rt_kprintf("temp: %ld C\n", (long)temperature_c); + } + return stm32_adc_msh_finish_special_result(device, name, "read", result); + } +#endif /* defined(STM32_ADC_MSH_HAS_TEMPSENSOR_READ) */ + +#if defined(STM32_ADC_MSH_HAS_VBAT_READ) + if (rt_strcmp(name, "vbat") == 0) + { + rt_uint32_t raw_value; + result = stm32_adc_msh_read_vbat(device, timeout_ms, &raw_value); + if (result == RT_EOK) + { + rt_kprintf("vbat: %lu raw\n", (unsigned long)raw_value); + } + return stm32_adc_msh_finish_special_result(device, name, "read", result); + } +#endif /* defined(STM32_ADC_MSH_HAS_VBAT_READ) */ + + RT_UNUSED(channel); + return -RT_ENOSYS; +} + +/** + * @brief Print STM32 ADC backend-specific FinSH command usage. + */ +void rt_adc_msh_special_help(void) +{ + stm32_adc_msh_special_usage(); +} + +/** + * @brief Handle STM32 ADC backend-specific FinSH commands. + * @param device Pointer to the selected ADC device object. + * @param argc Argument count excluding the top-level adc command. + * @param argv Argument vector excluding the top-level adc command. + * @return Operation status. + */ +rt_err_t rt_adc_msh_special(rt_adc_device_t device, int argc, char **argv) +{ + if ((device == RT_NULL) || (argv == RT_NULL) || (argc <= 0)) + { + return -RT_EINVAL; + } + + if (rt_strcmp(argv[0], "special") != 0) + { + return -RT_ENOSYS; + } + + if ((argc == 2) && (rt_strcmp(argv[1], "list") == 0)) + { + return stm32_adc_msh_special_list(device); + } + + if ((argc >= 3) && (rt_strcmp(argv[1], "read") == 0)) + { + return stm32_adc_msh_special_read(device, argc, argv); + } + + stm32_adc_msh_special_usage(); + return -RT_EINVAL; +} + +#endif /* defined(RT_USING_FINSH) && defined(RT_ADC_V2_USING_MSH) */ + +#endif /* defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) || defined(BSP_USING_ADC4) */ + +#endif /* defined(RT_USING_ADC_V2) */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h new file mode 100644 index 00000000000..99d2ee9ff8d --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h @@ -0,0 +1,787 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +/** + * @file drv_adc_v2_private.h + * @brief Private declarations for the STM32 ADC V2 backend. + */ + +#ifndef __DRV_ADC_V2_PRIVATE_H__ +#define __DRV_ADC_V2_PRIVATE_H__ + +#include + +#if defined(RT_USING_ADC_V2) + +#include "drv_adc_v2.h" +#include + +#if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) || defined(BSP_USING_ADC4) + +/* STM32 HAL ADC support is detected here when the HAL exposes a stable + * feature macro. Keep series-specific defaults and internal-channel routing + * overrides in config//adc_config_v2.h; keep HAL structure/API + * compatibility here so new series normally inherit support from their HAL + * headers. + */ + +/* STM32F0-like sequencers use ADC_RANK_CHANNEL_NUMBER instead of a numeric + * regular-rank slot. Other HALs that expose ADC_REGULAR_RANK_x constants can + * use those constants directly; otherwise plain rank numbers are used. + */ +#if defined(ADC_RANK_CHANNEL_NUMBER) +#define STM32_ADC_HAS_CHANNEL_NUMBER_RANK 1 +#elif defined(ADC_REGULAR_RANK_1) +#define STM32_ADC_HAS_ENUM_RANK 1 +#endif /* defined(ADC_RANK_CHANNEL_NUMBER) */ + +#if defined(ADC_CONVERSIONDATA_DR) && defined(ADC_CONVERSIONDATA_DMA_CIRCULAR) +#define STM32_ADC_HAS_INIT_CONVERSION_DATA_MANAGEMENT 1 +#endif /* defined(ADC_CONVERSIONDATA_DR) && defined(ADC_CONVERSIONDATA_DMA_CIRCULAR) */ + +#if defined(ADC_SCAN_ENABLE) +#define STM32_ADC_SCAN_MODE_ENABLE ADC_SCAN_ENABLE +#elif defined(ADC_SCAN_DIRECTION_FORWARD) +#define STM32_ADC_SCAN_MODE_ENABLE ADC_SCAN_DIRECTION_FORWARD +#else +#define STM32_ADC_SCAN_MODE_ENABLE ENABLE +#endif /* defined(ADC_SCAN_ENABLE) */ + +#if defined(ADC_SCAN_DISABLE) +#define STM32_ADC_SCAN_MODE_DISABLE ADC_SCAN_DISABLE +#elif defined(ADC_SCAN_DIRECTION_FORWARD) +#define STM32_ADC_SCAN_MODE_DISABLE ADC_SCAN_DIRECTION_FORWARD +#else +#define STM32_ADC_SCAN_MODE_DISABLE DISABLE +#endif /* defined(ADC_SCAN_DISABLE) */ + +/* Channel configuration fields are tied to HAL channel-mode and offset macros. + * A config file may still override these before including this driver header if + * a vendor HAL variant exposes a different field layout. + */ +#if !defined(STM32_ADC_HAS_SINGLE_DIFF_FIELDS) +#if defined(ADC_SINGLE_ENDED) && defined(ADC_DIFFERENTIAL_ENDED) +#define STM32_ADC_HAS_SINGLE_DIFF_FIELDS 1 +#define STM32_ADC_SINGLE_ENDED_VALUE ADC_SINGLE_ENDED +#define STM32_ADC_DIFFERENTIAL_VALUE ADC_DIFFERENTIAL_ENDED +#elif defined(LL_ADC_SINGLE_ENDED) && defined(LL_ADC_DIFFERENTIAL_ENDED) +#define STM32_ADC_HAS_SINGLE_DIFF_FIELDS 1 +#define STM32_ADC_SINGLE_ENDED_VALUE LL_ADC_SINGLE_ENDED +#define STM32_ADC_DIFFERENTIAL_VALUE LL_ADC_DIFFERENTIAL_ENDED +#endif /* defined(ADC_SINGLE_ENDED) && defined(ADC_DIFFERENTIAL_ENDED) */ +#endif /* !defined(STM32_ADC_HAS_SINGLE_DIFF_FIELDS) */ + +#if defined(ADC_OFFSET_NONE) +#ifndef STM32_ADC_HAS_CONFIG_OFFSET +#define STM32_ADC_HAS_CONFIG_OFFSET 1 +#endif /* STM32_ADC_HAS_CONFIG_OFFSET */ +#ifndef STM32_ADC_HAS_CONFIG_OFFSET_NUMBER +#define STM32_ADC_HAS_CONFIG_OFFSET_NUMBER 1 +#endif /* STM32_ADC_HAS_CONFIG_OFFSET_NUMBER */ +#endif /* defined(ADC_OFFSET_NONE) */ + +#if defined(ADC_RESOLUTION_12B) +#define STM32_ADC_HAS_CONFIGURABLE_RESOLUTION 1 +#endif /* defined(ADC_RESOLUTION_12B) */ + +#if defined(ADC_CALIB_OFFSET_LINEARITY) +#define STM32_ADC_HAS_LINEAR_CALIBRATION 1 +#endif /* defined(ADC_CALIB_OFFSET_LINEARITY) */ + +#if defined(STM32_ADC_HAS_SIMPLE_CALIBRATION) || defined(STM32_ADC_HAS_LINEAR_CALIBRATION) +#define STM32_ADC_HAS_CALIBRATION 1 +#endif /* defined(STM32_ADC_HAS_SIMPLE_CALIBRATION) || defined(STM32_ADC_HAS_LINEAR_CALIBRATION) */ + +#if defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32H7RS) +/** @brief Enable D-Cache-safe ADC DMA stream handling for Cortex-M7 STM32 series. */ +#define STM32_ADC_NEEDS_DMA_CACHE_MAINTENANCE 1 +#endif /* defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32H7RS) */ + +#if defined(BSP_ADC_USING_TRIGGER) && defined(RT_ADC_USING_TRIGGER) +/** @brief Whether the STM32 ADC trigger backend support is compiled in. */ +#define STM32_ADC_USING_TRIGGER 1 +#endif /* defined(BSP_ADC_USING_TRIGGER) && defined(RT_ADC_USING_TRIGGER) */ + +#if defined(STM32_ADC_USING_TRIGGER) && defined(BSP_ADC_USING_TIMER_TRIGGER) && defined(RT_ADC_TRIGGER_USING_TIMER) && defined(BSP_USING_TIM) +/** @brief Whether the STM32 ADC timer trigger selector backend is compiled in. */ +#define STM32_ADC_USING_TIMER_TRIGGER 1 +#endif /* defined(STM32_ADC_USING_TRIGGER) && defined(BSP_ADC_USING_TIMER_TRIGGER) && defined(RT_ADC_TRIGGER_USING_TIMER) && defined(BSP_USING_TIM) */ + +#if defined(STM32_ADC_USING_TRIGGER) && defined(BSP_ADC_USING_ANALOG_COMPARE_TRIGGER) +#if defined(RT_ADC_TRIGGER_USING_COMPARE) +/** @brief Whether the STM32 ADC analog-comparator trigger selector backend is compiled in. */ +#define STM32_ADC_USING_ANALOG_COMPARE_TRIGGER 1 +#endif /* defined(RT_ADC_TRIGGER_USING_COMPARE) */ +#endif /* defined(STM32_ADC_USING_TRIGGER) && defined(BSP_ADC_USING_ANALOG_COMPARE_TRIGGER) */ + +#if defined(__LL_ADC_CALC_VREFANALOG_VOLTAGE) && defined(STM32_ADC_HAS_CONFIGURABLE_RESOLUTION) +#define STM32_ADC_HAS_LL_VREF_CALC 1 +#endif /* defined(__LL_ADC_CALC_VREFANALOG_VOLTAGE) && defined(STM32_ADC_HAS_CONFIGURABLE_RESOLUTION) */ + +#if defined(STM32_ADC_HAS_LL_VREF_CALC) +#if defined(STM32_ADC_VREF_NEEDS_INSTANCE) +/* Calculate VDDA in millivolts with an instance-aware LL helper. */ +#define STM32_ADC_CALC_VREF_MV(_adc, _raw) \ + __LL_ADC_CALC_VREFANALOG_VOLTAGE((_adc)->handle.Instance, (_raw), (_adc)->handle.Init.Resolution) +#else +/* Calculate VDDA in millivolts with the generic LL helper. */ +#define STM32_ADC_CALC_VREF_MV(_adc, _raw) \ + __LL_ADC_CALC_VREFANALOG_VOLTAGE((_raw), (_adc)->handle.Init.Resolution) +#endif /* defined(STM32_ADC_VREF_NEEDS_INSTANCE) */ +#endif /* defined(STM32_ADC_HAS_LL_VREF_CALC) */ + +#if defined(__LL_ADC_CALC_TEMPERATURE) && defined(STM32_ADC_HAS_CONFIGURABLE_RESOLUTION) +#define STM32_ADC_HAS_LL_TEMPERATURE_CALC 1 + +#if defined(STM32_ADC_TEMPERATURE_NEEDS_INSTANCE) +/* Calculate temperature in degrees Celsius with an instance-aware LL helper. */ +#define STM32_ADC_CALC_TEMPERATURE(_adc, _vref_mv, _raw, _resolution) \ + __LL_ADC_CALC_TEMPERATURE((_adc)->handle.Instance, (_vref_mv), (_raw), (_resolution)) +#else +/* Calculate temperature in degrees Celsius with the generic LL helper. */ +#define STM32_ADC_CALC_TEMPERATURE(_adc, _vref_mv, _raw, _resolution) \ + __LL_ADC_CALC_TEMPERATURE((_vref_mv), (_raw), (_resolution)) +#endif /* defined(STM32_ADC_TEMPERATURE_NEEDS_INSTANCE) */ + +#endif /* defined(__LL_ADC_CALC_TEMPERATURE) && defined(STM32_ADC_HAS_CONFIGURABLE_RESOLUTION) */ + +#if defined(TEMPSENSOR_CAL1_ADDR) && defined(TEMPSENSOR_CAL2_ADDR) && defined(TEMPSENSOR_CAL1_TEMP) && \ + defined(TEMPSENSOR_CAL2_TEMP) && defined(TEMPSENSOR_CAL_VREFANALOG) +#define STM32_ADC_HAS_TEMPSENSOR_CALIBRATION_DATA 1 +#endif /* defined(TEMPSENSOR_CAL1_ADDR) && defined(TEMPSENSOR_CAL2_ADDR) && defined(TEMPSENSOR_CAL1_TEMP) && defined(TEMPSENSOR_CAL2_TEMP) && defined(TEMPSENSOR_CAL_VREFANALOG) */ + +#if defined(ADC_OVERSAMPLING_RATIO_2) && defined(ADC_RIGHTBITSHIFT_1) +#if defined(ADC_TRIGGEREDMODE_SINGLE_TRIGGER) && defined(ADC_REGOVERSAMPLING_CONTINUED_MODE) +#define STM32_ADC_HAS_HW_OVERSAMPLING 1 +#endif /* defined(ADC_TRIGGEREDMODE_SINGLE_TRIGGER) && defined(ADC_REGOVERSAMPLING_CONTINUED_MODE) */ +#endif /* defined(ADC_OVERSAMPLING_RATIO_2) && defined(ADC_RIGHTBITSHIFT_1) */ + +/** @brief Marker for an unavailable STM32 HAL ADC channel. */ +#ifndef STM32_ADC_INVALID_CHANNEL +#define STM32_ADC_INVALID_CHANNEL 0xFFFFFFFFUL +#endif /* STM32_ADC_INVALID_CHANNEL */ + +/** @brief Invalid RT-Thread logical ADC channel marker. */ +#ifndef STM32_ADC_INVALID_LOGICAL_CHANNEL +#define STM32_ADC_INVALID_LOGICAL_CHANNEL (-1) +#endif /* STM32_ADC_INVALID_LOGICAL_CHANNEL */ + +/** @brief STM32 ADC instance mask bit for ADC1. */ +#ifndef STM32_ADC_INSTANCE_MASK_ADC1 +#define STM32_ADC_INSTANCE_MASK_ADC1 (1UL << 0) +#endif /* STM32_ADC_INSTANCE_MASK_ADC1 */ + +/** @brief STM32 ADC instance mask bit for ADC2. */ +#ifndef STM32_ADC_INSTANCE_MASK_ADC2 +#define STM32_ADC_INSTANCE_MASK_ADC2 (1UL << 1) +#endif /* STM32_ADC_INSTANCE_MASK_ADC2 */ + +/** @brief STM32 ADC instance mask bit for ADC3. */ +#ifndef STM32_ADC_INSTANCE_MASK_ADC3 +#define STM32_ADC_INSTANCE_MASK_ADC3 (1UL << 2) +#endif /* STM32_ADC_INSTANCE_MASK_ADC3 */ + +/** @brief STM32 ADC instance mask bit for ADC4. */ +#ifndef STM32_ADC_INSTANCE_MASK_ADC4 +#define STM32_ADC_INSTANCE_MASK_ADC4 (1UL << 3) +#endif /* STM32_ADC_INSTANCE_MASK_ADC4 */ + +/** @brief STM32 ADC instance mask bit for ADC5. */ +#ifndef STM32_ADC_INSTANCE_MASK_ADC5 +#define STM32_ADC_INSTANCE_MASK_ADC5 (1UL << 4) +#endif /* STM32_ADC_INSTANCE_MASK_ADC5 */ + +/** @brief Mask value that allows every known STM32 ADC instance. */ +#ifndef STM32_ADC_INSTANCE_MASK_ALL +#define STM32_ADC_INSTANCE_MASK_ALL 0xffffffffUL +#endif /* STM32_ADC_INSTANCE_MASK_ALL */ + +/** @brief Convert a STM32 HAL ADC channel literal into a RT-Thread logical channel number. */ +#ifndef STM32_ADC_HAL_CHANNEL_TO_LOGICAL +#if defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_HAL_CHANNEL_TO_LOGICAL(_channel) __HAL_ADC_CHANNEL_TO_DECIMAL_NB(_channel) +#elif defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_HAL_CHANNEL_TO_LOGICAL(_channel) __LL_ADC_CHANNEL_TO_DECIMAL_NB(_channel) +#else +#define STM32_ADC_HAL_CHANNEL_TO_LOGICAL(_channel) STM32_ADC_INVALID_LOGICAL_CHANNEL +#endif /* defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) */ +#endif /* STM32_ADC_HAL_CHANNEL_TO_LOGICAL */ + +/** @brief Maximum HAL ADC channel-table entries exposed by the active STM32 HAL. */ +#ifndef STM32_ADC_MAX_CHANNELS +#if defined(ADC_CHANNEL_31) +#define STM32_ADC_MAX_CHANNELS 32 +#elif defined(ADC_CHANNEL_30) +#define STM32_ADC_MAX_CHANNELS 31 +#elif defined(ADC_CHANNEL_29) +#define STM32_ADC_MAX_CHANNELS 30 +#elif defined(ADC_CHANNEL_28) +#define STM32_ADC_MAX_CHANNELS 29 +#elif defined(ADC_CHANNEL_27) +#define STM32_ADC_MAX_CHANNELS 28 +#elif defined(ADC_CHANNEL_26) +#define STM32_ADC_MAX_CHANNELS 27 +#elif defined(ADC_CHANNEL_25) +#define STM32_ADC_MAX_CHANNELS 26 +#elif defined(ADC_CHANNEL_24) +#define STM32_ADC_MAX_CHANNELS 25 +#elif defined(ADC_CHANNEL_23) +#define STM32_ADC_MAX_CHANNELS 24 +#elif defined(ADC_CHANNEL_22) +#define STM32_ADC_MAX_CHANNELS 23 +#elif defined(ADC_CHANNEL_21) +#define STM32_ADC_MAX_CHANNELS 22 +#elif defined(ADC_CHANNEL_20) +#define STM32_ADC_MAX_CHANNELS 21 +#elif defined(ADC_CHANNEL_19) +#define STM32_ADC_MAX_CHANNELS 20 +#elif defined(ADC_CHANNEL_18) +#define STM32_ADC_MAX_CHANNELS 19 +#elif defined(ADC_CHANNEL_17) +#define STM32_ADC_MAX_CHANNELS 18 +#elif defined(ADC_CHANNEL_16) +#define STM32_ADC_MAX_CHANNELS 17 +#else +#define STM32_ADC_MAX_CHANNELS 16 +#endif /* defined(ADC_CHANNEL_31) */ +#endif /* STM32_ADC_MAX_CHANNELS */ + +/* Optional ADC channel encodings supplied by the active STM32 HAL. */ +#ifndef STM32_ADC_CHANNEL_16 +#ifdef ADC_CHANNEL_16 +#define STM32_ADC_CHANNEL_16 ADC_CHANNEL_16 +#else +#define STM32_ADC_CHANNEL_16 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_16 */ +#endif /* STM32_ADC_CHANNEL_16 */ + +#ifndef STM32_ADC_CHANNEL_17 +#ifdef ADC_CHANNEL_17 +#define STM32_ADC_CHANNEL_17 ADC_CHANNEL_17 +#else +#define STM32_ADC_CHANNEL_17 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_17 */ +#endif /* STM32_ADC_CHANNEL_17 */ + +#ifndef STM32_ADC_CHANNEL_18 +#ifdef ADC_CHANNEL_18 +#define STM32_ADC_CHANNEL_18 ADC_CHANNEL_18 +#else +#define STM32_ADC_CHANNEL_18 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_18 */ +#endif /* STM32_ADC_CHANNEL_18 */ + +#ifndef STM32_ADC_CHANNEL_19 +#ifdef ADC_CHANNEL_19 +#define STM32_ADC_CHANNEL_19 ADC_CHANNEL_19 +#else +#define STM32_ADC_CHANNEL_19 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_19 */ +#endif /* STM32_ADC_CHANNEL_19 */ + +#ifndef STM32_ADC_CHANNEL_20 +#ifdef ADC_CHANNEL_20 +#define STM32_ADC_CHANNEL_20 ADC_CHANNEL_20 +#else +#define STM32_ADC_CHANNEL_20 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_20 */ +#endif /* STM32_ADC_CHANNEL_20 */ + +#ifndef STM32_ADC_CHANNEL_21 +#ifdef ADC_CHANNEL_21 +#define STM32_ADC_CHANNEL_21 ADC_CHANNEL_21 +#else +#define STM32_ADC_CHANNEL_21 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_21 */ +#endif /* STM32_ADC_CHANNEL_21 */ + +#ifndef STM32_ADC_CHANNEL_22 +#ifdef ADC_CHANNEL_22 +#define STM32_ADC_CHANNEL_22 ADC_CHANNEL_22 +#else +#define STM32_ADC_CHANNEL_22 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_22 */ +#endif /* STM32_ADC_CHANNEL_22 */ + +#ifndef STM32_ADC_CHANNEL_23 +#ifdef ADC_CHANNEL_23 +#define STM32_ADC_CHANNEL_23 ADC_CHANNEL_23 +#else +#define STM32_ADC_CHANNEL_23 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_23 */ +#endif /* STM32_ADC_CHANNEL_23 */ + +#ifndef STM32_ADC_CHANNEL_24 +#ifdef ADC_CHANNEL_24 +#define STM32_ADC_CHANNEL_24 ADC_CHANNEL_24 +#else +#define STM32_ADC_CHANNEL_24 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_24 */ +#endif /* STM32_ADC_CHANNEL_24 */ + +#ifndef STM32_ADC_CHANNEL_25 +#ifdef ADC_CHANNEL_25 +#define STM32_ADC_CHANNEL_25 ADC_CHANNEL_25 +#else +#define STM32_ADC_CHANNEL_25 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_25 */ +#endif /* STM32_ADC_CHANNEL_25 */ + +#ifndef STM32_ADC_CHANNEL_26 +#ifdef ADC_CHANNEL_26 +#define STM32_ADC_CHANNEL_26 ADC_CHANNEL_26 +#else +#define STM32_ADC_CHANNEL_26 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_26 */ +#endif /* STM32_ADC_CHANNEL_26 */ + +#ifndef STM32_ADC_CHANNEL_27 +#ifdef ADC_CHANNEL_27 +#define STM32_ADC_CHANNEL_27 ADC_CHANNEL_27 +#else +#define STM32_ADC_CHANNEL_27 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_27 */ +#endif /* STM32_ADC_CHANNEL_27 */ + +#ifndef STM32_ADC_CHANNEL_28 +#ifdef ADC_CHANNEL_28 +#define STM32_ADC_CHANNEL_28 ADC_CHANNEL_28 +#else +#define STM32_ADC_CHANNEL_28 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_28 */ +#endif /* STM32_ADC_CHANNEL_28 */ + +#ifndef STM32_ADC_CHANNEL_29 +#ifdef ADC_CHANNEL_29 +#define STM32_ADC_CHANNEL_29 ADC_CHANNEL_29 +#else +#define STM32_ADC_CHANNEL_29 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_29 */ +#endif /* STM32_ADC_CHANNEL_29 */ + +#ifndef STM32_ADC_CHANNEL_30 +#ifdef ADC_CHANNEL_30 +#define STM32_ADC_CHANNEL_30 ADC_CHANNEL_30 +#else +#define STM32_ADC_CHANNEL_30 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_30 */ +#endif /* STM32_ADC_CHANNEL_30 */ + +#ifndef STM32_ADC_CHANNEL_31 +#ifdef ADC_CHANNEL_31 +#define STM32_ADC_CHANNEL_31 ADC_CHANNEL_31 +#else +#define STM32_ADC_CHANNEL_31 STM32_ADC_INVALID_CHANNEL +#endif /* ADC_CHANNEL_31 */ +#endif /* STM32_ADC_CHANNEL_31 */ + +/** + * @brief Default ADC instance mask for common STM32 internal ADC sources. + * + * Series configuration files should override this macro only when internal + * sources are not routed to ADC1 by default. + */ +#ifndef STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK +#define STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK STM32_ADC_INSTANCE_MASK_ADC1 +#endif /* STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK */ + +/* Resolve temperature sensor HAL channel and supported ADC instances. */ +#ifndef STM32_ADC_TEMP_HAL_CHANNEL +#if defined(ADC_CHANNEL_TEMPSENSOR_ADC1) +#define STM32_ADC_TEMP_HAL_CHANNEL ADC_CHANNEL_TEMPSENSOR_ADC1 +#ifndef STM32_ADC_TEMP_CHANNEL_AVAILABLE +#define STM32_ADC_TEMP_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_TEMP_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_TEMP_INSTANCE_MASK +#define STM32_ADC_TEMP_INSTANCE_MASK STM32_ADC_INSTANCE_MASK_ADC1 +#endif /* STM32_ADC_TEMP_INSTANCE_MASK */ +#elif defined(ADC_CHANNEL_TEMPSENSOR_ADC3) +#define STM32_ADC_TEMP_HAL_CHANNEL ADC_CHANNEL_TEMPSENSOR_ADC3 +#ifndef STM32_ADC_TEMP_CHANNEL_AVAILABLE +#define STM32_ADC_TEMP_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_TEMP_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_TEMP_INSTANCE_MASK +#define STM32_ADC_TEMP_INSTANCE_MASK STM32_ADC_INSTANCE_MASK_ADC3 +#endif /* STM32_ADC_TEMP_INSTANCE_MASK */ +#elif defined(ADC_CHANNEL_TEMPSENSOR) +#define STM32_ADC_TEMP_HAL_CHANNEL ADC_CHANNEL_TEMPSENSOR +#ifndef STM32_ADC_TEMP_CHANNEL_AVAILABLE +#define STM32_ADC_TEMP_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_TEMP_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_TEMP_INSTANCE_MASK +#define STM32_ADC_TEMP_INSTANCE_MASK STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK +#endif /* STM32_ADC_TEMP_INSTANCE_MASK */ +#else +#define STM32_ADC_TEMP_HAL_CHANNEL STM32_ADC_INVALID_CHANNEL +#ifndef STM32_ADC_TEMP_CHANNEL_AVAILABLE +#define STM32_ADC_TEMP_CHANNEL_AVAILABLE 0 +#endif /* STM32_ADC_TEMP_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_TEMP_INSTANCE_MASK +#define STM32_ADC_TEMP_INSTANCE_MASK 0UL +#endif /* STM32_ADC_TEMP_INSTANCE_MASK */ +#endif /* defined(ADC_CHANNEL_TEMPSENSOR_ADC1) */ +#endif /* STM32_ADC_TEMP_HAL_CHANNEL */ + +/** @brief Whether the primary temperature-sensor HAL channel can be used. */ +#ifndef STM32_ADC_TEMP_CHANNEL_AVAILABLE +#define STM32_ADC_TEMP_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_TEMP_CHANNEL_AVAILABLE */ + +#ifndef STM32_ADC_TEMP_INSTANCE_MASK +#if STM32_ADC_TEMP_CHANNEL_AVAILABLE +/** @brief ADC instances that can sample the temperature sensor. */ +#define STM32_ADC_TEMP_INSTANCE_MASK STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK +#else +/** @brief ADC instances that can sample the temperature sensor. */ +#define STM32_ADC_TEMP_INSTANCE_MASK 0UL +#endif /* STM32_ADC_TEMP_CHANNEL_AVAILABLE */ +#endif /* STM32_ADC_TEMP_INSTANCE_MASK */ + +#ifndef STM32_ADC_TEMP_CHANNEL +#if !STM32_ADC_TEMP_CHANNEL_AVAILABLE +#define STM32_ADC_TEMP_CHANNEL STM32_ADC_INVALID_LOGICAL_CHANNEL +#elif defined(STM32_ADC_TEMP_LOGICAL_OVERRIDE) +#define STM32_ADC_TEMP_CHANNEL STM32_ADC_TEMP_LOGICAL_OVERRIDE +#elif defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) || defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_TEMP_CHANNEL STM32_ADC_HAL_CHANNEL_TO_LOGICAL(STM32_ADC_TEMP_HAL_CHANNEL) +#else +#error "STM32 ADC V2: define STM32_ADC_TEMP_LOGICAL_OVERRIDE for this legacy HAL series." +#endif /* !STM32_ADC_TEMP_CHANNEL_AVAILABLE */ +#endif /* STM32_ADC_TEMP_CHANNEL */ + +/* Resolve VBAT HAL channel and supported ADC instances. */ +#ifndef STM32_ADC_VBAT_HAL_CHANNEL +#if defined(ADC_CHANNEL_VBAT_ADC1) +#define STM32_ADC_VBAT_HAL_CHANNEL ADC_CHANNEL_VBAT_ADC1 +#ifndef STM32_ADC_VBAT_CHANNEL_AVAILABLE +#define STM32_ADC_VBAT_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_VBAT_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_VBAT_INSTANCE_MASK +#define STM32_ADC_VBAT_INSTANCE_MASK STM32_ADC_INSTANCE_MASK_ADC1 +#endif /* STM32_ADC_VBAT_INSTANCE_MASK */ +#elif defined(ADC_CHANNEL_VBAT_ADC2) +#define STM32_ADC_VBAT_HAL_CHANNEL ADC_CHANNEL_VBAT_ADC2 +#ifndef STM32_ADC_VBAT_CHANNEL_AVAILABLE +#define STM32_ADC_VBAT_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_VBAT_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_VBAT_INSTANCE_MASK +#define STM32_ADC_VBAT_INSTANCE_MASK STM32_ADC_INSTANCE_MASK_ADC2 +#endif /* STM32_ADC_VBAT_INSTANCE_MASK */ +#elif defined(ADC_CHANNEL_VBAT_ADC3) +#define STM32_ADC_VBAT_HAL_CHANNEL ADC_CHANNEL_VBAT_ADC3 +#ifndef STM32_ADC_VBAT_CHANNEL_AVAILABLE +#define STM32_ADC_VBAT_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_VBAT_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_VBAT_INSTANCE_MASK +#define STM32_ADC_VBAT_INSTANCE_MASK STM32_ADC_INSTANCE_MASK_ADC3 +#endif /* STM32_ADC_VBAT_INSTANCE_MASK */ +#elif defined(ADC_CHANNEL_VBAT) +#define STM32_ADC_VBAT_HAL_CHANNEL ADC_CHANNEL_VBAT +#ifndef STM32_ADC_VBAT_CHANNEL_AVAILABLE +#define STM32_ADC_VBAT_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_VBAT_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_VBAT_INSTANCE_MASK +#define STM32_ADC_VBAT_INSTANCE_MASK STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK +#endif /* STM32_ADC_VBAT_INSTANCE_MASK */ +#else +#define STM32_ADC_VBAT_HAL_CHANNEL STM32_ADC_INVALID_CHANNEL +#ifndef STM32_ADC_VBAT_CHANNEL_AVAILABLE +#define STM32_ADC_VBAT_CHANNEL_AVAILABLE 0 +#endif /* STM32_ADC_VBAT_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_VBAT_INSTANCE_MASK +#define STM32_ADC_VBAT_INSTANCE_MASK 0UL +#endif /* STM32_ADC_VBAT_INSTANCE_MASK */ +#endif /* defined(ADC_CHANNEL_VBAT_ADC1) */ +#endif /* STM32_ADC_VBAT_HAL_CHANNEL */ + +/** @brief Whether the primary VBAT HAL channel can be used. */ +#ifndef STM32_ADC_VBAT_CHANNEL_AVAILABLE +#define STM32_ADC_VBAT_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_VBAT_CHANNEL_AVAILABLE */ + +#ifndef STM32_ADC_VBAT_INSTANCE_MASK +#if STM32_ADC_VBAT_CHANNEL_AVAILABLE +/** @brief ADC instances that can sample VBAT. */ +#define STM32_ADC_VBAT_INSTANCE_MASK STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK +#else +/** @brief ADC instances that can sample VBAT. */ +#define STM32_ADC_VBAT_INSTANCE_MASK 0UL +#endif /* STM32_ADC_VBAT_CHANNEL_AVAILABLE */ +#endif /* STM32_ADC_VBAT_INSTANCE_MASK */ + +#ifndef STM32_ADC_VBAT_CHANNEL +#if !STM32_ADC_VBAT_CHANNEL_AVAILABLE +#define STM32_ADC_VBAT_CHANNEL STM32_ADC_INVALID_LOGICAL_CHANNEL +#elif defined(STM32_ADC_VBAT_LOGICAL_OVERRIDE) +#define STM32_ADC_VBAT_CHANNEL STM32_ADC_VBAT_LOGICAL_OVERRIDE +#elif defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) || defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_VBAT_CHANNEL STM32_ADC_HAL_CHANNEL_TO_LOGICAL(STM32_ADC_VBAT_HAL_CHANNEL) +#else +#error "STM32 ADC V2: define STM32_ADC_VBAT_LOGICAL_OVERRIDE for this legacy HAL series." +#endif /* !STM32_ADC_VBAT_CHANNEL_AVAILABLE */ +#endif /* STM32_ADC_VBAT_CHANNEL */ + +/* Resolve VREFINT HAL channel and supported ADC instances. */ +#ifndef STM32_ADC_VREF_HAL_CHANNEL +#if defined(ADC_CHANNEL_VREFINT_ADC1) +#define STM32_ADC_VREF_HAL_CHANNEL ADC_CHANNEL_VREFINT_ADC1 +#ifndef STM32_ADC_VREF_CHANNEL_AVAILABLE +#define STM32_ADC_VREF_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_VREF_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_VREF_INSTANCE_MASK +#define STM32_ADC_VREF_INSTANCE_MASK STM32_ADC_INSTANCE_MASK_ADC1 +#endif /* STM32_ADC_VREF_INSTANCE_MASK */ +#elif defined(ADC_CHANNEL_VREFINT_ADC2) +#define STM32_ADC_VREF_HAL_CHANNEL ADC_CHANNEL_VREFINT_ADC2 +#ifndef STM32_ADC_VREF_CHANNEL_AVAILABLE +#define STM32_ADC_VREF_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_VREF_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_VREF_INSTANCE_MASK +#define STM32_ADC_VREF_INSTANCE_MASK STM32_ADC_INSTANCE_MASK_ADC2 +#endif /* STM32_ADC_VREF_INSTANCE_MASK */ +#elif defined(ADC_CHANNEL_VREFINT_ADC3) +#define STM32_ADC_VREF_HAL_CHANNEL ADC_CHANNEL_VREFINT_ADC3 +#ifndef STM32_ADC_VREF_CHANNEL_AVAILABLE +#define STM32_ADC_VREF_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_VREF_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_VREF_INSTANCE_MASK +#define STM32_ADC_VREF_INSTANCE_MASK STM32_ADC_INSTANCE_MASK_ADC3 +#endif /* STM32_ADC_VREF_INSTANCE_MASK */ +#elif defined(ADC_CHANNEL_VREFINT) +#define STM32_ADC_VREF_HAL_CHANNEL ADC_CHANNEL_VREFINT +#ifndef STM32_ADC_VREF_CHANNEL_AVAILABLE +#define STM32_ADC_VREF_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_VREF_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_VREF_INSTANCE_MASK +#define STM32_ADC_VREF_INSTANCE_MASK STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK +#endif /* STM32_ADC_VREF_INSTANCE_MASK */ +#else +#define STM32_ADC_VREF_HAL_CHANNEL STM32_ADC_INVALID_CHANNEL +#ifndef STM32_ADC_VREF_CHANNEL_AVAILABLE +#define STM32_ADC_VREF_CHANNEL_AVAILABLE 0 +#endif /* STM32_ADC_VREF_CHANNEL_AVAILABLE */ +#ifndef STM32_ADC_VREF_INSTANCE_MASK +#define STM32_ADC_VREF_INSTANCE_MASK 0UL +#endif /* STM32_ADC_VREF_INSTANCE_MASK */ +#endif /* defined(ADC_CHANNEL_VREFINT_ADC1) */ +#endif /* STM32_ADC_VREF_HAL_CHANNEL */ + +/** @brief Whether the primary VREFINT HAL channel can be used. */ +#ifndef STM32_ADC_VREF_CHANNEL_AVAILABLE +#define STM32_ADC_VREF_CHANNEL_AVAILABLE 1 +#endif /* STM32_ADC_VREF_CHANNEL_AVAILABLE */ + +#ifndef STM32_ADC_VREF_INSTANCE_MASK +#if STM32_ADC_VREF_CHANNEL_AVAILABLE +/** @brief ADC instances that can sample VREFINT. */ +#define STM32_ADC_VREF_INSTANCE_MASK STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK +#else +/** @brief ADC instances that can sample VREFINT. */ +#define STM32_ADC_VREF_INSTANCE_MASK 0UL +#endif /* STM32_ADC_VREF_CHANNEL_AVAILABLE */ +#endif /* STM32_ADC_VREF_INSTANCE_MASK */ + +#ifndef STM32_ADC_VREF_CHANNEL +#if !STM32_ADC_VREF_CHANNEL_AVAILABLE +#define STM32_ADC_VREF_CHANNEL STM32_ADC_INVALID_LOGICAL_CHANNEL +#elif defined(STM32_ADC_VREF_LOGICAL_OVERRIDE) +#define STM32_ADC_VREF_CHANNEL STM32_ADC_VREF_LOGICAL_OVERRIDE +#elif defined(__HAL_ADC_CHANNEL_TO_DECIMAL_NB) || defined(__LL_ADC_CHANNEL_TO_DECIMAL_NB) +#define STM32_ADC_VREF_CHANNEL STM32_ADC_HAL_CHANNEL_TO_LOGICAL(STM32_ADC_VREF_HAL_CHANNEL) +#else +#error "STM32 ADC V2: define STM32_ADC_VREF_LOGICAL_OVERRIDE for this legacy HAL series." +#endif /* !STM32_ADC_VREF_CHANNEL_AVAILABLE */ +#endif /* STM32_ADC_VREF_CHANNEL */ + +#ifndef STM32_ADC_TEMP_ALT_HAL_CHANNEL +#define STM32_ADC_TEMP_ALT_HAL_CHANNEL STM32_ADC_INVALID_CHANNEL +#endif /* STM32_ADC_TEMP_ALT_HAL_CHANNEL */ + +#ifndef STM32_ADC_TEMP_ALT_INSTANCE_MASK +#define STM32_ADC_TEMP_ALT_INSTANCE_MASK 0UL +#endif /* STM32_ADC_TEMP_ALT_INSTANCE_MASK */ + +#ifndef STM32_ADC_VBAT_ALT_HAL_CHANNEL +#define STM32_ADC_VBAT_ALT_HAL_CHANNEL STM32_ADC_INVALID_CHANNEL +#endif /* STM32_ADC_VBAT_ALT_HAL_CHANNEL */ + +#ifndef STM32_ADC_VBAT_ALT_INSTANCE_MASK +#define STM32_ADC_VBAT_ALT_INSTANCE_MASK 0UL +#endif /* STM32_ADC_VBAT_ALT_INSTANCE_MASK */ + +#ifndef STM32_ADC_VREF_ALT_HAL_CHANNEL +#define STM32_ADC_VREF_ALT_HAL_CHANNEL STM32_ADC_INVALID_CHANNEL +#endif /* STM32_ADC_VREF_ALT_HAL_CHANNEL */ + +#ifndef STM32_ADC_VREF_ALT_INSTANCE_MASK +#define STM32_ADC_VREF_ALT_INSTANCE_MASK 0UL +#endif /* STM32_ADC_VREF_ALT_INSTANCE_MASK */ + +#ifndef STM32_ADC_USING_STREAM +#define STM32_ADC_USING_STREAM 0 +#endif /* STM32_ADC_USING_STREAM */ + +#ifndef STM32_ADC_USING_DMA_STREAM +#define STM32_ADC_USING_DMA_STREAM STM32_ADC_USING_STREAM +#endif /* STM32_ADC_USING_DMA_STREAM */ + + +#if defined(STM32_ADC_USING_TRIGGER) +/** + * @brief Prepared STM32 ADC external trigger fields. + */ +struct stm32_adc_trigger_fields +{ + rt_uint32_t selector; /**< HAL ADC external trigger selector. */ + rt_uint32_t edge; /**< HAL ADC external trigger edge selector. */ +}; +#endif /* defined(STM32_ADC_USING_TRIGGER) */ + +/** + * @brief STM32 ADC device object. + * + * @note The HAL ADC handle must remain the first member. STM32 HAL + * callbacks receive an ADC_HandleTypeDef pointer, and this driver + * casts it back to struct stm32_adc while handling callbacks. + */ +struct stm32_adc +{ + ADC_HandleTypeDef handle; /**< HAL ADC handle; keep first for HAL callback owner cast. */ + const char *name; /**< Device name. */ + struct stm32_adc_private_cfg config; /**< Default STM32 backend private configuration. */ + struct rt_adc_device device; /**< RT-Thread ADC device object. */ +#if STM32_ADC_USING_DMA_STREAM + const struct stm32_dma_config *dma_rx; /**< ADC stream DMA RX configuration. */ + DMA_HandleTypeDef dma_handle; /**< HAL DMA handle used by stream mode. */ +#if defined(STM32_ADC_NEEDS_DMA_CACHE_MAINTENANCE) + rt_uint32_t *cache_dma_buffer; /**< Cache-aligned stream DMA buffer when caller buffer is not safe. */ +#endif /* defined(STM32_ADC_NEEDS_DMA_CACHE_MAINTENANCE) */ +#endif /* STM32_ADC_USING_DMA_STREAM */ +#if defined(STM32_ADC_USING_TRIGGER) + struct stm32_adc_trigger_fields prepared_trigger; /**< Cached trigger selector fields for the next stream config. */ + rt_bool_t prepared_trigger_valid; /**< Whether prepared_trigger contains a valid cached selector. */ +#endif /* defined(STM32_ADC_USING_TRIGGER) */ +}; + +/* + * HAL callbacks receive ADC_HandleTypeDef *. The driver casts it back to + * struct stm32_adc, so the HAL handle must remain the first member. + */ +RT_STATIC_ASSERT(stm32_adc_handle_must_be_first, offsetof(struct stm32_adc, handle) == 0U); + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief Check whether an ADC peripheral instance matches an instance mask. + * @param instance ADC peripheral instance. + * @param mask STM32_ADC_INSTANCE_MASK_x bit mask. + * @return RT_TRUE if the instance is included, otherwise RT_FALSE. + */ +rt_bool_t stm32_adc_instance_match(ADC_TypeDef *instance, rt_uint32_t mask); + +/** + * @brief Get the HAL ADC channel identifier. + * @param channel RT-Thread ADC channel identifier. + * @param hal_channel Pointer to the output HAL ADC channel identifier. + * @return Operation status. + */ +rt_err_t stm32_adc_get_channel(rt_uint8_t channel, uint32_t *hal_channel); + +/** + * @brief Get the logical channel used to sample STM32 internal VREFINT. + * @param adc Pointer to the STM32 ADC device object. + * @param channel Pointer to the output logical VREFINT channel. + * @return Operation status. + */ +rt_err_t stm32_adc_get_vref_logical_channel(struct stm32_adc *adc, rt_uint8_t *channel); + +/** + * @brief Get the logical channel used to sample STM32 internal temperature sensor. + * @param adc Pointer to the STM32 ADC device object. + * @param channel Pointer to the output logical temperature-sensor channel. + * @return Operation status. + */ +rt_err_t stm32_adc_get_tempsensor_logical_channel(struct stm32_adc *adc, rt_uint8_t *channel); + +/** + * @brief Get the logical channel used to sample STM32 internal VBAT divider. + * @param adc Pointer to the STM32 ADC device object. + * @param channel Pointer to the output logical VBAT channel. + * @return Operation status. + */ +rt_err_t stm32_adc_get_vbat_logical_channel(struct stm32_adc *adc, rt_uint8_t *channel); + +/** + * @brief Get one HAL sampling-time value from STM32 private configuration. + * @param cfg Pointer to the STM32 backend private configuration. + * @param sampling_time Pointer to the output HAL sampling-time value. + * @return Operation status. + */ +rt_err_t stm32_adc_get_sampling_time(const struct stm32_adc_private_cfg *cfg, uint32_t *sampling_time); + +/** + * @brief Get the current ADC resolution in bits. + * @param adc Pointer to the STM32 ADC device object. + * @return Resolution in bits, or 12 when it cannot be determined. + */ +rt_uint8_t stm32_adc_get_resolution_bits(const struct stm32_adc *adc); + +/** + * @brief Calculate STM32 internal temperature sensor value in degrees Celsius. + * @param device ADC device handle. + * @param raw_value Raw ADC sample value from the temperature sensor channel. + * @param vref_mv Current analog reference voltage in millivolts. + * @param resolution_bits ADC conversion resolution used for @p raw_value. + * @param temperature_c Pointer to the output temperature in degrees Celsius. + * @return Operation status. + */ +rt_err_t stm32_adc_calc_temperature(rt_adc_device_t device, rt_uint32_t raw_value, + rt_uint32_t vref_mv, rt_uint8_t resolution_bits, + rt_int32_t *temperature_c); + +/** + * @brief Calculate VDDA from a raw VREFINT sample. + * @param device Pointer to the ADC device object. + * @param vref_mv Pointer to the raw VREFINT sample on input and VDDA millivolts on output. + * @return Operation status. + */ +rt_err_t stm32_adc_calc_vref_mv(struct rt_adc_device *device, rt_uint32_t *vref_mv); + + +#if defined(STM32_ADC_USING_TRIGGER) +/** + * @brief Resolve STM32 ADC trigger selector fields. + * @param adc Pointer to the STM32 ADC device object. + * @param cfg Pointer to the ADC trigger configuration, or RT_NULL for software start. + * @param fields Pointer to the output STM32 trigger fields. + * @return Operation status. + */ +rt_err_t stm32_adc_trigger_fields_get(struct stm32_adc *adc, const struct rt_adc_trigger_cfg *cfg, + struct stm32_adc_trigger_fields *fields); + +/** + * @brief Preconfigure STM32 ADC trigger selector state for the next stream configuration. + * @param device Pointer to the ADC framework device object. + * @param cfg Pointer to the ADC trigger configuration, or RT_NULL for software start. + * @return Operation status. + */ +rt_err_t stm32_adc_trigger_prepare(struct rt_adc_device *device, const struct rt_adc_trigger_cfg *cfg); +#endif /* defined(STM32_ADC_USING_TRIGGER) */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) || defined(BSP_USING_ADC4) */ + +#endif /* defined(RT_USING_ADC_V2) */ + +#endif /* __DRV_ADC_V2_PRIVATE_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_trigger.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_trigger.c new file mode 100644 index 00000000000..59a4d4c8c91 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_trigger.c @@ -0,0 +1,1175 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-05-24 wdfk-prog add STM32 ADC V2 timer trigger backend + */ + +/** + * @file drv_adc_v2_trigger.c + * @brief STM32 ADC V2 trigger selector backend. + */ +#include + +#if defined(RT_USING_ADC_V2) + +#include "drv_config.h" +#include "drv_adc_v2_private.h" + +#if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) || defined(BSP_USING_ADC4) + +#define DRV_DEBUG +#define LOG_TAG "drv.adc" +#include + +#if defined(STM32_ADC_USING_TRIGGER) +/** @brief Invalid trigger selector array slot. */ +#define STM32_ADC_TRIGGER_SELECTOR_NONE { 0U, RT_FALSE } + +/** @brief Valid trigger selector array slot initializer. */ +#define STM32_ADC_TRIGGER_SELECTOR(_selector) { (_selector), RT_TRUE } + +/** @brief Maximum compare channel index encoded by the STM32 ADC trigger tables. */ +#define STM32_ADC_TIMER_COMPARE_CHANNEL_MAX 4U + +/** + * @brief STM32 ADC trigger selector slot. + */ +struct stm32_adc_trigger_selector +{ + rt_uint32_t selector; /**< HAL ADC external trigger selector. */ + rt_bool_t valid; /**< Whether selector is valid for this slot. */ +}; + +/** + * @brief Encode one ADC trigger edge as STM32 HAL external trigger edge. + * @param edge ADC framework trigger edge. + * @param hal_edge Pointer to the HAL edge selector output. + * @return Operation status. + */ +static rt_err_t stm32_adc_trigger_edge_encode(enum rt_adc_trigger_edge edge, rt_uint32_t *hal_edge) +{ + if (hal_edge == RT_NULL) + { + return -RT_EINVAL; + } + +#if defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) + switch (edge) + { + case RT_ADC_TRIGGER_EDGE_NONE: +#if defined(ADC_EXTERNALTRIGCONVEDGE_NONE) + *hal_edge = ADC_EXTERNALTRIGCONVEDGE_NONE; + return RT_EOK; +#else + return -RT_ENOSYS; +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_NONE) */ + + case RT_ADC_TRIGGER_EDGE_RISING: +#if defined(ADC_EXTERNALTRIGCONVEDGE_RISING) + *hal_edge = ADC_EXTERNALTRIGCONVEDGE_RISING; + return RT_EOK; +#else + return -RT_ENOSYS; +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_RISING) */ + + case RT_ADC_TRIGGER_EDGE_FALLING: +#if defined(ADC_EXTERNALTRIGCONVEDGE_FALLING) + *hal_edge = ADC_EXTERNALTRIGCONVEDGE_FALLING; + return RT_EOK; +#else + return -RT_ENOSYS; +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_FALLING) */ + + case RT_ADC_TRIGGER_EDGE_BOTH: +#if defined(ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING) + *hal_edge = ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING; + return RT_EOK; +#else + return -RT_ENOSYS; +#endif /* defined(ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING) */ + + default: + return -RT_EINVAL; + } +#else + if ((edge != RT_ADC_TRIGGER_EDGE_NONE) && (edge != RT_ADC_TRIGGER_EDGE_RISING)) + { + return -RT_ENOSYS; + } + + *hal_edge = 0U; + return RT_EOK; +#endif /* defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) */ +} + +#if defined(STM32_ADC_USING_TIMER_TRIGGER) +/** + * @brief STM32 timer to ADC trigger selector mapping entry. + */ +struct stm32_adc_timer_trigger_map +{ + TIM_TypeDef *instance; /**< TIM hardware instance. */ + rt_uint32_t adc_instance_mask; /**< ADC instances allowed to use this trigger. */ + struct stm32_adc_trigger_selector update; /**< TIM update/TRGO trigger selector. */ + + /** TIM compare trigger selectors indexed by 1-based channel number. */ + struct stm32_adc_trigger_selector compare[STM32_ADC_TIMER_COMPARE_CHANNEL_MAX + 1U]; +}; + +/** + * @brief ADC timer trigger selector table. + * + * @note Compare selectors are intentionally encoded with array indexes so + * channel 1 maps to compare[1], channel 2 maps to compare[2], etc. + */ +static const struct stm32_adc_timer_trigger_map stm32_adc_timer_trigger_table[] = { +#if defined(TIM1) + { + TIM1, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T1_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T1_TRGO), +#elif defined(ADC_EXTERNALTRIG_T1_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T1_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T1_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T1_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T1_CC1), +#elif defined(ADC_EXTERNALTRIG_T1_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T1_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T1_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T1_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T1_CC2), +#elif defined(ADC_EXTERNALTRIG_T1_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T1_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T1_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T1_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T1_CC3), +#elif defined(ADC_EXTERNALTRIG_T1_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T1_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T1_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T1_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T1_CC4), +#elif defined(ADC_EXTERNALTRIG_T1_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T1_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T1_CC4) */ + }, + }, +#endif /* defined(TIM1) */ +#if defined(TIM2) + { + TIM2, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T2_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T2_TRGO), +#elif defined(ADC_EXTERNALTRIG_T2_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T2_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T2_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T2_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T2_CC1), +#elif defined(ADC_EXTERNALTRIG_T2_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T2_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T2_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T2_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T2_CC2), +#elif defined(ADC_EXTERNALTRIG_T2_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T2_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T2_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T2_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T2_CC3), +#elif defined(ADC_EXTERNALTRIG_T2_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T2_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T2_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T2_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T2_CC4), +#elif defined(ADC_EXTERNALTRIG_T2_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T2_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T2_CC4) */ + }, + }, +#endif /* defined(TIM2) */ +#if defined(TIM3) + { + TIM3, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T3_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T3_TRGO), +#elif defined(ADC_EXTERNALTRIG_T3_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T3_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T3_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T3_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T3_CC1), +#elif defined(ADC_EXTERNALTRIG_T3_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T3_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T3_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T3_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T3_CC2), +#elif defined(ADC_EXTERNALTRIG_T3_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T3_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T3_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T3_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T3_CC3), +#elif defined(ADC_EXTERNALTRIG_T3_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T3_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T3_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T3_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T3_CC4), +#elif defined(ADC_EXTERNALTRIG_T3_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T3_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T3_CC4) */ + }, + }, +#endif /* defined(TIM3) */ +#if defined(TIM4) + { + TIM4, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T4_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T4_TRGO), +#elif defined(ADC_EXTERNALTRIG_T4_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T4_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T4_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T4_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T4_CC1), +#elif defined(ADC_EXTERNALTRIG_T4_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T4_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T4_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T4_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T4_CC2), +#elif defined(ADC_EXTERNALTRIG_T4_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T4_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T4_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T4_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T4_CC3), +#elif defined(ADC_EXTERNALTRIG_T4_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T4_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T4_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T4_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T4_CC4), +#elif defined(ADC_EXTERNALTRIG_T4_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T4_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T4_CC4) */ + }, + }, +#endif /* defined(TIM4) */ +#if defined(TIM5) + { + TIM5, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T5_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T5_TRGO), +#elif defined(ADC_EXTERNALTRIG_T5_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T5_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T5_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T5_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T5_CC1), +#elif defined(ADC_EXTERNALTRIG_T5_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T5_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T5_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T5_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T5_CC2), +#elif defined(ADC_EXTERNALTRIG_T5_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T5_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T5_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T5_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T5_CC3), +#elif defined(ADC_EXTERNALTRIG_T5_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T5_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T5_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T5_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T5_CC4), +#elif defined(ADC_EXTERNALTRIG_T5_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T5_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T5_CC4) */ + }, + }, +#endif /* defined(TIM5) */ +#if defined(TIM6) + { + TIM6, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T6_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T6_TRGO), +#elif defined(ADC_EXTERNALTRIG_T6_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T6_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T6_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T6_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T6_CC1), +#elif defined(ADC_EXTERNALTRIG_T6_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T6_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T6_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T6_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T6_CC2), +#elif defined(ADC_EXTERNALTRIG_T6_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T6_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T6_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T6_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T6_CC3), +#elif defined(ADC_EXTERNALTRIG_T6_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T6_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T6_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T6_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T6_CC4), +#elif defined(ADC_EXTERNALTRIG_T6_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T6_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T6_CC4) */ + }, + }, +#endif /* defined(TIM6) */ +#if defined(TIM7) + { + TIM7, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T7_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T7_TRGO), +#elif defined(ADC_EXTERNALTRIG_T7_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T7_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T7_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T7_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T7_CC1), +#elif defined(ADC_EXTERNALTRIG_T7_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T7_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T7_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T7_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T7_CC2), +#elif defined(ADC_EXTERNALTRIG_T7_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T7_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T7_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T7_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T7_CC3), +#elif defined(ADC_EXTERNALTRIG_T7_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T7_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T7_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T7_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T7_CC4), +#elif defined(ADC_EXTERNALTRIG_T7_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T7_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T7_CC4) */ + }, + }, +#endif /* defined(TIM7) */ +#if defined(TIM8) + { + TIM8, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T8_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T8_TRGO), +#elif defined(ADC_EXTERNALTRIG_T8_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T8_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T8_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T8_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T8_CC1), +#elif defined(ADC_EXTERNALTRIG_T8_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T8_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T8_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T8_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T8_CC2), +#elif defined(ADC_EXTERNALTRIG_T8_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T8_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T8_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T8_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T8_CC3), +#elif defined(ADC_EXTERNALTRIG_T8_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T8_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T8_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T8_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T8_CC4), +#elif defined(ADC_EXTERNALTRIG_T8_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T8_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T8_CC4) */ + }, + }, +#endif /* defined(TIM8) */ +#if defined(TIM9) + { + TIM9, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T9_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T9_TRGO), +#elif defined(ADC_EXTERNALTRIG_T9_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T9_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T9_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T9_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T9_CC1), +#elif defined(ADC_EXTERNALTRIG_T9_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T9_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T9_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T9_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T9_CC2), +#elif defined(ADC_EXTERNALTRIG_T9_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T9_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T9_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T9_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T9_CC3), +#elif defined(ADC_EXTERNALTRIG_T9_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T9_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T9_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T9_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T9_CC4), +#elif defined(ADC_EXTERNALTRIG_T9_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T9_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T9_CC4) */ + }, + }, +#endif /* defined(TIM9) */ +#if defined(TIM10) + { + TIM10, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T10_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T10_TRGO), +#elif defined(ADC_EXTERNALTRIG_T10_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T10_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T10_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T10_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T10_CC1), +#elif defined(ADC_EXTERNALTRIG_T10_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T10_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T10_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T10_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T10_CC2), +#elif defined(ADC_EXTERNALTRIG_T10_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T10_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T10_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T10_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T10_CC3), +#elif defined(ADC_EXTERNALTRIG_T10_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T10_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T10_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T10_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T10_CC4), +#elif defined(ADC_EXTERNALTRIG_T10_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T10_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T10_CC4) */ + }, + }, +#endif /* defined(TIM10) */ +#if defined(TIM11) + { + TIM11, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T11_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T11_TRGO), +#elif defined(ADC_EXTERNALTRIG_T11_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T11_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T11_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T11_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T11_CC1), +#elif defined(ADC_EXTERNALTRIG_T11_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T11_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T11_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T11_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T11_CC2), +#elif defined(ADC_EXTERNALTRIG_T11_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T11_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T11_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T11_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T11_CC3), +#elif defined(ADC_EXTERNALTRIG_T11_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T11_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T11_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T11_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T11_CC4), +#elif defined(ADC_EXTERNALTRIG_T11_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T11_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T11_CC4) */ + }, + }, +#endif /* defined(TIM11) */ +#if defined(TIM12) + { + TIM12, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T12_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T12_TRGO), +#elif defined(ADC_EXTERNALTRIG_T12_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T12_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T12_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T12_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T12_CC1), +#elif defined(ADC_EXTERNALTRIG_T12_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T12_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T12_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T12_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T12_CC2), +#elif defined(ADC_EXTERNALTRIG_T12_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T12_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T12_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T12_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T12_CC3), +#elif defined(ADC_EXTERNALTRIG_T12_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T12_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T12_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T12_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T12_CC4), +#elif defined(ADC_EXTERNALTRIG_T12_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T12_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T12_CC4) */ + }, + }, +#endif /* defined(TIM12) */ +#if defined(TIM13) + { + TIM13, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T13_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T13_TRGO), +#elif defined(ADC_EXTERNALTRIG_T13_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T13_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T13_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T13_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T13_CC1), +#elif defined(ADC_EXTERNALTRIG_T13_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T13_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T13_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T13_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T13_CC2), +#elif defined(ADC_EXTERNALTRIG_T13_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T13_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T13_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T13_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T13_CC3), +#elif defined(ADC_EXTERNALTRIG_T13_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T13_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T13_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T13_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T13_CC4), +#elif defined(ADC_EXTERNALTRIG_T13_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T13_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T13_CC4) */ + }, + }, +#endif /* defined(TIM13) */ +#if defined(TIM14) + { + TIM14, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T14_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T14_TRGO), +#elif defined(ADC_EXTERNALTRIG_T14_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T14_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T14_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T14_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T14_CC1), +#elif defined(ADC_EXTERNALTRIG_T14_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T14_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T14_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T14_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T14_CC2), +#elif defined(ADC_EXTERNALTRIG_T14_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T14_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T14_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T14_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T14_CC3), +#elif defined(ADC_EXTERNALTRIG_T14_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T14_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T14_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T14_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T14_CC4), +#elif defined(ADC_EXTERNALTRIG_T14_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T14_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T14_CC4) */ + }, + }, +#endif /* defined(TIM14) */ +#if defined(TIM15) + { + TIM15, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T15_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T15_TRGO), +#elif defined(ADC_EXTERNALTRIG_T15_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T15_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T15_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T15_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T15_CC1), +#elif defined(ADC_EXTERNALTRIG_T15_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T15_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T15_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T15_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T15_CC2), +#elif defined(ADC_EXTERNALTRIG_T15_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T15_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T15_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T15_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T15_CC3), +#elif defined(ADC_EXTERNALTRIG_T15_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T15_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T15_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T15_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T15_CC4), +#elif defined(ADC_EXTERNALTRIG_T15_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T15_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T15_CC4) */ + }, + }, +#endif /* defined(TIM15) */ +#if defined(TIM16) + { + TIM16, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T16_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T16_TRGO), +#elif defined(ADC_EXTERNALTRIG_T16_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T16_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T16_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T16_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T16_CC1), +#elif defined(ADC_EXTERNALTRIG_T16_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T16_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T16_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T16_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T16_CC2), +#elif defined(ADC_EXTERNALTRIG_T16_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T16_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T16_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T16_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T16_CC3), +#elif defined(ADC_EXTERNALTRIG_T16_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T16_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T16_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T16_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T16_CC4), +#elif defined(ADC_EXTERNALTRIG_T16_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T16_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T16_CC4) */ + }, + }, +#endif /* defined(TIM16) */ +#if defined(TIM17) + { + TIM17, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T17_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T17_TRGO), +#elif defined(ADC_EXTERNALTRIG_T17_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T17_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T17_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T17_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T17_CC1), +#elif defined(ADC_EXTERNALTRIG_T17_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T17_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T17_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T17_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T17_CC2), +#elif defined(ADC_EXTERNALTRIG_T17_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T17_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T17_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T17_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T17_CC3), +#elif defined(ADC_EXTERNALTRIG_T17_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T17_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T17_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T17_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T17_CC4), +#elif defined(ADC_EXTERNALTRIG_T17_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T17_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T17_CC4) */ + }, + }, +#endif /* defined(TIM17) */ +#if defined(TIM18) +{ + TIM18, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T18_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T18_TRGO), +#elif defined(ADC_EXTERNALTRIG_T18_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T18_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T18_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T18_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T18_CC1), +#elif defined(ADC_EXTERNALTRIG_T18_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T18_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T18_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T18_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T18_CC2), +#elif defined(ADC_EXTERNALTRIG_T18_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T18_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T18_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T18_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T18_CC3), +#elif defined(ADC_EXTERNALTRIG_T18_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T18_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T18_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T18_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T18_CC4), +#elif defined(ADC_EXTERNALTRIG_T18_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T18_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T18_CC4) */ + }, +}, +#endif /* defined(TIM18) */ +#if defined(TIM19) +{ + TIM19, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T19_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T19_TRGO), +#elif defined(ADC_EXTERNALTRIG_T19_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T19_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T19_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T19_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T19_CC1), +#elif defined(ADC_EXTERNALTRIG_T19_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T19_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T19_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T19_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T19_CC2), +#elif defined(ADC_EXTERNALTRIG_T19_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T19_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T19_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T19_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T19_CC3), +#elif defined(ADC_EXTERNALTRIG_T19_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T19_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T19_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T19_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T19_CC4), +#elif defined(ADC_EXTERNALTRIG_T19_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T19_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T19_CC4) */ + }, +}, +#endif /* defined(TIM19) */ +#if defined(TIM20) + { + TIM20, + STM32_ADC_INSTANCE_MASK_ALL, +#if defined(ADC_EXTERNALTRIGCONV_T20_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T20_TRGO), +#elif defined(ADC_EXTERNALTRIG_T20_TRGO) + STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T20_TRGO), +#else + STM32_ADC_TRIGGER_SELECTOR_NONE, +#endif /* defined(ADC_EXTERNALTRIGCONV_T20_TRGO) */ + { +#if defined(ADC_EXTERNALTRIGCONV_T20_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T20_CC1), +#elif defined(ADC_EXTERNALTRIG_T20_CC1) + [1] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T20_CC1), +#endif /* defined(ADC_EXTERNALTRIGCONV_T20_CC1) */ +#if defined(ADC_EXTERNALTRIGCONV_T20_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T20_CC2), +#elif defined(ADC_EXTERNALTRIG_T20_CC2) + [2] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T20_CC2), +#endif /* defined(ADC_EXTERNALTRIGCONV_T20_CC2) */ +#if defined(ADC_EXTERNALTRIGCONV_T20_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T20_CC3), +#elif defined(ADC_EXTERNALTRIG_T20_CC3) + [3] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T20_CC3), +#endif /* defined(ADC_EXTERNALTRIGCONV_T20_CC3) */ +#if defined(ADC_EXTERNALTRIGCONV_T20_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_T20_CC4), +#elif defined(ADC_EXTERNALTRIG_T20_CC4) + [4] = STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_T20_CC4), +#endif /* defined(ADC_EXTERNALTRIGCONV_T20_CC4) */ + }, + }, +#endif /* defined(TIM20) */ +}; + +/** + * @brief Resolve an ADC external trigger selector from a TIM event. + * @param adc Pointer to the STM32 ADC device object. + * @param instance TIM hardware instance. + * @param channel Timer compare channel, or 0 for update/TRGO. + * @param selector Pointer to the output HAL ADC trigger selector. + * @return RT_TRUE if the timer event is supported by this HAL build and ADC instance. + */ +static rt_bool_t stm32_adc_timer_trigger_selector_get(struct stm32_adc *adc, TIM_TypeDef *instance, + rt_uint16_t channel, rt_uint32_t *selector) +{ + rt_size_t index; + + for (index = 0; index < RT_ARRAY_SIZE(stm32_adc_timer_trigger_table); index++) + { + const struct stm32_adc_timer_trigger_map *map = &stm32_adc_timer_trigger_table[index]; + const struct stm32_adc_trigger_selector *slot; + + if (map->instance != instance) + { + continue; + } + + if (stm32_adc_instance_match(adc->handle.Instance, map->adc_instance_mask) != RT_TRUE) + { + return RT_FALSE; + } + + if (channel == 0U) + { + slot = &map->update; + } + else + { + if (channel > STM32_ADC_TIMER_COMPARE_CHANNEL_MAX) + { + return RT_FALSE; + } + slot = &map->compare[channel]; + } + + if (slot->valid != RT_TRUE) + { + return RT_FALSE; + } + + *selector = slot->selector; + return RT_TRUE; + } + + return RT_FALSE; +} + +/** + * @brief Encode one STM32 ADC timer trigger configuration. + * @param adc Pointer to the STM32 ADC device object. + * @param cfg Pointer to the ADC trigger configuration object. + * @param selector Pointer to the output HAL ADC trigger selector. + * @param edge Pointer to the output HAL ADC trigger edge selector. + * @return Operation status. + */ +static rt_err_t stm32_adc_encode_timer_trigger(struct stm32_adc *adc, const struct rt_adc_trigger_cfg *cfg, + rt_uint32_t *selector, rt_uint32_t *edge) +{ + TIM_HandleTypeDef *tim; + rt_uint16_t channel; + rt_err_t result; + + if (cfg->event.timer.timer == RT_NULL) + { + LOG_E("%s timer trigger source is null", adc->name); + return -RT_EINVAL; + } + + tim = (TIM_HandleTypeDef *)cfg->event.timer.timer->user_data; + if (tim == RT_NULL) + { + LOG_E("%s timer trigger source has no TIM handle", adc->name); + return -RT_EINVAL; + } + + switch (cfg->type) + { + case RT_ADC_TRIGGER_TIMER_UPDATE: + channel = 0U; + break; + + case RT_ADC_TRIGGER_TIMER_COMPARE: + channel = cfg->event.timer.channel; + if (channel == 0U) + { + LOG_E("%s timer compare trigger channel is invalid", adc->name); + return -RT_EINVAL; + } + break; + + default: + return -RT_EINVAL; + } + + if (stm32_adc_timer_trigger_selector_get(adc, tim->Instance, channel, selector) != RT_TRUE) + { + LOG_E("%s timer trigger source unsupported", adc->name); + return -RT_ENOSYS; + } + + result = stm32_adc_trigger_edge_encode(RT_ADC_TRIGGER_EDGE_RISING, edge); + return result; +} +#endif /* defined(STM32_ADC_USING_TIMER_TRIGGER) */ + +#if defined(STM32_ADC_USING_ANALOG_COMPARE_TRIGGER) +/** + * @brief STM32 comparator to ADC trigger selector table entry. + */ +struct stm32_adc_compare_trigger_slot +{ + rt_uint32_t adc_instance_mask; /**< ADC instances allowed to use this comparator trigger. */ + struct stm32_adc_trigger_selector trigger; /**< COMPx_OUT trigger selector. */ +}; + +/** + * @brief ADC analog comparator trigger selector table indexed by comparator channel. + */ +static const struct stm32_adc_compare_trigger_slot stm32_adc_compare_trigger_table[] = { + [0] = { 0U, STM32_ADC_TRIGGER_SELECTOR_NONE }, +#if defined(ADC_EXTERNALTRIGCONV_COMP1_OUT) + [1] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP1_OUT) }, +#elif defined(ADC_EXTERNALTRIG_COMP1_OUT) + [1] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP1_OUT) }, +#elif defined(ADC_EXTERNALTRIGCONV_COMP1) + [1] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP1) }, +#elif defined(ADC_EXTERNALTRIG_COMP1) + [1] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP1) }, +#endif /* defined(ADC_EXTERNALTRIGCONV_COMP1_OUT) */ +#if defined(ADC_EXTERNALTRIGCONV_COMP2_OUT) + [2] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP2_OUT) }, +#elif defined(ADC_EXTERNALTRIG_COMP2_OUT) + [2] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP2_OUT) }, +#elif defined(ADC_EXTERNALTRIGCONV_COMP2) + [2] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP2) }, +#elif defined(ADC_EXTERNALTRIG_COMP2) + [2] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP2) }, +#endif /* defined(ADC_EXTERNALTRIGCONV_COMP2_OUT) */ +#if defined(ADC_EXTERNALTRIGCONV_COMP3_OUT) + [3] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP3_OUT) }, +#elif defined(ADC_EXTERNALTRIG_COMP3_OUT) + [3] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP3_OUT) }, +#elif defined(ADC_EXTERNALTRIGCONV_COMP3) + [3] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP3) }, +#elif defined(ADC_EXTERNALTRIG_COMP3) + [3] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP3) }, +#endif /* defined(ADC_EXTERNALTRIGCONV_COMP3_OUT) */ +#if defined(ADC_EXTERNALTRIGCONV_COMP4_OUT) + [4] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP4_OUT) }, +#elif defined(ADC_EXTERNALTRIG_COMP4_OUT) + [4] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP4_OUT) }, +#elif defined(ADC_EXTERNALTRIGCONV_COMP4) + [4] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP4) }, +#elif defined(ADC_EXTERNALTRIG_COMP4) + [4] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP4) }, +#endif /* defined(ADC_EXTERNALTRIGCONV_COMP4_OUT) */ +#if defined(ADC_EXTERNALTRIGCONV_COMP5_OUT) + [5] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP5_OUT) }, +#elif defined(ADC_EXTERNALTRIG_COMP5_OUT) + [5] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP5_OUT) }, +#elif defined(ADC_EXTERNALTRIGCONV_COMP5) + [5] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP5) }, +#elif defined(ADC_EXTERNALTRIG_COMP5) + [5] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP5) }, +#endif /* defined(ADC_EXTERNALTRIGCONV_COMP5_OUT) */ +#if defined(ADC_EXTERNALTRIGCONV_COMP6_OUT) + [6] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP6_OUT) }, +#elif defined(ADC_EXTERNALTRIG_COMP6_OUT) + [6] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP6_OUT) }, +#elif defined(ADC_EXTERNALTRIGCONV_COMP6) + [6] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP6) }, +#elif defined(ADC_EXTERNALTRIG_COMP6) + [6] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP6) }, +#endif /* defined(ADC_EXTERNALTRIGCONV_COMP6_OUT) */ +#if defined(ADC_EXTERNALTRIGCONV_COMP7_OUT) + [7] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP7_OUT) }, +#elif defined(ADC_EXTERNALTRIG_COMP7_OUT) + [7] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP7_OUT) }, +#elif defined(ADC_EXTERNALTRIGCONV_COMP7) + [7] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIGCONV_COMP7) }, +#elif defined(ADC_EXTERNALTRIG_COMP7) + [7] = { STM32_ADC_INSTANCE_MASK_ALL, STM32_ADC_TRIGGER_SELECTOR(ADC_EXTERNALTRIG_COMP7) }, +#endif /* defined(ADC_EXTERNALTRIGCONV_COMP7_OUT) */ +}; + +/** + * @brief Resolve an ADC external trigger selector from a comparator channel. + * @param adc Pointer to the STM32 ADC device object. + * @param channel Comparator channel. + * @param selector Pointer to the output HAL ADC trigger selector. + * @return RT_TRUE if the comparator channel is supported by this HAL build and ADC instance. + */ +static rt_bool_t stm32_adc_compare_trigger_selector_get(struct stm32_adc *adc, rt_uint16_t channel, rt_uint32_t *selector) +{ + const struct stm32_adc_compare_trigger_slot *slot; + + if (channel >= RT_ARRAY_SIZE(stm32_adc_compare_trigger_table)) + { + return RT_FALSE; + } + + slot = &stm32_adc_compare_trigger_table[channel]; + if (slot->trigger.valid != RT_TRUE) + { + return RT_FALSE; + } + + if (stm32_adc_instance_match(adc->handle.Instance, slot->adc_instance_mask) != RT_TRUE) + { + return RT_FALSE; + } + + *selector = slot->trigger.selector; + return RT_TRUE; +} + +/** + * @brief Encode one STM32 ADC analog comparator trigger configuration. + * @param adc Pointer to the STM32 ADC device object. + * @param cfg Pointer to the ADC trigger configuration object. + * @param selector Pointer to the output HAL ADC trigger selector. + * @param edge Pointer to the output HAL ADC trigger edge selector. + * @return Operation status. + */ +static rt_err_t stm32_adc_encode_compare_trigger(struct stm32_adc *adc, const struct rt_adc_trigger_cfg *cfg, + rt_uint32_t *selector, rt_uint32_t *edge) +{ + rt_err_t result; + + if ((cfg->event.compare.channel == 0U) || + (cfg->event.compare.edge == RT_ADC_TRIGGER_EDGE_NONE)) + { + LOG_E("%s analog compare trigger config invalid", adc->name); + return -RT_EINVAL; + } + + if (stm32_adc_compare_trigger_selector_get(adc, cfg->event.compare.channel, selector) != RT_TRUE) + { + LOG_E("%s analog compare trigger source unsupported", adc->name); + return -RT_ENOSYS; + } + + result = stm32_adc_trigger_edge_encode(cfg->event.compare.edge, edge); + return result; +} +#endif /* defined(STM32_ADC_USING_ANALOG_COMPARE_TRIGGER) */ + +/** + * @brief Encode one STM32 ADC trigger configuration into HAL selector fields. + * @param adc Pointer to the STM32 ADC device object. + * @param cfg Pointer to the ADC trigger configuration object, or RT_NULL for software/default trigger. + * @param selector Pointer to the output HAL ADC trigger selector. + * @param edge Pointer to the output HAL ADC trigger edge selector. + * @return Operation status. + */ +static rt_err_t stm32_adc_encode_trigger(struct stm32_adc *adc, const struct rt_adc_trigger_cfg *cfg, + rt_uint32_t *selector, rt_uint32_t *edge) +{ + rt_err_t result; + + if (cfg == RT_NULL) + { + *selector = ADC_SOFTWARE_START; + return stm32_adc_trigger_edge_encode(RT_ADC_TRIGGER_EDGE_NONE, edge); + } + + switch (cfg->type) + { +#if defined(STM32_ADC_USING_TIMER_TRIGGER) + case RT_ADC_TRIGGER_TIMER_UPDATE: + case RT_ADC_TRIGGER_TIMER_COMPARE: + result = stm32_adc_encode_timer_trigger(adc, cfg, selector, edge); + break; +#endif /* defined(STM32_ADC_USING_TIMER_TRIGGER) */ + +#if defined(STM32_ADC_USING_ANALOG_COMPARE_TRIGGER) + case RT_ADC_TRIGGER_ANALOG_COMPARE: + result = stm32_adc_encode_compare_trigger(adc, cfg, selector, edge); + break; +#endif /* defined(STM32_ADC_USING_ANALOG_COMPARE_TRIGGER) */ + + + default: + LOG_E("%s trigger type unsupported: %d", adc->name, (int)cfg->type); + result = -RT_ENOSYS; + break; + } + + return result; +} + +/** + * @brief Resolve STM32 ADC trigger selector fields. + * @param adc Pointer to the STM32 ADC device object. + * @param cfg Pointer to the ADC trigger configuration, or RT_NULL for software start. + * @param fields Pointer to the output STM32 trigger fields. + * @return Operation status. + */ +rt_err_t stm32_adc_trigger_fields_get(struct stm32_adc *adc, const struct rt_adc_trigger_cfg *cfg, + struct stm32_adc_trigger_fields *fields) +{ + return stm32_adc_encode_trigger(adc, cfg, &fields->selector, &fields->edge); +} + +/** + * @brief Preconfigure STM32 ADC trigger selector state for the next stream configuration. + * @param device Pointer to the ADC framework device object. + * @param cfg Pointer to the ADC trigger configuration, or RT_NULL for software start. + * @return Operation status. + */ +rt_err_t stm32_adc_trigger_prepare(struct rt_adc_device *device, const struct rt_adc_trigger_cfg *cfg) +{ + struct stm32_adc *adc; + struct stm32_adc_trigger_fields fields; + rt_err_t result; + + adc = (struct stm32_adc *)device->parent.user_data; + if (adc == RT_NULL) + { + return -RT_EINVAL; + } + + result = stm32_adc_trigger_fields_get(adc, cfg, &fields); + if (result != RT_EOK) + { + adc->prepared_trigger_valid = RT_FALSE; + return result; + } + + adc->prepared_trigger = fields; + adc->prepared_trigger_valid = RT_TRUE; + return RT_EOK; +} +#endif /* defined(STM32_ADC_USING_TRIGGER) */ + +#endif /* defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) || defined(BSP_USING_ADC4) */ + +#endif /* defined(RT_USING_ADC_V2) */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_config.h b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_config.h index ff02efa64ca..be3221c517b 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_config.h +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_config.h @@ -6,7 +6,7 @@ * Change Logs: * Date Author Notes * 2018-10-30 SummerGift first version - * 2020-10-14 PeakRacing Porting for stm32wbxx + * 2020-10-14 PeakRacing Porting for stm32wbxx */ #ifndef __DRV_CONFIG_H__ @@ -18,7 +18,7 @@ #ifdef __cplusplus extern "C" { -#endif +#endif /* __cplusplus */ #if defined(SOC_SERIES_STM32F0) #include "f0/dma_config.h" @@ -27,101 +27,113 @@ extern "C" { #include "f0/tim_config.h" #include "f0/pwm_config.h" #include "f0/adc_config.h" +#include "f0/adc_config_v2.h" #elif defined(SOC_SERIES_STM32F1) #include "f1/dma_config.h" #include "f1/uart_config.h" #include "f1/spi_config.h" #include "f1/adc_config.h" +#include "f1/adc_config_v2.h" #include "f1/tim_config.h" #include "f1/sdio_config.h" #include "f1/pwm_config.h" #include "f1/usbd_config.h" #include "f1/i2c_hard_config.h" #include "f1/pulse_encoder_config.h" -#elif defined(SOC_SERIES_STM32F2) +#elif defined(SOC_SERIES_STM32F2) #include "f2/dma_config.h" #include "f2/uart_config.h" #include "f2/spi_config.h" #include "f2/adc_config.h" +#include "f2/adc_config_v2.h" #include "f2/tim_config.h" #include "f2/sdio_config.h" #include "f2/pwm_config.h" -#elif defined(SOC_SERIES_STM32F3) +#elif defined(SOC_SERIES_STM32F3) #include "f3/uart_config.h" #include "f3/tim_config.h" #include "f3/pwm_config.h" #include "f3/dma_config.h" -#elif defined(SOC_SERIES_STM32F4) +#include "f3/adc_config_v2.h" +#elif defined(SOC_SERIES_STM32F4) #include "f4/dma_config.h" #include "f4/uart_config.h" #include "f4/spi_config.h" #include "f4/qspi_config.h" #include "f4/usbd_config.h" #include "f4/adc_config.h" +#include "f4/adc_config_v2.h" #include "f4/dac_config.h" #include "f4/tim_config.h" #include "f4/sdio_config.h" #include "f4/pwm_config.h" #include "f4/i2c_hard_config.h" #include "f4/pulse_encoder_config.h" -#elif defined(SOC_SERIES_STM32F7) +#elif defined(SOC_SERIES_STM32F7) #include "f7/dma_config.h" #include "f7/uart_config.h" #include "f7/spi_config.h" #include "f7/qspi_config.h" #include "f7/adc_config.h" +#include "f7/adc_config_v2.h" #include "f7/tim_config.h" #include "f7/sdio_config.h" #include "f7/pwm_config.h" -#elif defined(SOC_SERIES_STM32L0) +#elif defined(SOC_SERIES_STM32L0) #include "l0/dma_config.h" #include "l0/uart_config.h" -#elif defined(SOC_SERIES_STM32L4) +#include "l0/adc_config_v2.h" +#elif defined(SOC_SERIES_STM32L4) #include "l4/dma_config.h" #include "l4/uart_config.h" #include "l4/spi_config.h" #include "l4/qspi_config.h" #include "l4/adc_config.h" +#include "l4/adc_config_v2.h" #include "l4/dac_config.h" #include "l4/tim_config.h" #include "l4/sdio_config.h" #include "l4/pwm_config.h" #include "l4/usbd_config.h" -#elif defined(SOC_SERIES_STM32L5) +#elif defined(SOC_SERIES_STM32L5) #include "l5/dma_config.h" #include "l5/uart_config.h" #include "l5/spi_config.h" #include "l5/qspi_config.h" #include "l5/adc_config.h" +#include "l5/adc_config_v2.h" #include "l5/dac_config.h" #include "l5/tim_config.h" #include "l5/sdio_config.h" #include "l5/pwm_config.h" #include "l5/usbd_config.h" -#elif defined(SOC_SERIES_STM32G0) +#elif defined(SOC_SERIES_STM32G0) #include "g0/dma_config.h" #include "g0/uart_config.h" #include "g0/spi_config.h" #include "g0/adc_config.h" +#include "g0/adc_config_v2.h" #include "g0/tim_config.h" #include "g0/pwm_config.h" -#elif defined(SOC_SERIES_STM32G4) +#elif defined(SOC_SERIES_STM32G4) #include "g4/dma_config.h" #include "g4/uart_config.h" #include "g4/spi_config.h" #include "g4/qspi_config.h" #include "g4/usbd_config.h" #include "g4/adc_config.h" +#include "g4/adc_config_v2.h" #include "g4/tim_config.h" #include "g4/sdio_config.h" #include "g4/pwm_config.h" #include "g4/pulse_encoder_config.h" -#elif defined(SOC_SERIES_STM32H7) +#elif defined(SOC_SERIES_STM32H7) #include "h7/dma_config.h" #include "h7/uart_config.h" #include "h7/spi_config.h" #include "h7/qspi_config.h" #include "h7/adc_config.h" +#include "h7/adc_config_v2.h" #include "h7/dac_config.h" #include "h7/tim_config.h" #include "h7/lptim_config.h" @@ -129,23 +141,23 @@ extern "C" { #include "h7/pwm_config.h" #include "h7/usbd_config.h" #include "h7/i2c_hard_config.h" - -#elif defined(SOC_SERIES_STM32H7RS) +#elif defined(SOC_SERIES_STM32H7RS) #include "h7/dma_config.h" #include "h7/uart_config.h" #include "h7/spi_config.h" #include "h7/adc_config.h" +#include "h7rs/adc_config_v2.h" #include "h7/dac_config.h" #include "h7/tim_config.h" #include "h7/pwm_config.h" #include "h7/usbd_config.h" - #elif defined(SOC_SERIES_STM32U5) #include "u5/dma_config.h" #include "u5/uart_config.h" #include "u5/spi_config.h" #include "u5/qspi_config.h" #include "u5/adc_config.h" +#include "u5/adc_config_v2.h" #include "u5/dac_config.h" #include "u5/tim_config.h" #include "u5/sdio_config.h" @@ -155,22 +167,26 @@ extern "C" { #include "h5/uart_config.h" #include "h5/pwm_config.h" #include "h5/adc_config.h" -#elif defined(SOC_SERIES_STM32MP1) +#include "h5/adc_config_v2.h" +#elif defined(SOC_SERIES_STM32MP1) #include "mp1/dma_config.h" #include "mp1/uart_config.h" #include "mp1/qspi_config.h" #include "mp1/spi_config.h" #include "mp1/adc_config.h" +#include "mp1/adc_config_v2.h" #include "mp1/dac_config.h" #include "mp1/tim_config.h" #include "mp1/pwm_config.h" -#elif defined(SOC_SERIES_STM32WL) +#elif defined(SOC_SERIES_STM32WL) #include "wl/dma_config.h" #include "wl/uart_config.h" #include "wl/spi_config.h" #include "wl/tim_config.h" -#elif defined(SOC_SERIES_STM32WB) +#include "wl/adc_config_v2.h" +#elif defined(SOC_SERIES_STM32WB) #include "wb/adc_config.h" +#include "wb/adc_config_v2.h" #include "wb/dma_config.h" #include "wb/pwm_config.h" #include "wb/qspi_config.h" @@ -178,10 +194,10 @@ extern "C" { #include "wb/tim_config.h" #include "wb/uart_config.h" #include "wb/usbd_config.h" -#endif +#endif /* defined(SOC_SERIES_STM32F0) */ #ifdef __cplusplus } -#endif +#endif /* __cplusplus */ -#endif +#endif /* __DRV_CONFIG_H__ */ \ No newline at end of file diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_dma.h b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_dma.h index c4feec05a86..83e1535e685 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_dma.h +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_dma.h @@ -265,6 +265,9 @@ struct stm32_dma_config #define STM32_DMA_RX_WORD_CONFIG_INIT_EX(_instance, _dma_rcc, _dma_irq, _channel, _request, _priority, _preempt_priority, _sub_priority) \ STM32_DMA_CONFIG_INIT_EX((_instance), (_dma_rcc), (_dma_irq), (_channel), (_request), (_priority), (_preempt_priority), (_sub_priority), DMA_PERIPH_TO_MEMORY, DMA_PINC_DISABLE, DMA_MINC_ENABLE, DMA_PDATAALIGN_WORD, DMA_MDATAALIGN_WORD, DMA_NORMAL) +#define STM32_DMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(_instance, _dma_rcc, _dma_irq, _channel, _request, _priority, _preempt_priority, _sub_priority) \ + STM32_DMA_CONFIG_INIT_EX((_instance), (_dma_rcc), (_dma_irq), (_channel), (_request), (_priority), (_preempt_priority), (_sub_priority), DMA_PERIPH_TO_MEMORY, DMA_PINC_DISABLE, DMA_MINC_ENABLE, DMA_PDATAALIGN_WORD, DMA_MDATAALIGN_WORD, DMA_CIRCULAR) + #define STM32_DMA_TX_WORD_CONFIG_INIT_EX(_instance, _dma_rcc, _dma_irq, _channel, _request, _priority, _preempt_priority, _sub_priority) \ STM32_DMA_CONFIG_INIT_EX((_instance), (_dma_rcc), (_dma_irq), (_channel), (_request), (_priority), (_preempt_priority), (_sub_priority), DMA_MEMORY_TO_PERIPH, DMA_PINC_DISABLE, DMA_MINC_ENABLE, DMA_PDATAALIGN_WORD, DMA_MDATAALIGN_WORD, DMA_NORMAL) @@ -305,6 +308,9 @@ struct stm32_dma_config #define STM32_GPDMA_RX_WORD_CONFIG_INIT_EX(_instance, _dma_rcc, _dma_irq, _request, _priority, _preempt_priority, _sub_priority) \ STM32_GPDMA_CONFIG_INIT_EX((_instance), (_dma_rcc), (_dma_irq), (_request), (_priority), (_preempt_priority), (_sub_priority), DMA_PERIPH_TO_MEMORY, DMA_SINC_FIXED, DMA_DINC_INCREMENTED, DMA_SRC_DATAWIDTH_WORD, DMA_DEST_DATAWIDTH_WORD, DMA_NORMAL) +#define STM32_GPDMA_RX_WORD_CIRCULAR_CONFIG_INIT_EX(_instance, _dma_rcc, _dma_irq, _request, _priority, _preempt_priority, _sub_priority) \ + STM32_GPDMA_CONFIG_INIT_EX((_instance), (_dma_rcc), (_dma_irq), (_request), (_priority), (_preempt_priority), (_sub_priority), DMA_PERIPH_TO_MEMORY, DMA_SINC_FIXED, DMA_DINC_INCREMENTED, DMA_SRC_DATAWIDTH_WORD, DMA_DEST_DATAWIDTH_WORD, DMA_CIRCULAR) + #define STM32_GPDMA_TX_WORD_CONFIG_INIT_EX(_instance, _dma_rcc, _dma_irq, _request, _priority, _preempt_priority, _sub_priority) \ STM32_GPDMA_CONFIG_INIT_EX((_instance), (_dma_rcc), (_dma_irq), (_request), (_priority), (_preempt_priority), (_sub_priority), DMA_MEMORY_TO_PERIPH, DMA_SINC_INCREMENTED, DMA_DINC_FIXED, DMA_SRC_DATAWIDTH_WORD, DMA_DEST_DATAWIDTH_WORD, DMA_NORMAL) diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_tim.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_tim.c index b236a7ffdd5..a443bc1494f 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_tim.c +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_tim.c @@ -116,6 +116,44 @@ void stm32_tim_pclkx_doubler_get(rt_uint32_t *pclk1_doubler, rt_uint32_t *pclk2_ #endif /* defined(SOC_SERIES_STM32MP1) */ } +#if defined(RT_USING_CLOCK_TIMER_TRIGGER) +/** + * @brief Get the effective input clock frequency of one STM32 timer. + * @param tim Pointer to the STM32 HAL timer handle. + * @param timer_clk Pointer to the output timer clock frequency in hertz. + * @return Operation status. + */ +static rt_err_t stm32_tim_clock_get(TIM_HandleTypeDef *tim, rt_uint32_t *timer_clk) +{ + rt_uint32_t pclk1_doubler; + rt_uint32_t pclk2_doubler; + + stm32_tim_pclkx_doubler_get(&pclk1_doubler, &pclk2_doubler); + +#if defined(APBPERIPH_BASE) + *timer_clk = HAL_RCC_GetPCLK1Freq() * pclk1_doubler; +#elif defined(APB1PERIPH_BASE) || defined(APB2PERIPH_BASE) + if ((rt_uint32_t)tim->Instance >= APB2PERIPH_BASE) + { + *timer_clk = HAL_RCC_GetPCLK2Freq() * pclk2_doubler; + } + else + { + *timer_clk = HAL_RCC_GetPCLK1Freq() * pclk1_doubler; + } +#else +#error "This driver has not supported this series yet!" +#endif /* defined(APBPERIPH_BASE) */ + + if (*timer_clk == 0U) + { + return -RT_ERROR; + } + + return RT_EOK; +} +#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */ + void stm32_tim_enable_clock(TIM_HandleTypeDef* htim_base) { RT_ASSERT(htim_base != RT_NULL); @@ -304,6 +342,10 @@ struct stm32_clock_timer TIM_HandleTypeDef tim_handle; IRQn_Type tim_irqn; char *name; +#if defined(RT_USING_CLOCK_TIMER_TRIGGER) + enum rt_clock_timer_trigger_event trigger_event; /**< Cached trigger output event. */ + rt_uint16_t trigger_channel; /**< Cached compare channel, or 0 for update event. */ +#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */ }; static struct stm32_clock_timer stm32_clock_timer_obj[] = @@ -485,6 +527,448 @@ static void timer_stop(rt_clock_timer_t *timer) __HAL_TIM_SET_COUNTER(tim, 0); } +#if defined(RT_USING_CLOCK_TIMER_TRIGGER) +/** + * @brief Calculate STM32 timer divider values for hardware trigger output. + * @param timer Pointer to the RT-Thread clock timer device. + * @param freq_hz Target trigger frequency in hertz. + * @param prescaler Pointer to the output PSC register value. + * @param period Pointer to the output ARR register value. + * @return Operation status. + */ +static rt_err_t timer_trigger_calc(rt_clock_timer_t *timer, rt_uint32_t freq_hz, rt_uint32_t *prescaler, rt_uint32_t *period) +{ + TIM_HandleTypeDef *tim; + rt_uint32_t timer_clk; + rt_uint32_t max_period; + rt_uint64_t cycles; + rt_uint64_t prescaler_div; + rt_uint64_t period_count; + rt_err_t result; + + tim = (TIM_HandleTypeDef *)timer->parent.user_data; + result = stm32_tim_clock_get(tim, &timer_clk); + if (result != RT_EOK) + { + return result; + } + + if (freq_hz > timer_clk) + { + return -RT_EINVAL; + } + + cycles = ((rt_uint64_t)timer_clk + (freq_hz / 2U)) / freq_hz; + if (cycles == 0U) + { + return -RT_EINVAL; + } + + max_period = ((timer->info != RT_NULL) && (timer->info->maxcnt != 0U)) ? timer->info->maxcnt : 0xffffU; + prescaler_div = (cycles + max_period - 1U) / max_period; + if ((prescaler_div == 0U) || (prescaler_div > 0x10000ULL)) + { + return -RT_EINVAL; + } + + period_count = cycles / prescaler_div; + if (period_count == 0U) + { + period_count = 1U; + } + if (period_count > max_period) + { + period_count = max_period; + } + + *prescaler = (rt_uint32_t)(prescaler_div - 1U); + *period = (rt_uint32_t)(period_count - 1U); + + return RT_EOK; +} + + +/** @brief Maximum compare channel index encoded by the STM32 TIM trigger backend. */ +#define STM32_TIM_TRIGGER_COMPARE_CHANNEL_MAX 4U + +/** + * @brief STM32 HAL timer compare channel slot. + */ +struct stm32_tim_compare_channel +{ + rt_uint32_t channel; /**< HAL TIM channel selector. */ + rt_uint32_t flag; /**< HAL TIM compare flag. */ + rt_bool_t valid; /**< Whether channel and flag are valid. */ +}; + +/** + * @brief HAL TIM compare channel table indexed by 1-based timer channel number. + */ +static const struct stm32_tim_compare_channel stm32_tim_compare_channel_table[STM32_TIM_TRIGGER_COMPARE_CHANNEL_MAX + 1U] = { +#if defined(TIM_CHANNEL_1) && defined(TIM_FLAG_CC1) + [1] = { TIM_CHANNEL_1, TIM_FLAG_CC1, RT_TRUE }, +#endif /* defined(TIM_CHANNEL_1) && defined(TIM_FLAG_CC1) */ +#if defined(TIM_CHANNEL_2) && defined(TIM_FLAG_CC2) + [2] = { TIM_CHANNEL_2, TIM_FLAG_CC2, RT_TRUE }, +#endif /* defined(TIM_CHANNEL_2) && defined(TIM_FLAG_CC2) */ +#if defined(TIM_CHANNEL_3) && defined(TIM_FLAG_CC3) + [3] = { TIM_CHANNEL_3, TIM_FLAG_CC3, RT_TRUE }, +#endif /* defined(TIM_CHANNEL_3) && defined(TIM_FLAG_CC3) */ +#if defined(TIM_CHANNEL_4) && defined(TIM_FLAG_CC4) + [4] = { TIM_CHANNEL_4, TIM_FLAG_CC4, RT_TRUE }, +#endif /* defined(TIM_CHANNEL_4) && defined(TIM_FLAG_CC4) */ +}; + +/** + * @brief Get a HAL compare channel slot from a 1-based timer channel number. + * @param channel 1-based timer compare channel number. + * @return Pointer to a valid channel slot, or RT_NULL when unsupported. + */ +static const struct stm32_tim_compare_channel *timer_trigger_compare_channel_get(rt_uint16_t channel) +{ + const struct stm32_tim_compare_channel *slot; + + if (channel >= RT_ARRAY_SIZE(stm32_tim_compare_channel_table)) + { + return RT_NULL; + } + + slot = &stm32_tim_compare_channel_table[channel]; + return (slot->valid == RT_TRUE) ? slot : RT_NULL; +} + +/** + * @brief Fill the common STM32 timer base configuration for trigger output. + * @param tim Pointer to the STM32 HAL timer handle. + * @param prescaler PSC register value. + * @param period ARR register value. + */ +static void timer_trigger_base_fill(TIM_HandleTypeDef *tim, rt_uint32_t prescaler, rt_uint32_t period) +{ + tim->Init.Prescaler = prescaler; + tim->Init.Period = period; + tim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + tim->Init.CounterMode = TIM_COUNTERMODE_UP; + tim->Init.RepetitionCounter = 0; +#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G4) || defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) + tim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; +#endif /* defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G4) || defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) */ +} + +/** + * @brief Configure one STM32 timer update event as a hardware trigger source. + * @param timer_device Pointer to the STM32 clock timer object. + * @param prescaler PSC register value. + * @param period ARR register value. + * @return Operation status. + */ +static rt_err_t timer_trigger_update_config(struct stm32_clock_timer *timer_device, rt_uint32_t prescaler, rt_uint32_t period) +{ +#if defined(TIM_TRGO_UPDATE) + TIM_HandleTypeDef *tim; + TIM_MasterConfigTypeDef master = {0}; + + tim = &timer_device->tim_handle; + HAL_TIM_Base_Stop(tim); + timer_trigger_base_fill(tim, prescaler, period); + + if (HAL_TIM_Base_Init(tim) != HAL_OK) + { + LOG_E("TIM trigger base init failed"); + return -RT_ERROR; + } + + master.MasterOutputTrigger = TIM_TRGO_UPDATE; +#if defined(TIM_MASTERSLAVEMODE_DISABLE) + master.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; +#endif /* defined(TIM_MASTERSLAVEMODE_DISABLE) */ + if (HAL_TIMEx_MasterConfigSynchronization(tim, &master) != HAL_OK) + { + LOG_E("TIM trigger master config failed"); + return -RT_ERROR; + } + + timer_device->trigger_event = CLOCK_TIMER_TRIGGER_EVENT_UPDATE; + timer_device->trigger_channel = 0U; + tim->Instance->CR1 &= (~TIM_OPMODE_SINGLE); + __HAL_TIM_SET_COUNTER(tim, 0); + __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE); + + return RT_EOK; +#else + RT_UNUSED(timer_device); + RT_UNUSED(prescaler); + RT_UNUSED(period); + return -RT_ENOSYS; +#endif /* defined(TIM_TRGO_UPDATE) */ +} + + +/** + * @brief Configure one STM32 timer compare event as a hardware trigger source. + * @param timer_device Pointer to the STM32 clock timer object. + * @param cfg Pointer to the hardware trigger configuration. + * @param prescaler PSC register value. + * @param period ARR register value. + * @return Operation status. + */ +static rt_err_t timer_trigger_compare_config(struct stm32_clock_timer *timer_device, + const struct rt_clock_timer_trigger_cfg *cfg, + rt_uint32_t prescaler, rt_uint32_t period) +{ +#if defined(TIM_OCMODE_TIMING) + const struct stm32_tim_compare_channel *slot; + TIM_HandleTypeDef *tim; + TIM_OC_InitTypeDef oc = {0}; + rt_uint32_t pulse; + + slot = timer_trigger_compare_channel_get(cfg->channel); + if (slot == RT_NULL) + { + return -RT_EINVAL; + } + + tim = &timer_device->tim_handle; + HAL_TIM_OC_Stop(tim, slot->channel); + HAL_TIM_Base_Stop(tim); + timer_trigger_base_fill(tim, prescaler, period); + + if (HAL_TIM_Base_Init(tim) != HAL_OK) + { + LOG_E("TIM trigger compare base init failed"); + return -RT_ERROR; + } + if (HAL_TIM_OC_Init(tim) != HAL_OK) + { + LOG_E("TIM trigger compare init failed"); + return -RT_ERROR; + } + + pulse = (period + 1U) / 2U; + if (pulse > period) + { + pulse = period; + } + + oc.OCMode = TIM_OCMODE_PWM2; + oc.Pulse = pulse; +#if defined(TIM_OCPOLARITY_HIGH) + oc.OCPolarity = TIM_OCPOLARITY_HIGH; +#endif /* defined(TIM_OCPOLARITY_HIGH) */ +#if defined(TIM_OCNPOLARITY_HIGH) + oc.OCNPolarity = TIM_OCNPOLARITY_HIGH; +#endif /* defined(TIM_OCNPOLARITY_HIGH) */ +#if defined(TIM_OCFAST_DISABLE) + oc.OCFastMode = TIM_OCFAST_DISABLE; +#endif /* defined(TIM_OCFAST_DISABLE) */ +#if defined(TIM_OCIDLESTATE_RESET) + oc.OCIdleState = TIM_OCIDLESTATE_RESET; +#endif /* defined(TIM_OCIDLESTATE_RESET) */ +#if defined(TIM_OCNIDLESTATE_RESET) + oc.OCNIdleState = TIM_OCNIDLESTATE_RESET; +#endif /* defined(TIM_OCNIDLESTATE_RESET) */ + + if (HAL_TIM_OC_ConfigChannel(tim, &oc, slot->channel) != HAL_OK) + { + LOG_E("TIM trigger compare channel config failed"); + return -RT_ERROR; + } + + timer_device->trigger_event = CLOCK_TIMER_TRIGGER_EVENT_COMPARE; + timer_device->trigger_channel = cfg->channel; + tim->Instance->CR1 &= (~TIM_OPMODE_SINGLE); + __HAL_TIM_SET_COUNTER(tim, 0); + __HAL_TIM_CLEAR_FLAG(tim, slot->flag); + + return RT_EOK; +#else + RT_UNUSED(timer_device); + RT_UNUSED(cfg); + RT_UNUSED(prescaler); + RT_UNUSED(period); + return -RT_ENOSYS; +#endif /* defined(TIM_OCMODE_TIMING) */ +} + +/** + * @brief Configure one STM32 timer as a hardware trigger source. + * @param timer Pointer to the RT-Thread clock timer device. + * @param cfg Pointer to the hardware trigger configuration. + * @return Operation status. + */ +static rt_err_t timer_trigger_config(rt_clock_timer_t *timer, const struct rt_clock_timer_trigger_cfg *cfg) +{ + struct stm32_clock_timer *timer_device; + rt_uint32_t prescaler; + rt_uint32_t period; + rt_err_t result; + + if (cfg->freq_hz == 0U) + { + return -RT_EINVAL; + } + + if ((cfg->event != CLOCK_TIMER_TRIGGER_EVENT_UPDATE) && + (cfg->event != CLOCK_TIMER_TRIGGER_EVENT_COMPARE)) + { + return -RT_EINVAL; + } + + timer_device = (struct stm32_clock_timer *)timer; + if (timer_device->time_device.parent.user_data == RT_NULL) + { + return -RT_EINVAL; + } + + result = timer_trigger_calc(timer, cfg->freq_hz, &prescaler, &period); + if (result != RT_EOK) + { + return result; + } + + stm32_tim_enable_clock(&timer_device->tim_handle); + + switch (cfg->event) + { + case CLOCK_TIMER_TRIGGER_EVENT_UPDATE: + return timer_trigger_update_config(timer_device, prescaler, period); + + case CLOCK_TIMER_TRIGGER_EVENT_COMPARE: + return timer_trigger_compare_config(timer_device, cfg, prescaler, period); + + default: + return -RT_EINVAL; + } +} + +/** + * @brief Start hardware trigger output on one STM32 timer. + * @param timer Pointer to the RT-Thread clock timer device. + * @return Operation status. + */ +static rt_err_t timer_trigger_start(rt_clock_timer_t *timer) +{ + struct stm32_clock_timer *timer_device; + const struct stm32_tim_compare_channel *slot; + TIM_HandleTypeDef *tim; + + timer_device = (struct stm32_clock_timer *)timer; + if (timer_device->time_device.parent.user_data == RT_NULL) + { + return -RT_EINVAL; + } + + tim = &timer_device->tim_handle; + tim->Instance->CR1 &= (~TIM_OPMODE_SINGLE); + __HAL_TIM_SET_COUNTER(tim, 0); + + if (timer_device->trigger_event == CLOCK_TIMER_TRIGGER_EVENT_COMPARE) + { + slot = timer_trigger_compare_channel_get(timer_device->trigger_channel); + if (slot == RT_NULL) + { + return -RT_EINVAL; + } + __HAL_TIM_CLEAR_FLAG(tim, slot->flag); + return (HAL_TIM_OC_Start(tim, slot->channel) == HAL_OK) ? RT_EOK : -RT_ERROR; + } + + __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE); + return (HAL_TIM_Base_Start(tim) == HAL_OK) ? RT_EOK : -RT_ERROR; +} + +/** + * @brief Stop hardware trigger output on one STM32 timer. + * @param timer Pointer to the RT-Thread clock timer device. + * @return Operation status. + */ +static rt_err_t timer_trigger_stop(rt_clock_timer_t *timer) +{ + struct stm32_clock_timer *timer_device; + const struct stm32_tim_compare_channel *slot; + TIM_HandleTypeDef *tim; + rt_err_t result; + + timer_device = (struct stm32_clock_timer *)timer; + if (timer_device->time_device.parent.user_data == RT_NULL) + { + return -RT_EINVAL; + } + + tim = &timer_device->tim_handle; + + if (timer_device->trigger_event == CLOCK_TIMER_TRIGGER_EVENT_COMPARE) + { + slot = timer_trigger_compare_channel_get(timer_device->trigger_channel); + if (slot == RT_NULL) + { + return -RT_EINVAL; + } + result = (HAL_TIM_OC_Stop(tim, slot->channel) == HAL_OK) ? RT_EOK : -RT_ERROR; + __HAL_TIM_CLEAR_FLAG(tim, slot->flag); + } + else + { + result = (HAL_TIM_Base_Stop(tim) == HAL_OK) ? RT_EOK : -RT_ERROR; + __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE); + } + + __HAL_TIM_SET_COUNTER(tim, 0); + return result; +} + +/** + * @brief Release and deinitialize hardware trigger output on one STM32 timer. + * @param timer Pointer to the RT-Thread clock timer device. + * @return Operation status. + * @note Timer trigger sources are dedicated to trigger output. Releasing a + * trigger source stops the timer, clears the trigger output when the HAL + * exposes a reset selector, and deinitializes the HAL TIM base state. It + * does not unregister the RT-Thread timer device object. + */ +static rt_err_t timer_trigger_release(rt_clock_timer_t *timer) +{ + struct stm32_clock_timer *timer_device; + TIM_HandleTypeDef *tim; + rt_err_t result = RT_EOK; + + timer_device = (struct stm32_clock_timer *)timer; + if (timer_device->time_device.parent.user_data == RT_NULL) + { + return -RT_EINVAL; + } + + tim = &timer_device->tim_handle; + + if (timer_trigger_stop(timer) != RT_EOK) + { + result = -RT_ERROR; + } + +#if defined(TIM_TRGO_RESET) + TIM_MasterConfigTypeDef master = {0}; + master.MasterOutputTrigger = TIM_TRGO_RESET; +#if defined(TIM_MASTERSLAVEMODE_DISABLE) + master.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; +#endif /* defined(TIM_MASTERSLAVEMODE_DISABLE) */ + if (HAL_TIMEx_MasterConfigSynchronization(tim, &master) != HAL_OK) + { + result = -RT_ERROR; + } +#endif /* defined(TIM_TRGO_RESET) */ + + if (HAL_TIM_Base_DeInit(tim) != HAL_OK) + { + result = -RT_ERROR; + } + + timer_device->trigger_event = CLOCK_TIMER_TRIGGER_EVENT_UPDATE; + timer_device->trigger_channel = 0U; + return result; +} + +#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */ + static rt_err_t timer_ctrl(rt_clock_timer_t *timer, rt_uint32_t cmd, void *arg) { TIM_HandleTypeDef *tim = RT_NULL; @@ -492,7 +976,6 @@ static rt_err_t timer_ctrl(rt_clock_timer_t *timer, rt_uint32_t cmd, void *arg) uint32_t pclk1_doubler, pclk2_doubler; RT_ASSERT(timer != RT_NULL); - RT_ASSERT(arg != RT_NULL); tim = (TIM_HandleTypeDef *)timer->parent.user_data; @@ -503,6 +986,12 @@ static rt_err_t timer_ctrl(rt_clock_timer_t *timer, rt_uint32_t cmd, void *arg) rt_uint32_t freq; rt_uint16_t val=0; + if (arg == RT_NULL) + { + result = -RT_EINVAL; + break; + } + /* set timer frequence */ freq = *((rt_uint32_t *)arg); @@ -581,6 +1070,33 @@ static rt_err_t timer_ctrl(rt_clock_timer_t *timer, rt_uint32_t cmd, void *arg) result = RT_EOK; } break; +#if defined(RT_USING_CLOCK_TIMER_TRIGGER) + case CLOCK_TIMER_CTRL_TRIGGER_CONFIG: + { + if (arg == RT_NULL) + { + result = -RT_EINVAL; + break; + } + result = timer_trigger_config(timer, (const struct rt_clock_timer_trigger_cfg *)arg); + } + break; + case CLOCK_TIMER_CTRL_TRIGGER_START: + { + result = timer_trigger_start(timer); + } + break; + case CLOCK_TIMER_CTRL_TRIGGER_STOP: + { + result = timer_trigger_stop(timer); + } + break; + case CLOCK_TIMER_CTRL_TRIGGER_RELEASE: + { + result = timer_trigger_release(timer); + } + break; +#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */ default: { result = -RT_EINVAL; diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index f613302d966..598cf87dfad 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -5,6 +5,7 @@ rsource "ipc/Kconfig" rsource "serial/Kconfig" rsource "can/Kconfig" +rsource "adc/Kconfig" rsource "clock_time/Kconfig" rsource "i2c/Kconfig" rsource "phy/Kconfig" diff --git a/components/drivers/adc/Kconfig b/components/drivers/adc/Kconfig new file mode 100644 index 00000000000..28d9ec47a00 --- /dev/null +++ b/components/drivers/adc/Kconfig @@ -0,0 +1,121 @@ +menuconfig RT_USING_ADC + bool "Using ADC device drivers" + default n + +if RT_USING_ADC + config RT_USING_ADC_V2 + bool "Using ADC V2 device drivers" + default n + help + Enable the standalone ADC V2 framework. ADC V2 uses the legacy ADC + public namespace, so it cannot be enabled together with ADC V1. + + config RT_USING_ADC_V1 + bool + default y if !RT_USING_ADC_V2 + +if RT_USING_DM && RT_USING_ADC_V1 + osource "$(SOC_DM_ADC_DIR)/Kconfig" +endif + +if RT_USING_ADC_V2 + + +config RT_ADC_USING_TRIGGER + bool "Enable ADC trigger framework" + default n + help + Enable device-level ADC trigger requests, framework validation, caching, + and stream lifecycle coordination. Timer trigger frequency and TRGO + start/stop are delegated to the timer trigger backend. + +config RT_ADC_TRIGGER_USING_TIMER + bool "Enable ADC timer trigger selector support" + depends on RT_ADC_USING_TRIGGER + default n + help + Enable timer update/TRGO and timer compare events as ADC stream + trigger sources. + +config RT_ADC_TRIGGER_USING_COMPARE + bool "Enable ADC analog comparator trigger selector support" + depends on RT_ADC_USING_TRIGGER + default n + help + Enable analog comparator output events as ADC stream trigger sources. + + +config RT_ADC_USING_STREAM + bool "Enable ADC stream framework" + default n + help + Enable long-running ADC stream sessions. + + Disable this option to remove ADC stream runtime state, stream APIs, + and stream backend hooks from the ADC V2 framework. + +if RT_ADC_USING_STREAM + +menu "ADC stream buffering policies" + +config RT_ADC_STREAM_USING_LATEST + bool "Enable ADC stream latest-frame policy" + default y + help + Enable the latest-frame ADC stream policy. + + This mode is intended for slow-changing or status-like ADC values, such + as battery voltage, temperature, potentiometer input, resistor-divider + voltage, or board health monitoring. + + The DMA buffer stores exactly one complete ADC scan frame. Old values + may be overwritten. This mode does not require DMA half-transfer or + transfer-complete data interrupts, and it does not allocate a framework + FIFO. + + This option may be enabled together with RT_ADC_STREAM_USING_FIFO. The + active policy is selected per stream at runtime. + +config RT_ADC_STREAM_USING_FIFO + bool "Enable ADC stream FIFO policy" + default n + help + Enable the FIFO ADC stream policy. + + This mode is intended for continuous and loss-sensitive sampling. The + DMA buffer is used as a staging buffer, and completed DMA data events + are copied into a ringbuffer for ordered blocking reads. + + FIFO mode requires DMA data events. The default DMA event mode uses both + half-transfer and transfer-complete events to reduce read latency. A + stream configuration may select full-only events to reduce interrupt + frequency, at the cost of higher latency and larger data bursts. + + This option may be enabled together with RT_ADC_STREAM_USING_LATEST. The + active policy is selected per stream at runtime. + +comment "At least one ADC stream buffering policy should be enabled" + depends on !RT_ADC_STREAM_USING_LATEST && !RT_ADC_STREAM_USING_FIFO + +endmenu + +endif + +config RT_ADC_V2_USING_MSH + bool "Enable ADC V2 MSH command" + depends on RT_USING_FINSH + default y + help + Enable the ADC V2 MSH command. + + This option exports the "adc" shell command for probing ADC devices, + configuring channels, reading raw samples, reading voltage values, and + reading one ADC sequence. When RT_ADC_USING_STREAM is enabled, stream + subcommands are also available. + + Disable this option to remove the ADC V2 shell command while keeping + the ADC V2 framework and driver APIs available. + +endif + +endif diff --git a/components/drivers/adc/SConscript b/components/drivers/adc/SConscript new file mode 100644 index 00000000000..94101138f0e --- /dev/null +++ b/components/drivers/adc/SConscript @@ -0,0 +1,23 @@ +from building import * + +cwd = GetCurrentDir() +src = [] +CPPPATH = [cwd + '/../include'] +group = [] + +if GetDepend(['RT_USING_ADC']) and not GetDepend(['RT_USING_ADC_V2']): + src += ['adc.c'] + +if GetDepend(['RT_USING_ADC_V2']): + src += ['adc_v2.c'] + +if GetDepend(['RT_USING_ADC_V2', 'RT_ADC_USING_TRIGGER']): + src += ['adc_v2_trigger.c'] + +if GetDepend(['RT_USING_ADC_V2', 'RT_USING_FINSH', 'RT_ADC_V2_USING_MSH']): + src += ['adc_v2_msh.c'] + +if len(src): + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_ADC'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/misc/adc.c b/components/drivers/adc/adc.c similarity index 100% rename from components/drivers/misc/adc.c rename to components/drivers/adc/adc.c diff --git a/components/drivers/adc/adc_v2.c b/components/drivers/adc/adc_v2.c new file mode 100644 index 00000000000..9ec3b6ac111 --- /dev/null +++ b/components/drivers/adc/adc_v2.c @@ -0,0 +1,1779 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add standalone adc v2 framework implementation + */ + +/** + * @file adc_v2.c + * @brief Standalone ADC V2 framework implementation. + */ + +#include + +#if defined(RT_USING_ADC_V2) + +#include +#include + +#define DBG_TAG "adc.v2" +#define DBG_LVL DBG_LOG +#include + +#include +#include "adc_v2_internal.h" + +/** + * @brief Get the current ADC framework state atomically. + * @param device Pointer to the ADC device object. + * @return Current ADC runtime state. + */ +enum rt_adc_state adc_get_state(rt_adc_device_t device) +{ + return (enum rt_adc_state)rt_atomic_load(&device->state); +} + +#if DBG_LVL >= DBG_LOG +/** + * @brief Convert one ADC framework state to a debug log string. + * @param state ADC runtime state. + * @return Constant state name string. + */ +static const char *adc_state_name(enum rt_adc_state state) +{ + switch (state) + { + case RT_ADC_STATE_IDLE: + return "IDLE"; + + case RT_ADC_STATE_LOCKED: + return "BUSY"; + +#ifdef RT_ADC_USING_STREAM + case RT_ADC_STATE_STREAM: + return "STREAM"; +#endif /* RT_ADC_USING_STREAM */ + + default: + return "UNKNOWN"; + } +} + +/** @brief ADC control command string table offset base. */ +#define RT_ADC_CMD_NAME_BASE RT_ADC_CMD_GET_RESOLUTION + +/** @brief ADC control command string table entry count. */ +#define RT_ADC_CMD_NAME_COUNT (RT_ADC_CMD_CLEAR_CHANNEL_CONFIG - RT_ADC_CMD_GET_RESOLUTION + 1) + +/** + * @brief ADC control command name table. + */ +static const char * const rt_adc_control_cmd_names[RT_ADC_CMD_NAME_COUNT] = +{ + [RT_ADC_CMD_GET_RESOLUTION - RT_ADC_CMD_NAME_BASE] = "GET_RESOLUTION", + [RT_ADC_CMD_CALIBRATE - RT_ADC_CMD_NAME_BASE] = "CALIBRATE", + [RT_ADC_CMD_SET_VREF - RT_ADC_CMD_NAME_BASE] = "SET_VREF", + [RT_ADC_CMD_CALC_VREF - RT_ADC_CMD_NAME_BASE] = "CALC_VREF", + [RT_ADC_CMD_GET_VREF_CHANNEL - RT_ADC_CMD_NAME_BASE] = "GET_VREF_CHANNEL", + [RT_ADC_CMD_SET_SESSION - RT_ADC_CMD_NAME_BASE] = "SET_SESSION", + [RT_ADC_CMD_SET_CONFIG - RT_ADC_CMD_NAME_BASE] = "SET_CONFIG", + [RT_ADC_CMD_GET_CONFIG - RT_ADC_CMD_NAME_BASE] = "GET_CONFIG", + [RT_ADC_CMD_CLEAR_CHANNEL_CONFIG - RT_ADC_CMD_NAME_BASE] = "CLEAR_CHANNEL_CONFIG", +}; + +/** + * @brief Get ADC control command name. + * @param cmd ADC control command identifier. + * @return ADC control command name string. + */ +static const char *rt_adc_control_cmd_name(int cmd) +{ + int index; + + index = cmd - RT_ADC_CMD_NAME_BASE; + if ((index < 0) || (index >= RT_ADC_CMD_NAME_COUNT) || (rt_adc_control_cmd_names[index] == RT_NULL)) + { + return "UNKNOWN"; + } + + return rt_adc_control_cmd_names[index]; +} + +#ifdef RT_ADC_USING_STREAM +/** + * @brief Convert one ADC stream policy to a debug log string. + * @param policy ADC stream buffering policy. + * @return Constant stream policy name string. + */ +static const char *adc_stream_policy_name(enum rt_adc_stream_policy policy) +{ + switch (policy) + { +#ifdef RT_ADC_STREAM_USING_LATEST + case RT_ADC_STREAM_POLICY_LATEST: + return "LATEST"; +#endif /* RT_ADC_STREAM_USING_LATEST */ + +#ifdef RT_ADC_STREAM_USING_FIFO + case RT_ADC_STREAM_POLICY_FIFO: + return "FIFO"; +#endif /* RT_ADC_STREAM_USING_FIFO */ + + default: + return "UNKNOWN"; + } +} +#endif /* RT_ADC_USING_STREAM */ + +#endif /* DBG_LVL >= DBG_LOG */ + +/** + * @brief Store one ADC framework state atomically. + * @param device Pointer to the ADC device object. + * @param state New ADC runtime state. + */ +static void adc_set_state(rt_adc_device_t device, enum rt_adc_state state) +{ + LOG_D("state set: device=%s state=%s", device->parent.parent.name, adc_state_name(state)); + rt_atomic_store(&device->state, (rt_atomic_t)state); +} + +/** + * @brief Clear the cached active ADC session configuration. + * @param device Pointer to the ADC device object. + */ +static void adc_clear_session_ctrl(rt_adc_device_t device) +{ + rt_memset(&device->session_ctrl, 0, sizeof(device->session_ctrl)); +} + +/** + * @brief Cache one ADC session while the caller owns the device BUSY state. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @return Operation status. + */ +static rt_err_t adc_cache_session_ctrl(rt_adc_device_t device, rt_uint32_t channels) +{ + rt_size_t channel_count; + + if ((device == RT_NULL) || (channels == 0U)) + { + return -RT_EINVAL; + } + + channel_count = rt_adc_channel_mask_count(channels); + if (channel_count == 0U) + { + return -RT_EINVAL; + } + + device->session_ctrl.channels = channels; + device->session_ctrl.channel_count = channel_count; + device->session_ctrl.configured = RT_TRUE; + + return RT_EOK; +} + +/** + * @brief Try to change the ADC framework state atomically. + * @param device Pointer to the ADC device object. + * @param expected Expected current ADC runtime state. + * @param target Target ADC runtime state. + * @return RT_TRUE if the state transition succeeded. + */ +static rt_bool_t adc_try_set_state(rt_adc_device_t device, enum rt_adc_state expected, enum rt_adc_state target) +{ + rt_atomic_t old_state; + rt_bool_t matched; + + old_state = (rt_atomic_t)expected; + matched = (rt_atomic_compare_exchange_strong(&device->state, &old_state, (rt_atomic_t)target) != 0) ? RT_TRUE : RT_FALSE; + if (matched == RT_TRUE) + { + LOG_D("state transition: device=%s %s -> %s", device->parent.parent.name, adc_state_name(expected), adc_state_name(target)); + } + else + { + LOG_W("state transition rejected: device=%s expected=%d actual=%d target=%d", device->parent.parent.name, (int)expected, (int)old_state, (int)target); + } + + return matched; +} + +/** + * @brief Apply one ADC conversion session to the backend driver. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @return Operation status. + */ +static rt_err_t adc_session_config(rt_adc_device_t device, rt_uint32_t channels) +{ + rt_size_t channel_count; + rt_err_t result; + + if ((device == RT_NULL) || (channels == 0U) || + (device->ops == RT_NULL) || (device->ops->core == RT_NULL) || + (device->ops->core->session_config == RT_NULL)) + { + return -RT_EINVAL; + } + + channel_count = rt_adc_channel_mask_count(channels); + LOG_D("session config: device=%s channels=0x%08x count=%d", + device->parent.parent.name, channels, channel_count); + + result = device->ops->core->session_config(device, channels); + if (result != RT_EOK) + { + goto fail; + } + + result = adc_cache_session_ctrl(device, channels); + if (result != RT_EOK) + { + goto fail; + } + + LOG_D("session configure done: device=%s", device->parent.parent.name); + return RT_EOK; + +fail: + adc_clear_session_ctrl(device); + LOG_E("session configure failed: device=%s result=%d", device->parent.parent.name, result); + + return result; +} + +/** + * @brief Get the raw sample index of one channel in a configured session. + * @param session_channels Configured ADC session channel mask. + * @param channel Single-channel mask to locate. + * @param index Pointer to the output raw sample index. + * @return Operation status. + */ +rt_err_t rt_adc_session_channel_index(rt_uint32_t session_channels, rt_uint32_t channel, rt_size_t *index) +{ + if ((index == RT_NULL) || (session_channels == 0U) || (rt_adc_channel_mask_count(channel) != 1U) || ((session_channels & channel) == 0U)) + { + return -RT_EINVAL; + } + + *index = rt_adc_channel_mask_count(session_channels & (channel - 1U)); + return RT_EOK; +} + +/** + * @brief Transfer ADC sequence samples after the session has been selected. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the sequence request object. + * @param sample_total Number of samples to read. + * @param read_count Pointer to the stored sample count. + * @return Operation status. + */ +static rt_err_t adc_sequence_transfer_locked(rt_adc_device_t device, rt_uint32_t channels, + const struct rt_adc_sequence_cfg *cfg, rt_size_t sample_total, rt_size_t *read_count) +{ + rt_err_t result; + rt_err_t stop_result; + rt_size_t index; + + *read_count = 0U; + result = device->ops->sequence->start(device, channels, cfg); + if (result != RT_EOK) + { + LOG_E("sequence start failed: device=%s result=%d", device->parent.parent.name, result); + return result; + } + + for (index = 0U; index < sample_total; index++) + { + result = device->ops->sequence->read(device, &cfg->buffer[index], cfg->timeout_ms); + if (result != RT_EOK) + { + LOG_E("sequence read failed: device=%s index=%u result=%d", + device->parent.parent.name, (unsigned int)index, result); + break; + } + + (*read_count)++; + } + + stop_result = device->ops->sequence->stop(device); + if (stop_result != RT_EOK) + { + LOG_E("sequence stop failed: device=%s result=%d", device->parent.parent.name, stop_result); + return (result != RT_EOK) ? result : stop_result; + } + + return result; +} + +/** + * @brief Open the ADC device. + * @param dev Pointer to the RT-Thread device object. + * @param oflag Open flags. + * @return Operation status. + */ +static rt_err_t adc_open_device(rt_device_t dev, rt_uint16_t oflag) +{ + rt_adc_device_t device; + rt_err_t result; + + RT_UNUSED(oflag); + + if (dev == RT_NULL) + { + return -RT_EINVAL; + } + + device = (rt_adc_device_t)dev; + if ((device->ops == RT_NULL) || (device->ops->core == RT_NULL) || + (device->ops->core->open == RT_NULL)) + { + return -RT_ENOSYS; + } + + if (adc_try_set_state(device, RT_ADC_STATE_IDLE, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + + LOG_D("open start: device=%s", device->parent.parent.name); + result = device->ops->core->open(device); + adc_set_state(device, RT_ADC_STATE_IDLE); + if (result == RT_EOK) + { + LOG_I("open done: device=%s", device->parent.parent.name); + } + else + { + LOG_E("open failed: device=%s result=%d", device->parent.parent.name, result); + } + return result; +} + +/** + * @brief Close the ADC device. + * @param dev Pointer to the RT-Thread device object. + * @return Operation status. + */ +static rt_err_t adc_close_device(rt_device_t dev) +{ + rt_adc_device_t device; + rt_err_t result; + + if (dev == RT_NULL) + { + return -RT_EINVAL; + } + + device = (rt_adc_device_t)dev; + if ((device->ops == RT_NULL) || (device->ops->core == RT_NULL) || (device->ops->core->close == RT_NULL)) + { + return -RT_ENOSYS; + } + +#ifdef RT_ADC_USING_STREAM + enum rt_adc_state state = adc_get_state(device); + if (state == RT_ADC_STATE_STREAM) + { + result = rt_adc_stream_stop(device); + if (result != RT_EOK) + { + LOG_E("stop stream before close failed: device=%s result=%d", device->parent.parent.name, result); + return result; + } + } + else if (state != RT_ADC_STATE_IDLE) + { + return -RT_EBUSY; + } +#endif /* RT_ADC_USING_STREAM */ + + if (adc_try_set_state(device, RT_ADC_STATE_IDLE, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + + LOG_D("close start: device=%s", device->parent.parent.name); + result = device->ops->core->close(device); + if (result == RT_EOK) + { + adc_clear_session_ctrl(device); + } + adc_set_state(device, RT_ADC_STATE_IDLE); + if (result == RT_EOK) + { + LOG_I("close done: device=%s", device->parent.parent.name); + } + else + { + LOG_E("close failed: device=%s result=%d", device->parent.parent.name, result); + } + return result; +} + +/** + * @brief Read ADC raw samples from the configured session. + * @param dev Pointer to the RT-Thread device object. + * @param pos Unused read position. + * @param buffer Pointer to the output sample buffer. + * @param size Output sample buffer length in samples. + * @return Number of samples read, or negative error code on failure. + * + * @note @p size must match the configured session channel count. The output + * order follows the ascending bit order of the configured channel mask. + */ +static rt_ssize_t adc_read_device(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + rt_adc_device_t device; + rt_uint32_t *values; + rt_err_t result; + + RT_UNUSED(pos); + + if ((dev == RT_NULL) || (buffer == RT_NULL)) + { + return -RT_EINVAL; + } + + device = (rt_adc_device_t)dev; + values = (rt_uint32_t *)buffer; + + if (adc_try_set_state(device, RT_ADC_STATE_IDLE, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + + if ((device->session_ctrl.configured != RT_TRUE) || (device->session_ctrl.channel_count == 0U) || + (size != device->session_ctrl.channel_count)) + { + result = -RT_EINVAL; + goto out; + } + + struct rt_adc_sequence_cfg sequence_cfg; + rt_size_t read_count; + + rt_memset(&sequence_cfg, 0, sizeof(sequence_cfg)); + sequence_cfg.buffer = values; + sequence_cfg.buffer_length = size; + sequence_cfg.timeout_ms = -1; + + result = adc_sequence_transfer_locked(device, device->session_ctrl.channels, + &sequence_cfg, size, &read_count); + if ((result == RT_EOK) && (read_count != size)) + { + result = -RT_ERROR; + } + +out: + adc_set_state(device, RT_ADC_STATE_IDLE); + + return (result == RT_EOK) ? (rt_ssize_t)size : (rt_ssize_t)result; +} + +/** + * @brief Handle ADC control commands. + * @param dev Pointer to the RT-Thread device object. + * @param cmd Control command. + * @param args Pointer to the control argument buffer. + * @return Operation status. + */ +static rt_err_t adc_control_device(rt_device_t dev, int cmd, void *args) +{ + rt_adc_device_t device; + rt_err_t result; + + if (dev == RT_NULL) + { + return -RT_EINVAL; + } + + device = (rt_adc_device_t)dev; + LOG_D("control request: device=%s cmd=%s(0x%x)", device->parent.parent.name, rt_adc_control_cmd_name(cmd), cmd); + switch (cmd) + { + case RT_ADC_CMD_GET_RESOLUTION: + case RT_ADC_CMD_GET_VREF_CHANNEL: + case RT_ADC_CMD_CALC_VREF: + case RT_ADC_CMD_CALIBRATE: + case RT_ADC_CMD_SET_CONFIG: + case RT_ADC_CMD_GET_CONFIG: + if ((device->ops == RT_NULL) || (device->ops->core == RT_NULL) || + (device->ops->core->control == RT_NULL)) + { + return -RT_ENOSYS; + } + if (adc_try_set_state(device, RT_ADC_STATE_IDLE, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + result = device->ops->core->control(device, cmd, args); + adc_set_state(device, RT_ADC_STATE_IDLE); + return result; + + case RT_ADC_CMD_CLEAR_CHANNEL_CONFIG: + if (args != RT_NULL) + { + return -RT_EINVAL; + } + + if ((dev->open_flag & RT_DEVICE_OFLAG_OPEN) == 0U) + { + return -RT_EIO; + } + + if ((device->ops == RT_NULL) || (device->ops->core == RT_NULL) || + (device->ops->core->control == RT_NULL)) + { + return -RT_ENOSYS; + } + + if (adc_try_set_state(device, RT_ADC_STATE_IDLE, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + + result = device->ops->core->control(device, cmd, RT_NULL); + if (result == RT_EOK) + { + adc_clear_session_ctrl(device); + } + + adc_set_state(device, RT_ADC_STATE_IDLE); + return result; + + case RT_ADC_CMD_SET_VREF: + if (args == RT_NULL) + { + return -RT_EINVAL; + } + + rt_uint32_t vref_mv = *((rt_uint32_t *)args); + if (vref_mv == 0U) + { + return -RT_EINVAL; + } + + if (adc_try_set_state(device, RT_ADC_STATE_IDLE, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + device->default_vref_mv = vref_mv; + LOG_I("fallback vref updated: %lu mV", (unsigned long)device->default_vref_mv); + adc_set_state(device, RT_ADC_STATE_IDLE); + return RT_EOK; + + case RT_ADC_CMD_SET_SESSION: + if (args == RT_NULL) + { + return -RT_EINVAL; + } + + if (adc_try_set_state(device, RT_ADC_STATE_IDLE, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + result = adc_session_config(device, *((const rt_uint32_t *)args)); + adc_set_state(device, RT_ADC_STATE_IDLE); + return result; + + default: + if ((device->ops == RT_NULL) || (device->ops->core == RT_NULL) || + (device->ops->core->control == RT_NULL)) + { + return -RT_ENOSYS; + } + if (adc_try_set_state(device, RT_ADC_STATE_IDLE, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + result = device->ops->core->control(device, cmd, args); + adc_set_state(device, RT_ADC_STATE_IDLE); + return result; + } +} + +#ifdef RT_USING_DEVICE_OPS +/** + * @brief ADC device-framework operation table. + */ +static const struct rt_device_ops adc_device_ops = { + RT_NULL, + adc_open_device, + adc_close_device, + adc_read_device, + RT_NULL, + adc_control_device, +}; +#endif /* RT_USING_DEVICE_OPS */ + +/** + * @brief Register an ADC device. + * @param device Pointer to the ADC device object. + * @param name Pointer to the device name string. + * @param ops Pointer to the ADC driver operation table. + * @param user_data Pointer to the driver private data. + * @return Operation status. + */ +rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const struct rt_adc_ops *ops, const void *user_data) +{ + rt_err_t result; + + if ((device == RT_NULL) || (name == RT_NULL) || (ops == RT_NULL) || + (ops->core == RT_NULL) || (ops->core->session_config == RT_NULL) || + (ops->sequence == RT_NULL) || (ops->sequence->start == RT_NULL) || + (ops->sequence->read == RT_NULL) || (ops->sequence->stop == RT_NULL)) + { + return -RT_EINVAL; + } + + device->parent.type = RT_Device_Class_ADC; + device->parent.rx_indicate = RT_NULL; + device->parent.tx_complete = RT_NULL; +#ifdef RT_USING_DEVICE_OPS + device->parent.ops = &adc_device_ops; +#else + device->parent.init = RT_NULL; + device->parent.open = adc_open_device; + device->parent.close = adc_close_device; + device->parent.read = adc_read_device; + device->parent.write = RT_NULL; + device->parent.control = adc_control_device; +#endif /* RT_USING_DEVICE_OPS */ + device->ops = ops; + rt_spin_lock_init(&device->spinlock); + rt_atomic_store(&device->state, (rt_atomic_t)RT_ADC_STATE_IDLE); + device->default_vref_mv = 0; + adc_clear_session_ctrl(device); +#if defined(RT_ADC_USING_TRIGGER) + adc_trigger_init(device); +#endif /* defined(RT_ADC_USING_TRIGGER) */ +#ifdef RT_ADC_USING_STREAM + rt_memset(&device->stream_ctrl, 0, sizeof(device->stream_ctrl)); +#endif /* RT_ADC_USING_STREAM */ + device->parent.user_data = (void *)user_data; + + result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); + if (result == RT_EOK) + { + LOG_I("device registered: %s", name); + } + else + { + LOG_E("device register failed: %s result=%d", name, result); + } + + return result; +} + +/** + * @brief Read one validated ADC sequence while the caller owns the device state. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the validated sequence request object. + * @param keep_state_on_success Whether to keep BUSY state after a successful read. + * @param read_count Pointer to the stored sample count. + * @return Operation status. + * + * @note A synchronous sequence request reads one scan frame only. Partial + * samples are reported through @p read_count when a read error or timeout + * happens after at least one sample is stored. + */ +static rt_err_t adc_read_sequence_locked(rt_adc_device_t device, rt_uint32_t channels, + const struct rt_adc_sequence_cfg *cfg, rt_bool_t keep_state_on_success, rt_size_t *read_count) +{ + rt_err_t result; + rt_size_t channel_count; + + *read_count = 0U; + channel_count = rt_adc_channel_mask_count(channels); + + result = adc_session_config(device, channels); + if (result != RT_EOK) + { + LOG_E("sequence config failed: device=%s result=%d", device->parent.parent.name, result); + adc_set_state(device, RT_ADC_STATE_IDLE); + return result; + } + + result = adc_sequence_transfer_locked(device, channels, cfg, channel_count, read_count); + + if ((result != RT_EOK) || (keep_state_on_success != RT_TRUE)) + { + adc_set_state(device, RT_ADC_STATE_IDLE); + } + + return result; +} + +/** + * @brief Read one ADC sequence frame. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the sequence request object. + * @param read_count Pointer to the stored sample count. + * @return Operation status. + */ +rt_err_t rt_adc_read_sequence(rt_adc_device_t device, rt_uint32_t channels, + const struct rt_adc_sequence_cfg *cfg, rt_size_t *read_count) +{ + rt_size_t channel_count; + + if ((device == RT_NULL) || (cfg == RT_NULL) || (cfg->buffer == RT_NULL) || + (read_count == RT_NULL) || (channels == 0U) || + (device->ops == RT_NULL) || (device->ops->sequence == RT_NULL) || (device->ops->sequence->start == RT_NULL) || + (device->ops->sequence->read == RT_NULL) || (device->ops->sequence->stop == RT_NULL)) + { + return -RT_EINVAL; + } + + *read_count = 0U; + channel_count = rt_adc_channel_mask_count(channels); + if ((channel_count == 0U) || (cfg->buffer_length < channel_count)) + { + return -RT_EINVAL; + } + + if (adc_try_set_state(device, RT_ADC_STATE_IDLE, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + + return adc_read_sequence_locked(device, channels, cfg, RT_FALSE, read_count); +} + + +#ifdef RT_ADC_USING_STREAM +/** + * @brief Check whether an ADC stream policy is enabled by configuration. + * @param policy ADC stream buffering policy. + * @return RT_TRUE if the policy is supported, otherwise RT_FALSE. + */ +static rt_bool_t adc_stream_policy_is_supported(enum rt_adc_stream_policy policy) +{ + switch (policy) + { +#ifdef RT_ADC_STREAM_USING_LATEST + case RT_ADC_STREAM_POLICY_LATEST: + return RT_TRUE; +#endif /* RT_ADC_STREAM_USING_LATEST */ +#ifdef RT_ADC_STREAM_USING_FIFO + case RT_ADC_STREAM_POLICY_FIFO: + return RT_TRUE; +#endif /* RT_ADC_STREAM_USING_FIFO */ + default: + return RT_FALSE; + } +} + +/** + * @brief Resolve the effective DMA data event mode for one stream request. + * @param policy Active stream buffering policy. + * @param request Requested DMA event mode. + * @param effective Pointer to the output effective event mode. + * @return Operation status. + */ +static rt_err_t adc_stream_resolve_dma_event_mode(enum rt_adc_stream_policy policy, + enum rt_adc_stream_dma_event_mode request, + enum rt_adc_stream_dma_event_mode *effective) +{ + if (request == RT_ADC_STREAM_DMA_EVENT_AUTO) + { +#ifdef RT_ADC_STREAM_USING_LATEST + if (policy == RT_ADC_STREAM_POLICY_LATEST) + { + *effective = RT_ADC_STREAM_DMA_EVENT_NONE; + return RT_EOK; + } +#endif /* RT_ADC_STREAM_USING_LATEST */ +#ifdef RT_ADC_STREAM_USING_FIFO + if (policy == RT_ADC_STREAM_POLICY_FIFO) + { + *effective = RT_ADC_STREAM_DMA_EVENT_HALF_FULL; + return RT_EOK; + } +#endif /* RT_ADC_STREAM_USING_FIFO */ + return -RT_ENOSYS; + } + +#ifdef RT_ADC_STREAM_USING_FIFO + if ((policy == RT_ADC_STREAM_POLICY_FIFO) && (request == RT_ADC_STREAM_DMA_EVENT_NONE)) + { + return -RT_EINVAL; + } +#endif /* RT_ADC_STREAM_USING_FIFO */ + + if ((request != RT_ADC_STREAM_DMA_EVENT_NONE) && + (request != RT_ADC_STREAM_DMA_EVENT_FULL_ONLY) && + (request != RT_ADC_STREAM_DMA_EVENT_HALF_FULL)) + { + return -RT_EINVAL; + } + + *effective = request; + return RT_EOK; +} + +/** + * @brief Reset one ADC stream runtime control block. + * @param ctrl Pointer to the stream control block. + */ +static void adc_stream_ctrl_reset(struct rt_adc_stream_ctrl *ctrl) +{ + rt_memset(ctrl, 0, sizeof(*ctrl)); +} + +#ifdef RT_ADC_STREAM_USING_FIFO +/** + * @brief Wake FIFO stream readers when the active stream owns a FIFO. + * @param ctrl Pointer to the stream control block. + */ +static void adc_stream_fifo_wakeup(struct rt_adc_stream_ctrl *ctrl) +{ + if ((ctrl->policy == RT_ADC_STREAM_POLICY_FIFO) && (ctrl->fifo_enabled == RT_TRUE)) + { + rt_completion_done(&ctrl->rx_cpt); + } +} +#endif /* RT_ADC_STREAM_USING_FIFO */ + +/** + * @brief Validate a stream request and initialize the stream control block. + * @param device Pointer to the ADC device object. + * @param cfg Pointer to the stream configuration object. + * @param frame_length Samples in one ADC scan frame. + * @return Operation status. + */ +static rt_err_t adc_stream_ctrl_configure(rt_adc_device_t device, const struct rt_adc_stream_cfg *cfg, rt_size_t frame_length) +{ + struct rt_adc_stream_ctrl *ctrl; + enum rt_adc_stream_dma_event_mode dma_event_mode; + rt_err_t result; + + if ((cfg->dma_buffer == RT_NULL) || (cfg->dma_buffer_length == 0U) || (frame_length == 0U) || + (adc_stream_policy_is_supported(cfg->policy) != RT_TRUE)) + { + LOG_E("stream ctrl config invalid args: device=%s buffer=%p len=%u frame=%u", + device->parent.parent.name, cfg->dma_buffer, (unsigned int)cfg->dma_buffer_length, (unsigned int)frame_length); + return -RT_EINVAL; + } + + result = adc_stream_resolve_dma_event_mode(cfg->policy, cfg->dma_event_mode, &dma_event_mode); + if (result != RT_EOK) + { + LOG_E("stream ctrl config invalid event mode: device=%s policy=%d mode=%d", + device->parent.parent.name, (int)cfg->policy, (int)cfg->dma_event_mode); + return result; + } + + LOG_D("stream ctrl config start: device=%s policy=%s frame=%u dma=%u event_mode=%d", + device->parent.parent.name, adc_stream_policy_name(cfg->policy), + (unsigned int)frame_length, (unsigned int)cfg->dma_buffer_length, (int)dma_event_mode); + ctrl = &device->stream_ctrl; + adc_stream_ctrl_reset(ctrl); + +#ifdef RT_ADC_STREAM_USING_LATEST + if (cfg->policy == RT_ADC_STREAM_POLICY_LATEST) + { + if (cfg->dma_buffer_length != frame_length) + { + LOG_E("latest stream invalid length: device=%s dma=%u frame=%u", + device->parent.parent.name, (unsigned int)cfg->dma_buffer_length, (unsigned int)frame_length); + return -RT_EINVAL; + } + + ctrl->active = RT_TRUE; + ctrl->policy = cfg->policy; + ctrl->dma_event_mode = dma_event_mode; + ctrl->dma_buffer = cfg->dma_buffer; + ctrl->dma_buffer_length = cfg->dma_buffer_length; + ctrl->frame_length = frame_length; + LOG_D("latest stream configured: device=%s frame=%u", device->parent.parent.name, (unsigned int)frame_length); + return RT_EOK; + } +#endif /* RT_ADC_STREAM_USING_LATEST */ + +#ifdef RT_ADC_STREAM_USING_FIFO + if (cfg->policy == RT_ADC_STREAM_POLICY_FIFO) + { + if ((cfg->fifo_buffer == RT_NULL) || (cfg->fifo_buffer_length == 0U)) + { + LOG_E("fifo stream invalid fifo buffer: device=%s len=%u", + device->parent.parent.name, (unsigned int)cfg->fifo_buffer_length); + return -RT_EINVAL; + } + + if ((cfg->watermark != 0U) && (cfg->watermark > cfg->fifo_buffer_length)) + { + LOG_E("fifo stream invalid watermark: device=%s watermark=%u fifo=%u", + device->parent.parent.name, (unsigned int)cfg->watermark, (unsigned int)cfg->fifo_buffer_length); + return -RT_EINVAL; + } + + if (cfg->dma_buffer_length < frame_length) + { + LOG_E("fifo stream invalid dma length: device=%s dma=%u frame=%u", + device->parent.parent.name, (unsigned int)cfg->dma_buffer_length, (unsigned int)frame_length); + return -RT_EINVAL; + } + + /* The default FIFO start path accepts generic DMA staging buffers and + * reports runtime overflow through last_error. Use + * rt_adc_stream_start_frame_aligned_fifo() when the caller requires a DMA + * data-event block layout that never splits ADC scan frames. + */ + ctrl->active = RT_TRUE; + ctrl->policy = cfg->policy; + ctrl->dma_event_mode = dma_event_mode; + ctrl->dma_buffer = cfg->dma_buffer; + ctrl->dma_buffer_length = cfg->dma_buffer_length; + ctrl->frame_length = frame_length; + ctrl->watermark = cfg->watermark; + ctrl->callback = cfg->callback; + ctrl->user_data = cfg->user_data; + ctrl->overflow_count = 0U; + rt_atomic_store(&ctrl->last_error, (rt_atomic_t)RT_EOK); + rt_ringbuffer_init(&ctrl->fifo, (rt_uint8_t *)cfg->fifo_buffer, (rt_int32_t)(cfg->fifo_buffer_length * sizeof(rt_uint32_t))); + rt_completion_init(&ctrl->rx_cpt); + ctrl->fifo_enabled = RT_TRUE; + LOG_D("fifo stream configured: device=%s frame=%u dma=%u fifo=%u watermark=%u event_mode=%d", + device->parent.parent.name, (unsigned int)frame_length, (unsigned int)cfg->dma_buffer_length, + (unsigned int)cfg->fifo_buffer_length, (unsigned int)cfg->watermark, (int)dma_event_mode); + return RT_EOK; + } +#endif /* RT_ADC_STREAM_USING_FIFO */ + + LOG_E("stream policy unsupported: device=%s policy=%d", device->parent.parent.name, (int)cfg->policy); + return -RT_ENOSYS; +} + +#ifdef RT_ADC_STREAM_USING_LATEST +/** + * @brief Read the latest ADC rank values from the DMA buffer. + * @param device Pointer to the ADC device object. + * @param buffer Pointer to the destination sample buffer. + * @param sample_count Destination buffer length in samples. + * @param timeout_ms Unused timeout parameter. + * @return Number of samples read, or a negative RT-Thread error code. + * + * @note Latest mode is a lockless DMA-buffer view. CPU-side atomic operations, + * spin locks, mutexes, or read-write locks cannot prevent the DMA engine + * from updating memory concurrently, because DMA does not participate in + * CPU locking protocols. This mode only guarantees that each buffer index + * maps to the corresponding ADC rank latest value; it does not guarantee + * that the copied frame is a single hardware scan-cycle snapshot. Use FIFO + * mode when ordered and frame-accurate samples are required. + */ +static rt_ssize_t rt_adc_stream_read_latest(rt_adc_device_t device, rt_uint32_t *buffer, + rt_size_t sample_count, rt_int32_t timeout_ms) +{ + struct rt_adc_stream_ctrl *ctrl; + rt_err_t result; + + RT_UNUSED(timeout_ms); + + ctrl = &device->stream_ctrl; + if (sample_count < ctrl->frame_length) + { + LOG_E("latest read buffer too small: device=%s samples=%u frame=%u", + device->parent.parent.name, (unsigned int)sample_count, (unsigned int)ctrl->frame_length); + return -RT_EINVAL; + } + + result = (rt_err_t)rt_atomic_load(&ctrl->last_error); + if (result != RT_EOK) + { + return result; + } + + if ((device->ops != RT_NULL) && (device->ops->stream != RT_NULL) && (device->ops->stream->sync != RT_NULL)) + { + result = device->ops->stream->sync(device, ctrl->dma_buffer, ctrl->frame_length); + if (result != RT_EOK) + { + return result; + } + } + + result = (rt_err_t)rt_atomic_load(&ctrl->last_error); + if (result != RT_EOK) + { + return result; + } + + rt_memcpy(buffer, ctrl->dma_buffer, ctrl->frame_length * sizeof(rt_uint32_t)); + return (rt_ssize_t)ctrl->frame_length; +} +#endif /* RT_ADC_STREAM_USING_LATEST */ + +#ifdef RT_ADC_STREAM_USING_FIFO +/** + * @brief Read ordered ADC samples from the framework FIFO. + * @param device Pointer to the ADC device object. + * @param buffer Pointer to the destination sample buffer. + * @param sample_count Number of samples to read before returning unless timeout or error occurs. + * @param timeout_ms Total read timeout in milliseconds; negative means wait forever. + * @return Number of samples read, or a negative RT-Thread error code. + * @note In blocking mode, this function waits until the requested sample count is read or timeout occurs. + * On timeout, the partial sample count is returned if any samples were read. + */ +static rt_ssize_t rt_adc_stream_read_fifo(rt_adc_device_t device, rt_uint32_t *buffer, rt_size_t sample_count, rt_int32_t timeout_ms) +{ + struct rt_adc_stream_ctrl *ctrl; + rt_size_t read_count; + rt_tick_t timeout_tick; + rt_tick_t begin_tick; + + ctrl = &device->stream_ctrl; + read_count = 0U; + timeout_tick = (timeout_ms < 0) ? RT_WAITING_FOREVER : rt_tick_from_millisecond(timeout_ms); + begin_tick = rt_tick_get(); + + while (read_count < sample_count) + { + enum rt_adc_state state; + rt_base_t level; + rt_size_t got; + rt_err_t result; + rt_tick_t wait_tick; + + state = adc_get_state(device); + if (state != RT_ADC_STATE_STREAM) + { + return (read_count > 0U) ? (rt_ssize_t)read_count : ((state == RT_ADC_STATE_IDLE) ? -RT_EINVAL : -RT_EBUSY); + } + + level = rt_spin_lock_irqsave(&device->spinlock); + got = rt_ringbuffer_get(&ctrl->fifo, (rt_uint8_t *)&buffer[read_count], + (rt_uint32_t)((sample_count - read_count) * sizeof(rt_uint32_t))); + rt_spin_unlock_irqrestore(&device->spinlock, level); + + read_count += got / sizeof(rt_uint32_t); + if (read_count >= sample_count) + { + return (rt_ssize_t)read_count; + } + + result = (rt_err_t)rt_atomic_load(&ctrl->last_error); + if (result != RT_EOK) + { + return result; + } + + if (timeout_ms == RT_WAITING_NO) + { + return (read_count > 0U) ? (rt_ssize_t)read_count : -RT_ETIMEOUT; + } + + if (timeout_ms < 0) + { + wait_tick = RT_WAITING_FOREVER; + } + else + { + rt_tick_t delta_tick; + + delta_tick = rt_tick_get_delta(begin_tick); + if (delta_tick >= timeout_tick) + { + return (read_count > 0U) ? (rt_ssize_t)read_count : -RT_ETIMEOUT; + } + + wait_tick = timeout_tick - delta_tick; + } + + if (rt_completion_wait(&ctrl->rx_cpt, wait_tick) != RT_EOK) + { + return (read_count > 0U) ? (rt_ssize_t)read_count : -RT_ETIMEOUT; + } + } + + return (rt_ssize_t)read_count; +} +#endif /* RT_ADC_STREAM_USING_FIFO */ + +/** + * @brief Start one ADC stream session. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the stream configuration object. + * @return Operation status. + */ +rt_err_t rt_adc_stream_start(rt_adc_device_t device, rt_uint32_t channels, const struct rt_adc_stream_cfg *cfg) +{ + rt_size_t frame_length; + rt_err_t result; + rt_bool_t start_called; + + if ((device == RT_NULL) || (cfg == RT_NULL) || (channels == 0U)) + { + return -RT_EINVAL; + } + + if ((device->ops == RT_NULL) || (device->ops->stream == RT_NULL) || + (device->ops->stream->start == RT_NULL) || (device->ops->stream->stop == RT_NULL)) + { + return -RT_ENOSYS; + } + + if (adc_try_set_state(device, RT_ADC_STATE_IDLE, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + start_called = RT_FALSE; +#if defined(RT_ADC_USING_TRIGGER) + rt_bool_t trigger_started = RT_FALSE; +#endif /* defined(RT_ADC_USING_TRIGGER) */ + + frame_length = rt_adc_channel_mask_count(channels); + result = adc_cache_session_ctrl(device, channels); + if (result != RT_EOK) + { + goto fail_after_lock; + } + + result = adc_stream_ctrl_configure(device, cfg, frame_length); + if (result != RT_EOK) + { + goto fail_after_lock; + } + +#if defined(RT_ADC_USING_TRIGGER) + result = adc_trigger_preconfig(device); + if (result != RT_EOK) + { + goto fail_after_lock; + } +#endif /* defined(RT_ADC_USING_TRIGGER) */ + + start_called = RT_TRUE; + result = device->ops->stream->start(device, channels, cfg); + if (result != RT_EOK) + { + goto fail_after_lock; + } + + result = (rt_err_t)rt_atomic_load(&device->stream_ctrl.last_error); + if (result != RT_EOK) + { + goto fail_after_lock; + } + +#if defined(RT_ADC_USING_TRIGGER) + result = adc_trigger_source_control(device, ADC_TRIGGER_SOURCE_START, &trigger_started, RT_EOK); + if (result != RT_EOK) + { + goto fail_after_lock; + } +#endif /* defined(RT_ADC_USING_TRIGGER) */ + + adc_set_state(device, RT_ADC_STATE_STREAM); + return RT_EOK; + +fail_after_lock: + if(result != RT_EOK) + { + LOG_E("stream start failed: device=%s result=%d", device->parent.parent.name, result); + } +#if defined(RT_ADC_USING_TRIGGER) + result = adc_trigger_source_control(device, ADC_TRIGGER_SOURCE_STOP, &trigger_started, result); +#endif /* defined(RT_ADC_USING_TRIGGER) */ + + if (start_called == RT_TRUE) + { + rt_err_t stop_result; + rt_bool_t hardware_stopped; + + hardware_stopped = RT_FALSE; + stop_result = device->ops->stream->stop(device, &hardware_stopped); + if ((stop_result != RT_EOK) && (hardware_stopped != RT_TRUE)) + { + adc_set_state(device, RT_ADC_STATE_STREAM); + return stop_result; + } + } + + adc_stream_ctrl_reset(&device->stream_ctrl); + adc_clear_session_ctrl(device); + adc_set_state(device, RT_ADC_STATE_IDLE); + return result; +} + +#ifdef RT_ADC_STREAM_USING_FIFO +/** + * @brief Start a FIFO ADC stream with strict frame-aligned buffer layout. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the stream configuration object. + * @return Operation status. + * + * @note This helper is intended for continuous FIFO sampling where DMA + * data-event blocks must not split ADC scan frames. It validates that + * each DMA event block contains complete frames and that the FIFO can + * accept at least one complete event block. + * @note Passing this validation does not prove that samples can never be lost. + * The reader must still drain the FIFO fast enough for the selected + * sample rate and scheduler latency. Runtime overflow is still reported + * through the stream error state. + */ +rt_err_t rt_adc_stream_start_frame_aligned_fifo(rt_adc_device_t device, rt_uint32_t channels, const struct rt_adc_stream_cfg *cfg) +{ + rt_size_t frame_length; + rt_size_t block_length; + enum rt_adc_stream_dma_event_mode dma_event_mode; + rt_err_t result; + + if ((device == RT_NULL) || (cfg == RT_NULL) || (channels == 0U) || + (cfg->policy != RT_ADC_STREAM_POLICY_FIFO) || + (cfg->dma_buffer == RT_NULL) || (cfg->dma_buffer_length == 0U) || + (cfg->fifo_buffer == RT_NULL) || (cfg->fifo_buffer_length == 0U)) + { + return -RT_EINVAL; + } + + frame_length = rt_adc_channel_mask_count(channels); + if (frame_length == 0U) + { + return -RT_EINVAL; + } + + result = adc_stream_resolve_dma_event_mode(cfg->policy, cfg->dma_event_mode, &dma_event_mode); + if (result != RT_EOK) + { + return result; + } + + block_length = (dma_event_mode == RT_ADC_STREAM_DMA_EVENT_FULL_ONLY) ? cfg->dma_buffer_length : (cfg->dma_buffer_length / 2U); + if ((cfg->dma_buffer_length < frame_length) || /* DMA buffer must contain at least one complete scan frame. */ + ((cfg->dma_buffer_length % frame_length) != 0U) || /* DMA buffer length must be aligned to complete scan frames. */ + (block_length == 0U) || /* The selected DMA event mode must produce a non-empty staging block. */ + ((block_length % frame_length) != 0U) || /* Each staging block copied to FIFO must contain complete scan frames only. */ + (cfg->fifo_buffer_length < block_length) || /* FIFO must be able to store at least one completed DMA staging block. */ + ((cfg->fifo_buffer_length % frame_length) != 0U)) /* FIFO capacity must also be aligned to complete scan frames. */ + { + LOG_E("frame-aligned fifo stream invalid layout: device=%s dma=%u block=%u frame=%u fifo=%u", + device->parent.parent.name, (unsigned int)cfg->dma_buffer_length, + (unsigned int)block_length, (unsigned int)frame_length, + (unsigned int)cfg->fifo_buffer_length); + return -RT_EINVAL; + } + + if ((dma_event_mode == RT_ADC_STREAM_DMA_EVENT_HALF_FULL) && ((cfg->dma_buffer_length % 2U) != 0U)) + { + return -RT_EINVAL; + } + + return rt_adc_stream_start(device, channels, cfg); +} +#endif /* RT_ADC_STREAM_USING_FIFO */ + +/** + * @brief Read converted samples from an active ADC stream session. + * @param device Pointer to the ADC device object. + * @param buffer Pointer to the destination sample buffer. + * @param sample_count Number of samples to read. + * @param timeout_ms Read timeout in milliseconds; negative means wait forever. + * @return Number of samples read, or a negative RT-Thread error code. + */ +rt_ssize_t rt_adc_stream_read(rt_adc_device_t device, rt_uint32_t *buffer, rt_size_t sample_count, rt_int32_t timeout_ms) +{ + struct rt_adc_stream_ctrl *ctrl; + rt_ssize_t read_count; + + if ((device == RT_NULL) || (buffer == RT_NULL) || (sample_count == 0U)) + { + return -RT_EINVAL; + } + + if (adc_get_state(device) != RT_ADC_STATE_STREAM) + { + return -RT_EINVAL; + } + + ctrl = &device->stream_ctrl; + switch (ctrl->policy) + { +#ifdef RT_ADC_STREAM_USING_LATEST + case RT_ADC_STREAM_POLICY_LATEST: + read_count = rt_adc_stream_read_latest(device, buffer, sample_count, timeout_ms); + break; +#endif /* RT_ADC_STREAM_USING_LATEST */ +#ifdef RT_ADC_STREAM_USING_FIFO + case RT_ADC_STREAM_POLICY_FIFO: + read_count = rt_adc_stream_read_fifo(device, buffer, sample_count, timeout_ms); + break; +#endif /* RT_ADC_STREAM_USING_FIFO */ + default: + read_count = -RT_EINVAL; + break; + } + + return read_count; +} + +/** + * @brief Cancel a blocked ADC stream reader before stream shutdown. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ +rt_err_t rt_adc_stream_cancel(rt_adc_device_t device) +{ + struct rt_adc_stream_ctrl *ctrl; + rt_atomic_t old_error; + enum rt_adc_state state; + + if (device == RT_NULL) + { + return -RT_EINVAL; + } + + state = adc_get_state(device); + if (state != RT_ADC_STATE_STREAM) + { + return (state == RT_ADC_STATE_IDLE) ? -RT_EINVAL : -RT_EBUSY; + } + + ctrl = &device->stream_ctrl; + old_error = (rt_atomic_t)RT_EOK; + (void)rt_atomic_compare_exchange_strong(&ctrl->last_error, &old_error, (rt_atomic_t)-RT_EINTR); + +#ifdef RT_ADC_STREAM_USING_FIFO + adc_stream_fifo_wakeup(ctrl); +#endif /* RT_ADC_STREAM_USING_FIFO */ + + return RT_EOK; +} + +/** + * @brief Stop one ADC stream session. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ +rt_err_t rt_adc_stream_stop(rt_adc_device_t device) +{ + rt_bool_t hardware_stopped; + rt_err_t result; + rt_err_t trigger_result; + enum rt_adc_state state; + + if (device == RT_NULL) + { + return -RT_EINVAL; + } + + if ((device->ops == RT_NULL) || (device->ops->stream == RT_NULL) || (device->ops->stream->stop == RT_NULL)) + { + return -RT_ENOSYS; + } + + state = adc_get_state(device); + if (state == RT_ADC_STATE_IDLE) + { + return RT_EOK; + } + if (state != RT_ADC_STATE_STREAM) + { + return -RT_EBUSY; + } + + if (adc_try_set_state(device, RT_ADC_STATE_STREAM, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + +#if defined(RT_ADC_USING_TRIGGER) + rt_bool_t trigger_started = RT_TRUE; + trigger_result = adc_trigger_source_control(device, ADC_TRIGGER_SOURCE_STOP, &trigger_started, RT_EOK); +#else + trigger_result = RT_EOK; +#endif /* defined(RT_ADC_USING_TRIGGER) */ + + hardware_stopped = RT_FALSE; + result = device->ops->stream->stop(device, &hardware_stopped); + if ((result == RT_EOK) && (trigger_result != RT_EOK)) + { + result = trigger_result; + } + + if ((result == RT_EOK) || (hardware_stopped == RT_TRUE)) + { +#ifdef RT_ADC_STREAM_USING_FIFO + rt_atomic_store(&device->stream_ctrl.last_error, (rt_atomic_t)((result == RT_EOK) ? -RT_EINVAL : result)); + adc_stream_fifo_wakeup(&device->stream_ctrl); + device->stream_ctrl.fifo_enabled = RT_FALSE; +#endif /* RT_ADC_STREAM_USING_FIFO */ + adc_stream_ctrl_reset(&device->stream_ctrl); + adc_clear_session_ctrl(device); + adc_set_state(device, RT_ADC_STATE_IDLE); + } + else + { + adc_set_state(device, RT_ADC_STATE_STREAM); + } + + return result; +} + +/** + * @brief ADC stream ISR event handler used by low-level drivers. + * @param device Pointer to the ADC device object. + * @param event Stream event. + * @param sample_buffer Pointer to the completed DMA sample block. + * @param sample_count Completed sample count. + * @return Operation status. + */ +rt_err_t rt_hw_adc_stream_isr(rt_adc_device_t device, enum rt_adc_stream_event event, + const rt_uint32_t *sample_buffer, rt_size_t sample_count) +{ + struct rt_adc_stream_ctrl *ctrl; + enum rt_adc_state state; +#ifdef RT_ADC_STREAM_USING_FIFO + const rt_uint8_t *src; + rt_size_t bytes; + rt_size_t put_len; + rt_size_t data_len; + rt_base_t level; +#endif /* RT_ADC_STREAM_USING_FIFO */ + + if (device == RT_NULL) + { + return -RT_EINVAL; + } + + ctrl = &device->stream_ctrl; + if (event == RT_ADC_STREAM_EVENT_ERROR) + { + rt_atomic_t old_error; + + old_error = (rt_atomic_t)RT_EOK; + if (rt_atomic_compare_exchange_strong(&ctrl->last_error, &old_error, (rt_atomic_t)-RT_ERROR) == RT_TRUE) + { + LOG_W("stream error: device=%s event=%d", device->parent.parent.name, event); + } +#ifdef RT_ADC_STREAM_USING_FIFO + adc_stream_fifo_wakeup(ctrl); +#endif /* RT_ADC_STREAM_USING_FIFO */ + return RT_EOK; + } + + state = adc_get_state(device); +#ifdef RT_ADC_STREAM_USING_FIFO + if ((state != RT_ADC_STATE_STREAM) && !((state == RT_ADC_STATE_LOCKED) && (ctrl->fifo_enabled == RT_TRUE))) + { + return RT_EOK; + } +#else + if (state != RT_ADC_STATE_STREAM) + { + return RT_EOK; + } +#endif /* RT_ADC_STREAM_USING_FIFO */ + + if ((event != RT_ADC_STREAM_EVENT_DMA_HALF) && (event != RT_ADC_STREAM_EVENT_DMA_DONE)) + { + return -RT_EINVAL; + } + + if ((rt_err_t)rt_atomic_load(&ctrl->last_error) != RT_EOK) + { + return RT_EOK; + } + +#ifdef RT_ADC_STREAM_USING_FIFO + if ((ctrl->policy != RT_ADC_STREAM_POLICY_FIFO) || (ctrl->fifo_enabled != RT_TRUE)) + { + return RT_EOK; + } + + if ((sample_buffer == RT_NULL) || (sample_count == 0U)) + { + return -RT_EINVAL; + } + + src = (const rt_uint8_t *)sample_buffer; + bytes = sample_count * sizeof(rt_uint32_t); + + level = rt_spin_lock_irqsave(&device->spinlock); + put_len = rt_ringbuffer_put(&ctrl->fifo, src, (rt_uint32_t)bytes); + data_len = rt_ringbuffer_data_len(&ctrl->fifo); + rt_spin_unlock_irqrestore(&device->spinlock, level); + + if (put_len < bytes) + { + rt_atomic_t old_error; + ctrl->overflow_count++; + old_error = (rt_atomic_t)RT_EOK; + if (rt_atomic_compare_exchange_strong(&ctrl->last_error, &old_error, (rt_atomic_t)-RT_EFULL) == RT_TRUE) + { + LOG_W("stream fifo overflow: device=%s put=%u expected=%u data_len=%u", + device->parent.parent.name, (unsigned int)put_len, (unsigned int)bytes, (unsigned int)data_len); + } + adc_stream_fifo_wakeup(ctrl); + } + + if ((put_len > 0U) && ((ctrl->watermark == 0U) || (data_len >= (ctrl->watermark * sizeof(rt_uint32_t))))) + { + adc_stream_fifo_wakeup(ctrl); + + if (ctrl->callback != RT_NULL) + { + ctrl->callback(device, put_len / sizeof(rt_uint32_t), ctrl->user_data); + } + } + + return RT_EOK; +#else + RT_UNUSED(sample_buffer); + RT_UNUSED(sample_count); + return RT_EOK; +#endif /* RT_ADC_STREAM_USING_FIFO */ +} +#endif /* RT_ADC_USING_STREAM */ + +/** + * @brief Convert one ADC raw sample to millivolts. + * @param raw_value Raw ADC sample code. + * @param vref_mv ADC reference voltage in millivolts. + * @param resolution_bits ADC resolution in bits. + * @param voltage_mv Pointer to the output voltage in millivolts. + * @return Operation status. + * + * ADC codes are treated as an inclusive range from 0 to + * ``(1 << resolution_bits) - 1``. The calculation uses a 64-bit + * intermediate value and rounds to the nearest integer millivolt. + */ +rt_err_t rt_adc_raw_to_voltage_mv(rt_uint32_t raw_value, rt_uint32_t vref_mv, + rt_uint8_t resolution_bits, rt_uint32_t *voltage_mv) +{ + rt_uint64_t full_scale_code; + + if ((voltage_mv == RT_NULL) || (vref_mv == 0U) || (resolution_bits == 0U) || (resolution_bits > 32U)) + { + return -RT_EINVAL; + } + + full_scale_code = ((rt_uint64_t)1 << resolution_bits) - 1ULL; + if ((rt_uint64_t)raw_value > full_scale_code) + { + return -RT_EINVAL; + } + + /* + * Convert ADC code to millivolts: + * + * voltage_mv = raw * vref_mv / full_scale_code + * full_scale_code = (1 << resolution_bits) - 1 + * + * ADC codes are treated as an inclusive range from 0 to full scale. + * The multiplication is promoted to 64-bit first, then half of the + * denominator is added to round to the nearest integer millivolt instead + * of truncating non-exact divisions toward zero. + */ + *voltage_mv = (rt_uint32_t)(((rt_uint64_t)raw_value * (rt_uint64_t)vref_mv + (full_scale_code / 2ULL)) / full_scale_code); + + return RT_EOK; +} + +/** + * @brief Convert one ADC raw sample to a scaled voltage in millivolts. + * @param raw_value Raw ADC sample code. + * @param vref_mv ADC reference voltage in millivolts. + * @param resolution_bits ADC resolution in bits. + * @param scale_num Voltage scaling numerator. + * @param scale_den Voltage scaling denominator. + * @param voltage_mv Pointer to the output scaled voltage in millivolts. + * @return Operation status. + * + * The scaled voltage is calculated as: + * + * raw_to_voltage_mv(raw_value) * scale_num / scale_den + * + * @note @p scale_num and @p scale_den may describe any positive rational + * scaling ratio that does not overflow the internal calculation. The + * final scaled millivolt value must fit in rt_uint32_t. + * + * @retval RT_EOK The conversion completed successfully. + * @retval -RT_EINVAL A pointer is null, a scale argument is zero, the ADC + * conversion arguments are invalid, or the scaled result overflows + * rt_uint32_t. + */ +rt_err_t rt_adc_raw_to_scaled_voltage_mv(rt_uint32_t raw_value, rt_uint32_t vref_mv, + rt_uint8_t resolution_bits, rt_uint32_t scale_num, + rt_uint32_t scale_den, rt_uint32_t *voltage_mv) +{ + rt_uint32_t input_mv; + rt_uint64_t numerator; + rt_uint64_t rounding; + rt_uint64_t scaled_mv; + rt_err_t result; + + if ((voltage_mv == RT_NULL) || (scale_num == 0U) || (scale_den == 0U)) + { + return -RT_EINVAL; + } + + result = rt_adc_raw_to_voltage_mv(raw_value, vref_mv, resolution_bits, &input_mv); + if (result != RT_EOK) + { + return result; + } + + numerator = (rt_uint64_t)input_mv * (rt_uint64_t)scale_num; + rounding = (rt_uint64_t)scale_den / 2ULL; + + if (numerator > (((rt_uint64_t)~0ULL) - rounding)) + { + return -RT_EINVAL; + } + + scaled_mv = (numerator + rounding) / (rt_uint64_t)scale_den; + if (scaled_mv > RT_UINT32_MAX) + { + return -RT_EINVAL; + } + + *voltage_mv = (rt_uint32_t)scaled_mv; + return RT_EOK; +} + +/** + * @brief Read voltage values from the configured ADC session. + * @param device Pointer to the ADC device object. + * @param voltages_mv Pointer to the output voltage buffer in millivolts. + * @param size Output voltage buffer length in samples. + * @param timeout_ms Read timeout in milliseconds; negative means wait forever. + * @return Operation status. + * + * @note @p size must match the configured session channel count. The output + * order follows the ascending bit order of the configured channel mask. + * The configured default_vref_mv is preferred for voltage conversion. If + * default_vref_mv is not configured, the backend VREF channel is used for + * VDDA calculation only when it is present in the configured session. + */ +rt_err_t rt_adc_voltage(rt_adc_device_t device, rt_uint32_t *voltages_mv, rt_size_t size, rt_int32_t timeout_ms) +{ + rt_uint32_t vref_mv; + rt_uint32_t vref_value; + rt_uint8_t resolution_bits; + rt_uint8_t vref_channel; + rt_size_t vref_index; + rt_size_t index; + struct rt_adc_sequence_cfg sequence_cfg; + rt_size_t read_count; + rt_err_t result; + + if ((device == RT_NULL) || (voltages_mv == RT_NULL)) + { + return -RT_EINVAL; + } + + if ((device->ops == RT_NULL) || (device->ops->core == RT_NULL) || (device->ops->core->control == RT_NULL)) + { + return -RT_ENOSYS; + } + + if (adc_try_set_state(device, RT_ADC_STATE_IDLE, RT_ADC_STATE_LOCKED) != RT_TRUE) + { + return -RT_EBUSY; + } + + LOG_D("voltage request: device=%s count=%u timeout=%ld", device->parent.parent.name, (unsigned int)size, (long)timeout_ms); + + if ((device->session_ctrl.configured != RT_TRUE) || (device->session_ctrl.channel_count == 0U) || (size != device->session_ctrl.channel_count)) + { + result = -RT_EINVAL; + goto out; + } + + rt_memset(&sequence_cfg, 0, sizeof(sequence_cfg)); + sequence_cfg.buffer = voltages_mv; + sequence_cfg.buffer_length = size; + sequence_cfg.timeout_ms = timeout_ms; + result = adc_sequence_transfer_locked(device, device->session_ctrl.channels, + &sequence_cfg, size, &read_count); + if ((result == RT_EOK) && (read_count != size)) + { + result = -RT_ERROR; + } + if (result != RT_EOK) + { + LOG_E("voltage sample read failed: device=%s result=%d", device->parent.parent.name, result); + goto out; + } + + result = device->ops->core->control(device, RT_ADC_CMD_GET_RESOLUTION, &resolution_bits); + if (result != RT_EOK) + { + goto out; + } + + vref_mv = 0U; + if (device->default_vref_mv != 0U) + { + vref_mv = device->default_vref_mv; + result = RT_EOK; + } + else + { + vref_channel = 0U; + result = device->ops->core->control(device, RT_ADC_CMD_GET_VREF_CHANNEL, &vref_channel); + if ((result == RT_EOK) && (vref_channel < 32U) && ((device->session_ctrl.channels & RT_ADC_CHANNEL_MASK(vref_channel)) != 0U)) + { + result = rt_adc_session_channel_index(device->session_ctrl.channels, RT_ADC_CHANNEL_MASK(vref_channel), &vref_index); + if (result != RT_EOK) + { + goto out; + } + + vref_value = voltages_mv[vref_index]; + result = device->ops->core->control(device, RT_ADC_CMD_CALC_VREF, &vref_value); + if (result != RT_EOK) + { + LOG_E("vref calculate failed: device=%s raw=%lu result=%d", + device->parent.parent.name, (unsigned long)voltages_mv[vref_index], result); + goto out; + } + + if (vref_value == 0U) + { + result = -RT_EINVAL; + goto out; + } + + vref_mv = vref_value; + } + else + { + result = -RT_EINVAL; + goto out; + } + } + + for (index = 0U; index < size; index++) + { + result = rt_adc_raw_to_voltage_mv(voltages_mv[index], vref_mv, resolution_bits, &voltages_mv[index]); + if (result != RT_EOK) + { + goto out; + } + } + + LOG_D("voltage done: device=%s count=%u vref=%lu resolution=%u", + device->parent.parent.name, (unsigned int)size, + (unsigned long)vref_mv, (unsigned int)resolution_bits); + result = RT_EOK; + +out: + adc_set_state(device, RT_ADC_STATE_IDLE); + return result; +} + +#endif /* defined(RT_USING_ADC_V2) */ diff --git a/components/drivers/adc/adc_v2_internal.h b/components/drivers/adc/adc_v2_internal.h new file mode 100644 index 00000000000..1f97f17dd8b --- /dev/null +++ b/components/drivers/adc/adc_v2_internal.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file adc_v2_internal.h + * @brief Internal ADC V2 framework declarations. + */ + +#ifndef __ADC_V2_INTERNAL_H__ +#define __ADC_V2_INTERNAL_H__ + +#include +#include + +#if defined(RT_ADC_USING_TRIGGER) +/** + * @brief Initialize the cached ADC trigger state to the default software-started mode. + * @param device Pointer to the ADC device object. + */ +void adc_trigger_init(rt_adc_device_t device); + +/** + * @brief Preconfigure the active device-level ADC trigger before hardware configuration. + * @param device Pointer to the ADC device object. + * @return RT_EOK on success, otherwise an RT-Thread error code. + */ +rt_err_t adc_trigger_preconfig(rt_adc_device_t device); + +/** + * @brief Get the active device-level ADC trigger configuration. + * @param device Pointer to the ADC device object. + * @return Pointer to the cached trigger configuration, or RT_NULL when no hardware trigger is configured. + */ +const struct rt_adc_trigger_cfg *adc_trigger_active_get(rt_adc_device_t device); + +/** + * @brief Trigger-source lifecycle actions used after ADC hardware is armed. + */ +enum adc_trigger_source_action +{ + ADC_TRIGGER_SOURCE_START = 0, /**< Start the active trigger source. */ + ADC_TRIGGER_SOURCE_STOP /**< Stop the previously started trigger source. */ +}; + +/** + * @brief Control the active trigger source around an armed ADC conversion path. + * @param device Pointer to the ADC device object. + * @param action Trigger-source lifecycle action. + * @param started Pointer to the trigger-start state. + * @param current_result Transfer result before trigger stop, ignored for start. + * @return For start, trigger-source start result; for stop, @p current_result unless trigger stop is the first + * observed failure. + */ +rt_err_t adc_trigger_source_control(rt_adc_device_t device, enum adc_trigger_source_action action, + rt_bool_t *started, rt_err_t current_result); + +#endif /* defined(RT_ADC_USING_TRIGGER) */ + +#endif /* __ADC_V2_INTERNAL_H__ */ diff --git a/components/drivers/adc/adc_v2_msh.c b/components/drivers/adc/adc_v2_msh.c new file mode 100644 index 00000000000..7bc42f6cbf5 --- /dev/null +++ b/components/drivers/adc/adc_v2_msh.c @@ -0,0 +1,1225 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-05-09 wdfk-prog split adc v2 msh command implementation + */ + +/** + * @file adc_v2_msh.c + * @brief ADC V2 FinSH/MSH command implementation. + */ + +#include + +#if defined(RT_USING_ADC_V2) && defined(RT_USING_FINSH) && defined(RT_ADC_V2_USING_MSH) + +#include + +#include +#include +#include + +#include + +/** @brief Default FinSH temporary read buffer capacity in samples. */ +#define RT_ADC_MSH_VALUE_BUFFER_SIZE 32U + +/** @brief Default timeout in milliseconds for ADC MSH sequence read command. */ +#define RT_ADC_MSH_SEQ_DEFAULT_TIMEOUT_MS 1000 + +/** @brief Default FinSH stream read timeout in milliseconds. */ +#define RT_ADC_MSH_STREAM_READ_TIMEOUT_MS 1000 + +/** @brief Default FinSH stream DMA buffer capacity in samples. */ +#define RT_ADC_MSH_STREAM_DMA_BUFFER_SIZE 32U + +/** @brief Default FIFO storage capacity in samples for the ADC MSH FIFO stream test. */ +#define RT_ADC_MSH_FIFO_TEST_FIFO_BUFFER_SIZE 512U + +/** + * @brief Print backend-specific ADC FinSH command usage. + */ +rt_weak void rt_adc_msh_special_help(void) +{ +} + +/** + * @brief Handle backend-specific ADC FinSH commands. + * @param device Pointer to the selected ADC device object. + * @param argc Argument count excluding the top-level adc command. + * @param argv Argument vector excluding the top-level adc command. + * @return Operation status. + */ +rt_weak rt_err_t rt_adc_msh_special(rt_adc_device_t device, int argc, char **argv) +{ + RT_UNUSED(device); + RT_UNUSED(argc); + RT_UNUSED(argv); + + return -RT_ENOSYS; +} + +#if defined(RT_ADC_USING_TRIGGER) +/** + * @brief Print ADC trigger MSH command usage. + */ +static void adc_msh_usage_trigger(void) +{ +#if defined(RT_ADC_TRIGGER_USING_TIMER) + rt_kprintf(" adc trigger set timer_update \n"); + rt_kprintf(" adc trigger set timer_compare \n"); +#endif /* defined(RT_ADC_TRIGGER_USING_TIMER) */ +#if defined(RT_ADC_TRIGGER_USING_COMPARE) + rt_kprintf(" adc trigger set compare [comparator_device] , num: 0~31\n"); +#endif /* defined(RT_ADC_TRIGGER_USING_COMPARE) */ + rt_kprintf(" adc trigger clear\n"); + rt_kprintf(" adc trigger status\n"); +} +#endif /* defined(RT_ADC_USING_TRIGGER) */ + +#if defined(RT_ADC_USING_STREAM) +/** + * @brief Print ADC stream MSH command usage. + */ +static void adc_msh_usage_stream(void) +{ + rt_kprintf(" adc stream start [num1 ...], num: 0~31\n"); + rt_kprintf(" adc stream read [timeout_ms]\n"); + rt_kprintf(" adc stream cancel\n"); + rt_kprintf(" adc stream stop\n"); +#if defined(RT_ADC_MSH_USING_FIFO_TEST) && defined(RT_ADC_STREAM_USING_FIFO) + rt_kprintf(" adc fifo [num1 ...]\n"); +#endif /* defined(RT_ADC_MSH_USING_FIFO_TEST) && defined(RT_ADC_STREAM_USING_FIFO) */ +} +#endif /* defined(RT_ADC_USING_STREAM) */ + +/** + * @brief Print ADC FinSH command usage. + */ +static void adc_msh_usage(void) +{ + rt_kprintf("Usage:\n"); + rt_kprintf(" adc probe \n"); + rt_kprintf(" adc close\n"); + rt_kprintf(" adc config [num1 ...], num: 0~31, eg: 0 1 10\n"); + rt_kprintf(" adc read\n"); + rt_kprintf(" adc voltage \n"); + rt_kprintf(" voltage reads the current session configured by adc config\n"); + rt_kprintf(" if default_vref is absent, adc config must include the backend VREF channel\n"); + rt_kprintf(" adc seq [num1 ...], num: 0~31, eg: 0 1 10\n"); +#if defined(RT_ADC_USING_TRIGGER) + adc_msh_usage_trigger(); +#endif /* defined(RT_ADC_USING_TRIGGER) */ + +#if defined(RT_ADC_USING_STREAM) + adc_msh_usage_stream(); +#endif /* defined(RT_ADC_USING_STREAM) */ + + rt_adc_msh_special_help(); +} + +/** + * @brief Convert one shell argument to a single-channel mask. + * @param arg Pointer to the shell argument string. + * @param channels Pointer to the output channel mask. + * @return Operation status. + */ +static rt_err_t adc_msh_parse_channel_mask(const char *arg, rt_uint32_t *channels) +{ + char *endptr; + unsigned long value; + + if ((*arg == '\0') || (*arg == '-')) + { + return -RT_EINVAL; + } + + endptr = RT_NULL; + value = strtoul(arg, &endptr, 0); + if ((endptr == arg) || (endptr == RT_NULL) || (*endptr != '\0') || (value >= 32UL)) + { + return -RT_EINVAL; + } + + *channels = RT_ADC_CHANNEL_MASK(value); + return RT_EOK; +} + +/** + * @brief Convert one shell argument to a timeout value. + * @param arg Pointer to the shell argument string. + * @return Timeout in milliseconds; negative means wait forever. + * + * @note This command keeps the permissive MSH parsing convention: strtol() + * is used without endptr validation, so a non-numeric string with no + * converted digits is treated as 0 by the C library conversion path. A + * timeout value of 0 means non-blocking/immediate timeout. + */ +static rt_int32_t adc_msh_parse_timeout(const char *arg) +{ + return (rt_int32_t)strtol(arg, RT_NULL, 0); +} + +#if defined(RT_ADC_USING_TRIGGER) && (defined(RT_ADC_TRIGGER_USING_TIMER) || defined(RT_ADC_TRIGGER_USING_COMPARE)) +/** + * @brief Convert one shell argument to an unsigned integer. + * @param arg Pointer to the shell argument string. + * @param max_value Maximum accepted value. + * @param value Pointer to the output value. + * @return Operation status. + */ +static rt_err_t adc_msh_parse_ulong(const char *arg, unsigned long max_value, unsigned long *value) +{ + char *endptr; + unsigned long parsed; + + if ((arg == RT_NULL) || (value == RT_NULL) || (*arg == '\0') || (*arg == '-')) + { + return -RT_EINVAL; + } + + endptr = RT_NULL; + parsed = strtoul(arg, &endptr, 0); + if ((endptr == arg) || (endptr == RT_NULL) || (*endptr != '\0') || (parsed > max_value)) + { + return -RT_EINVAL; + } + + *value = parsed; + return RT_EOK; +} + +#if defined(RT_ADC_TRIGGER_USING_COMPARE) +/** + * @brief Convert one shell argument to an ADC trigger edge selector. + * @param arg Pointer to the shell argument string. + * @param edge Pointer to the output trigger edge selector. + * @return Operation status. + */ +static rt_err_t adc_msh_parse_trigger_edge(const char *arg, enum rt_adc_trigger_edge *edge) +{ + if ((arg == RT_NULL) || (edge == RT_NULL)) + { + return -RT_EINVAL; + } + + if (!rt_strcmp(arg, "rising")) + { + *edge = RT_ADC_TRIGGER_EDGE_RISING; + return RT_EOK; + } + + if (!rt_strcmp(arg, "falling")) + { + *edge = RT_ADC_TRIGGER_EDGE_FALLING; + return RT_EOK; + } + + if (!rt_strcmp(arg, "both")) + { + *edge = RT_ADC_TRIGGER_EDGE_BOTH; + return RT_EOK; + } + + return -RT_EINVAL; +} + +#endif /* defined(RT_ADC_TRIGGER_USING_COMPARE) */ + +/** + * @brief Find one trigger source device by shell argument. + * @param name Pointer to the source device name string. + * @param source Pointer to the output source device object. + * @return Operation status. + */ +static rt_err_t adc_msh_find_trigger_source(const char *name, rt_device_t *source) +{ + rt_device_t dev; + + if ((name == RT_NULL) || (source == RT_NULL)) + { + return -RT_EINVAL; + } + + dev = rt_device_find(name); + if (dev == RT_NULL) + { + rt_kprintf("trigger source %s not found\n", name); + return -RT_ERROR; + } + + *source = dev; + return RT_EOK; +} +#endif /* defined(RT_ADC_USING_TRIGGER) && (defined(RT_ADC_TRIGGER_USING_TIMER) || defined(RT_ADC_TRIGGER_USING_COMPARE)) */ + +#ifdef RT_ADC_USING_STREAM +/** + * @brief Clear the FinSH stream scratch buffer owner. + * @param stream_device Pointer to the saved stream device owner. + */ +static void adc_msh_clear_stream_owner(rt_adc_device_t *stream_device) +{ + if (stream_device != RT_NULL) + { + *stream_device = RT_NULL; + } +} + +/** + * @brief Get the current ADC framework state for the FinSH command. + * @param device Pointer to the ADC device object. + * @return Current ADC runtime state. + */ +static enum rt_adc_state adc_msh_get_state(rt_adc_device_t device) +{ + return (enum rt_adc_state)rt_atomic_load(&device->state); +} + +/** + * @brief Check whether the FinSH stream scratch buffer is still owned by an active stream. + * @param stream_device Saved stream device owner. + * @return RT_TRUE if the stream buffer is still owned by an active stream. + */ +static rt_bool_t adc_msh_stream_buffer_is_active(rt_adc_device_t stream_device) +{ + if (stream_device == RT_NULL) + { + return RT_FALSE; + } + + return (adc_msh_get_state(stream_device) == RT_ADC_STATE_STREAM) ? RT_TRUE : RT_FALSE; +} +#endif /* RT_ADC_USING_STREAM */ + +static rt_adc_device_t device = RT_NULL; +#ifdef RT_ADC_USING_STREAM +static rt_adc_device_t stream_device = RT_NULL; +static rt_uint32_t stream_dma_buffer[RT_ADC_MSH_STREAM_DMA_BUFFER_SIZE]; +#if defined(RT_ADC_MSH_USING_FIFO_TEST) && defined(RT_ADC_STREAM_USING_FIFO) +static rt_uint32_t stream_fifo_buffer[RT_ADC_MSH_FIFO_TEST_FIFO_BUFFER_SIZE]; +#endif /* defined(RT_ADC_MSH_USING_FIFO_TEST) && defined(RT_ADC_STREAM_USING_FIFO) */ +#endif /* RT_ADC_USING_STREAM */ + + +#if defined(RT_ADC_USING_TRIGGER) +/** + * @brief Handle ADC trigger subcommands. + * @param device Pointer to the selected ADC device object. + * @param argc Argument count excluding "adc trigger". + * @param argv Argument vector excluding "adc trigger". + * @return Command status. + */ +static rt_err_t adc_msh_trigger(rt_adc_device_t device, int argc, char **argv) +{ + rt_err_t result; + + if (argc < 1) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + if (!rt_strcmp(argv[0], "clear")) + { + if (argc != 1) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + result = rt_adc_trigger_clear(device); + if (result == RT_EOK) + { + rt_kprintf("adc trigger cleared\n"); + } + return result; + } + + if (!rt_strcmp(argv[0], "status")) + { + if (argc != 1) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + rt_kprintf("adc trigger: %s\n", rt_adc_trigger_is_set(device) == RT_TRUE ? "set" : "clear"); + return RT_EOK; + } + + if (!rt_strcmp(argv[0], "set")) + { + struct rt_adc_trigger_cfg trigger_cfg; + + if (argc < 2) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + rt_memset(&trigger_cfg, 0, sizeof(trigger_cfg)); +#if defined(RT_ADC_TRIGGER_USING_TIMER) + if (!rt_strcmp(argv[1], "timer_update")) + { + unsigned long freq_hz; + + if (argc != 4) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + result = adc_msh_find_trigger_source(argv[2], &trigger_cfg.event.timer.timer); + if (result != RT_EOK) + { + return result; + } + + result = adc_msh_parse_ulong(argv[3], 0xffffffffUL, &freq_hz); + if ((result != RT_EOK) || (freq_hz == 0UL)) + { + rt_kprintf("invalid adc trigger timer frequency: %s\n", argv[3]); + return (result != RT_EOK) ? result : -RT_EINVAL; + } + + trigger_cfg.type = RT_ADC_TRIGGER_TIMER_UPDATE; + trigger_cfg.event.timer.freq_hz = (rt_uint32_t)freq_hz; + trigger_cfg.event.timer.channel = 0U; + } + else if (!rt_strcmp(argv[1], "timer_compare")) + { + unsigned long channel; + unsigned long freq_hz; + + if (argc != 5) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + result = adc_msh_find_trigger_source(argv[2], &trigger_cfg.event.timer.timer); + if (result != RT_EOK) + { + return result; + } + + result = adc_msh_parse_ulong(argv[3], 65535UL, &channel); + if ((result != RT_EOK) || (channel == 0UL)) + { + rt_kprintf("invalid adc trigger timer channel: %s\n", argv[3]); + return (result != RT_EOK) ? result : -RT_EINVAL; + } + + result = adc_msh_parse_ulong(argv[4], 0xffffffffUL, &freq_hz); + if ((result != RT_EOK) || (freq_hz == 0UL)) + { + rt_kprintf("invalid adc trigger timer frequency: %s\n", argv[4]); + return (result != RT_EOK) ? result : -RT_EINVAL; + } + + trigger_cfg.type = RT_ADC_TRIGGER_TIMER_COMPARE; + trigger_cfg.event.timer.freq_hz = (rt_uint32_t)freq_hz; + trigger_cfg.event.timer.channel = (rt_uint16_t)channel; + } + else +#endif /* defined(RT_ADC_TRIGGER_USING_TIMER) */ +#if defined(RT_ADC_TRIGGER_USING_COMPARE) + if (!rt_strcmp(argv[1], "compare")) + { + unsigned long channel; + int channel_arg; + int edge_arg; + + if ((argc != 4) && (argc != 5)) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + if (argc == 5) + { + result = adc_msh_find_trigger_source(argv[2], &trigger_cfg.event.compare.comparator); + if (result != RT_EOK) + { + return result; + } + channel_arg = 3; + edge_arg = 4; + } + else + { + channel_arg = 2; + edge_arg = 3; + } + + result = adc_msh_parse_ulong(argv[channel_arg], 65535UL, &channel); + if ((result != RT_EOK) || (channel == 0UL)) + { + rt_kprintf("invalid adc trigger compare channel: %s\n", argv[channel_arg]); + return (result != RT_EOK) ? result : -RT_EINVAL; + } + + result = adc_msh_parse_trigger_edge(argv[edge_arg], &trigger_cfg.event.compare.edge); + if (result != RT_EOK) + { + rt_kprintf("invalid adc trigger edge: %s\n", argv[edge_arg]); + return result; + } + + trigger_cfg.type = RT_ADC_TRIGGER_ANALOG_COMPARE; + trigger_cfg.event.compare.channel = (rt_uint16_t)channel; + } + else +#endif /* defined(RT_ADC_TRIGGER_USING_COMPARE) */ + { + adc_msh_usage(); + return -RT_EINVAL; + } + + result = rt_adc_trigger_set(device, &trigger_cfg); + if (result == RT_EOK) + { + rt_kprintf("adc trigger set: %s\n", argv[1]); + } + return result; + } + + adc_msh_usage(); + return -RT_EINVAL; +} +#endif /* defined(RT_ADC_USING_TRIGGER) */ + +#ifdef RT_ADC_USING_STREAM +/** + * @brief Handle ADC stream subcommands. + * @param device Pointer to the selected ADC device object. + * @param argc Argument count excluding "adc stream". + * @param argv Argument vector excluding "adc stream". + * @return Command status. + */ +static rt_err_t adc_msh_stream(rt_adc_device_t device, int argc, char **argv) +{ + rt_uint32_t values[RT_ADC_MSH_VALUE_BUFFER_SIZE]; + rt_size_t count; + rt_size_t index; + rt_err_t result; + + if (argc < 1) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + if (!rt_strcmp(argv[0], "start")) + { +#ifndef RT_ADC_STREAM_USING_LATEST + return -RT_ENOSYS; +#else + struct rt_adc_stream_cfg stream_cfg; + rt_uint32_t channels; + rt_uint32_t channel_mask; + + if (argc < 2) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + if (adc_msh_get_state(device) == RT_ADC_STATE_STREAM) + { + rt_kprintf("adc stream is already running, stop it first\n"); + return -RT_EBUSY; + } + + channels = 0U; + for (index = 0U; index < (rt_size_t)(argc - 1); index++) + { + result = adc_msh_parse_channel_mask(argv[index + 1], &channel_mask); + if (result != RT_EOK) + { + rt_kprintf("invalid adc channel: %s\n", argv[index + 1]); + return result; + } + channels |= channel_mask; + } + + count = rt_adc_channel_mask_count(channels); + if (count == 0U) + { + return -RT_EINVAL; + } + + if (adc_msh_stream_buffer_is_active(stream_device) == RT_TRUE) + { + rt_kprintf("adc stream is already running, stop it first\n"); + return -RT_EBUSY; + } + adc_msh_clear_stream_owner(&stream_device); + + if (count > RT_ADC_MSH_STREAM_DMA_BUFFER_SIZE) + { + rt_kprintf("adc stream buffer too large, max %u samples\n", (unsigned int)RT_ADC_MSH_STREAM_DMA_BUFFER_SIZE); + return -RT_EINVAL; + } + + rt_memset(&stream_cfg, 0, sizeof(stream_cfg)); + stream_cfg.policy = RT_ADC_STREAM_POLICY_LATEST; + stream_cfg.dma_event_mode = RT_ADC_STREAM_DMA_EVENT_AUTO; + stream_cfg.dma_buffer = stream_dma_buffer; + stream_cfg.dma_buffer_length = count; + + result = rt_adc_stream_start(device, channels, &stream_cfg); + if (result == RT_EOK) + { + stream_device = device; + } + else if (adc_msh_get_state(device) == RT_ADC_STATE_STREAM) + { + stream_device = device; + rt_kprintf("adc stream start failed but stream hardware may still be running, stop it first\n"); + } + else + { + adc_msh_clear_stream_owner(&stream_device); + } + return result; +#endif /* RT_ADC_STREAM_USING_LATEST */ + } + + if (!rt_strcmp(argv[0], "read")) + { + rt_ssize_t read_count; + rt_int32_t timeout_ms; + + if (argc > 2) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + if ((stream_device != RT_NULL) && (stream_device != device)) + { + rt_kprintf("adc stream belongs to another device\n"); + return -RT_EBUSY; + } + + if (adc_msh_get_state(device) != RT_ADC_STATE_STREAM) + { + rt_kprintf("adc stream is not running\n"); + return -RT_EINVAL; + } + + count = device->stream_ctrl.frame_length; + if (count == 0U) + { + rt_kprintf("adc stream channel count is zero\n"); + return -RT_EINVAL; + } + + if (count > RT_ADC_MSH_VALUE_BUFFER_SIZE) + { + rt_kprintf("adc stream read count too large, max %u samples\n", (unsigned int)RT_ADC_MSH_VALUE_BUFFER_SIZE); + return -RT_EINVAL; + } + + timeout_ms = (argc == 2) ? adc_msh_parse_timeout(argv[1]) : RT_ADC_MSH_STREAM_READ_TIMEOUT_MS; + read_count = rt_adc_stream_read(device, values, count, timeout_ms); + if (read_count > 0) + { + for (index = 0U; index < (rt_size_t)read_count; index++) + { + rt_kprintf("[%u]=%lu\n", (unsigned int)index, (unsigned long)values[index]); + } + } + + return (read_count >= 0) ? RT_EOK : (rt_err_t)read_count; + } + + if (!rt_strcmp(argv[0], "stop")) + { + if (argc != 1) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + if ((stream_device != RT_NULL) && (stream_device != device)) + { + rt_kprintf("adc stream belongs to another device\n"); + return -RT_EBUSY; + } + + result = rt_adc_stream_stop(device); + if (result == RT_EOK) + { + adc_msh_clear_stream_owner(&stream_device); + } + return result; + } + + if (!rt_strcmp(argv[0], "cancel")) + { + if (argc != 1) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + if ((stream_device != RT_NULL) && (stream_device != device)) + { + rt_kprintf("adc stream belongs to another device\n"); + return -RT_EBUSY; + } + + return rt_adc_stream_cancel(device); + } + + adc_msh_usage(); + return -RT_EINVAL; +} +#endif /* RT_ADC_USING_STREAM */ + +#if defined(RT_ADC_USING_STREAM) && defined(RT_ADC_MSH_USING_FIFO_TEST) && defined(RT_ADC_STREAM_USING_FIFO) +#define RT_ADC_MSH_FIFO_TEST_READ_FRAME_COUNT 16U +#define RT_ADC_MSH_FIFO_TEST_READ_TIMEOUT_MS 1000 +/** + * @brief Handle the ADC FIFO stream test command. + * @param device Pointer to the selected ADC device object. + * @param argc Argument count excluding "adc fifo". + * @param argv Argument vector excluding "adc fifo". + * @return Command status. + */ +static rt_err_t adc_msh_fifo_test(rt_adc_device_t device, int argc, char **argv) +{ + struct rt_adc_stream_cfg stream_cfg; + rt_uint32_t *buffer; + rt_uint32_t channels; + rt_uint32_t channel_mask; + rt_size_t channel_count; + rt_size_t sample_count; + rt_size_t dma_buffer_length; + rt_size_t fifo_buffer_length; + rt_size_t read_times; + rt_size_t index; + rt_size_t full_count; + rt_size_t partial_count; + rt_size_t timeout_count; + rt_size_t error_count; + rt_size_t total_samples; + rt_tick_t begin_tick; + rt_tick_t end_tick; + rt_tick_t timeout_tick; + rt_int32_t timeout_ms; + rt_err_t result; + rt_err_t stop_result; + + if (argc < 2) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + timeout_ms = adc_msh_parse_timeout(argv[0]); + if (timeout_ms <= 0) + { + rt_kprintf("fifo test timeout_ms must be greater than 0\n"); + return -RT_EINVAL; + } + + if (adc_msh_get_state(device) == RT_ADC_STATE_STREAM) + { + rt_kprintf("adc stream is already running, stop it first\n"); + return -RT_EBUSY; + } + + if (adc_msh_stream_buffer_is_active(stream_device) == RT_TRUE) + { + rt_kprintf("adc stream is already running, stop it first\n"); + return -RT_EBUSY; + } + adc_msh_clear_stream_owner(&stream_device); + + channels = 0U; + for (index = 0U; index < (rt_size_t)(argc - 1); index++) + { + result = adc_msh_parse_channel_mask(argv[index + 1], &channel_mask); + if (result != RT_EOK) + { + rt_kprintf("invalid adc channel: %s\n", argv[index + 1]); + return result; + } + channels |= channel_mask; + } + + channel_count = rt_adc_channel_mask_count(channels); + if (channel_count == 0U) + { + return -RT_EINVAL; + } + + if (RT_ADC_MSH_STREAM_DMA_BUFFER_SIZE < (channel_count * 2U)) + { + rt_kprintf("adc fifo test dma buffer too small, min %u samples\n", (unsigned int)(channel_count * 2U)); + return -RT_EINVAL; + } + + sample_count = channel_count * RT_ADC_MSH_FIFO_TEST_READ_FRAME_COUNT; + if ((sample_count == 0U) || (sample_count > (((rt_size_t)-1) / sizeof(rt_uint32_t)))) + { + rt_kprintf("adc fifo test read sample count is too large\n"); + return -RT_EINVAL; + } + + dma_buffer_length = (RT_ADC_MSH_STREAM_DMA_BUFFER_SIZE / (channel_count * 2U)) * (channel_count * 2U); + fifo_buffer_length = (RT_ADC_MSH_FIFO_TEST_FIFO_BUFFER_SIZE / channel_count) * channel_count; + if (fifo_buffer_length < (dma_buffer_length / 2U)) + { + rt_kprintf("adc fifo test fifo buffer too small, min %u samples\n", (unsigned int)(dma_buffer_length / 2U)); + return -RT_EINVAL; + } + + buffer = (rt_uint32_t *)rt_malloc(sample_count * sizeof(rt_uint32_t)); + if (buffer == RT_NULL) + { + rt_kprintf("no memory for fifo test buffer\n"); + return -RT_ENOMEM; + } + + rt_memset(&stream_cfg, 0, sizeof(stream_cfg)); + stream_cfg.policy = RT_ADC_STREAM_POLICY_FIFO; + stream_cfg.dma_event_mode = RT_ADC_STREAM_DMA_EVENT_HALF_FULL; + stream_cfg.dma_buffer = stream_dma_buffer; + stream_cfg.dma_buffer_length = dma_buffer_length; + stream_cfg.fifo_buffer = stream_fifo_buffer; + stream_cfg.fifo_buffer_length = fifo_buffer_length; + stream_cfg.watermark = dma_buffer_length / 2U; + + result = rt_adc_stream_start_frame_aligned_fifo(device, channels, &stream_cfg); + if (result != RT_EOK) + { + rt_free(buffer); + return result; + } + stream_device = device; + + result = RT_EOK; + read_times = 0U; + full_count = 0U; + partial_count = 0U; + timeout_count = 0U; + error_count = 0U; + total_samples = 0U; + begin_tick = rt_tick_get(); + timeout_tick = rt_tick_from_millisecond(timeout_ms); + + while (rt_tick_get_delta(begin_tick) < timeout_tick) + { + rt_ssize_t read_count; + + read_count = rt_adc_stream_read(device, buffer, sample_count, RT_ADC_MSH_FIFO_TEST_READ_TIMEOUT_MS); + read_times++; + if (read_count < 0) + { + if (read_count == -RT_ETIMEOUT) + { + timeout_count++; + continue; + } + + result = (rt_err_t)read_count; + error_count++; + rt_kprintf("stream fifo test failed at %u: %d\n", (unsigned int)read_times, (int)read_count); + break; + } + + total_samples += (rt_size_t)read_count; + if ((rt_size_t)read_count == sample_count) + { + full_count++; + } + else + { + partial_count++; + } + } + + end_tick = rt_tick_get(); + stop_result = rt_adc_stream_stop(device); + if (stop_result == RT_EOK) + { + adc_msh_clear_stream_owner(&stream_device); + } + + rt_size_t elapsed_tick; + rt_size_t total_frames; + rt_size_t read_frames; + rt_size_t dma_frames; + rt_size_t fifo_frames; + rt_size_t frame_rate; + rt_size_t sample_rate_per_channel; + + elapsed_tick = end_tick - begin_tick; + total_frames = total_samples / channel_count; + read_frames = sample_count / channel_count; + dma_frames = dma_buffer_length / channel_count; + fifo_frames = fifo_buffer_length / channel_count; + + if (elapsed_tick > 0U) + { + frame_rate = (total_frames * RT_TICK_PER_SECOND) / elapsed_tick; + sample_rate_per_channel = frame_rate; + } + else + { + frame_rate = 0U; + sample_rate_per_channel = 0U; + } + + rt_kprintf("adc fifo_test: %s\n", (error_count == 0U && timeout_count == 0U && partial_count == 0U) ? "PASS" : "FAIL"); + rt_kprintf(" duration : %d ms\n", (int)timeout_ms); + rt_kprintf(" channels : %u\n", (unsigned int)channel_count); + rt_kprintf(" read block : %u frames, %u samples\n", + (unsigned int)read_frames, (unsigned int)sample_count); + rt_kprintf(" dma buffer : %u frames, %u samples\n", + (unsigned int)dma_frames, (unsigned int)dma_buffer_length); + rt_kprintf(" fifo buffer : %u frames, %u samples\n", + (unsigned int)fifo_frames, (unsigned int)fifo_buffer_length); + rt_kprintf(" read count : %u\n", (unsigned int)read_times); + rt_kprintf(" full reads : %u\n", (unsigned int)full_count); + rt_kprintf(" partial reads : %u\n", (unsigned int)partial_count); + rt_kprintf(" timeouts : %u\n", (unsigned int)timeout_count); + rt_kprintf(" errors : %u\n", (unsigned int)error_count); + rt_kprintf(" total frames : %u\n", (unsigned int)total_frames); + rt_kprintf(" total samples : %u\n", (unsigned int)total_samples); + rt_kprintf(" frame rate : %u frames/s\n", (unsigned int)frame_rate); + rt_kprintf(" sample rate/ch : %u samples/s\n", (unsigned int)sample_rate_per_channel); + rt_kprintf(" elapsed tick : %u\n", (unsigned int)elapsed_tick); + + rt_free(buffer); + if (error_count > 0U) + { + return result; + } + + if (timeout_count > 0U) + { + return -RT_ETIMEOUT; + } + + return stop_result; +} +#endif /* defined(RT_ADC_USING_STREAM) && defined(RT_ADC_MSH_USING_FIFO_TEST) && defined(RT_ADC_STREAM_USING_FIFO) */ + +/** + * @brief Handle the ADC FinSH command. + * @param argc Argument count. + * @param argv Argument vector. + * @return Command status. + */ +static int adc(int argc, char **argv) +{ + rt_uint32_t values_buf[RT_ADC_MSH_VALUE_BUFFER_SIZE]; + rt_uint32_t *values; + rt_uint32_t channels; + rt_uint32_t channel_mask; + rt_size_t index; + rt_size_t count; + rt_ssize_t read_count; + rt_err_t result; + + if (argc < 2) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + values = values_buf; + if (!rt_strcmp(argv[1], "probe")) + { + rt_device_t new_dev; + rt_adc_device_t new_device; + + if (argc != 3) + { + adc_msh_usage(); + return -RT_EINVAL; + } + +#ifdef RT_ADC_USING_STREAM + if (adc_msh_stream_buffer_is_active(stream_device) == RT_TRUE) + { + rt_kprintf("adc stream is running, stop it first\n"); + return -RT_EBUSY; + } + adc_msh_clear_stream_owner(&stream_device); +#endif /* RT_ADC_USING_STREAM */ + + new_dev = rt_device_find(argv[2]); + if (new_dev == RT_NULL) + { + rt_kprintf("adc device %s not found\n", argv[2]); + return -RT_ERROR; + } + + if (new_dev->type != RT_Device_Class_ADC) + { + rt_kprintf("%s is not an adc device\n", argv[2]); + return -RT_EINVAL; + } + + new_device = (rt_adc_device_t)new_dev; + if (device == new_device) + { + rt_kprintf("probe %s: %d\n", argv[2], RT_EOK); + return RT_EOK; + } + + result = rt_device_open(new_dev, RT_DEVICE_OFLAG_RDWR); + if (result != RT_EOK) + { + rt_kprintf("probe %s failed: %d\n", argv[2], result); + return result; + } + + if (device != RT_NULL) + { + rt_err_t close_result; + + close_result = rt_device_close(&device->parent); + if (close_result != RT_EOK) + { + (void)rt_device_close(new_dev); + rt_kprintf("close previous adc device %s failed: %d\n", device->parent.parent.name, close_result); + return close_result; + } + } + + device = new_device; + rt_kprintf("probe %s: %d\n", argv[2], result); + return result; + } + + if (device == RT_NULL) + { + rt_kprintf("no adc device selected\n"); + return -RT_EINVAL; + } + + if (!rt_strcmp(argv[1], "config")) + { + if (argc < 3) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + channels = 0U; + for (index = 0U; index < (rt_size_t)(argc - 2); index++) + { + result = adc_msh_parse_channel_mask(argv[index + 2], &channel_mask); + if (result != RT_EOK) + { + rt_kprintf("invalid adc channel: %s\n", argv[index + 2]); + return result; + } + channels |= channel_mask; + } + + result = rt_device_control(&device->parent, RT_ADC_CMD_SET_SESSION, &channels); + if (result == RT_EOK) + { + rt_kprintf("config channels=0x%08lx count=%u\n", + (unsigned long)channels, (unsigned int)rt_adc_channel_mask_count(channels)); + } + return result; + } + + if (!rt_strcmp(argv[1], "read")) + { + if (argc > 2) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + if ((device->session_ctrl.configured != RT_TRUE) || (device->session_ctrl.channel_count == 0U)) + { + rt_kprintf("adc session is not configured, run adc config first\n"); + return -RT_EINVAL; + } + + count = device->session_ctrl.channel_count; + if (count > RT_ADC_MSH_VALUE_BUFFER_SIZE) + { + rt_kprintf("adc read count too large, max %u samples\n", (unsigned int)RT_ADC_MSH_VALUE_BUFFER_SIZE); + return -RT_EINVAL; + } + + read_count = rt_device_read(&device->parent, 0, values, count); + if (read_count < 0) + { + result = (rt_err_t)read_count; + } + else if ((rt_size_t)read_count != count) + { + result = -RT_ERROR; + } + else + { + result = RT_EOK; + for (index = 0U; index < count; index++) + { + rt_kprintf("[%u]=%lu\n", (unsigned int)index, (unsigned long)values[index]); + } + } + return result; + } + + if (!rt_strcmp(argv[1], "voltage")) + { + rt_int32_t timeout_ms; + + if (argc != 3) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + if ((device->session_ctrl.configured != RT_TRUE) || (device->session_ctrl.channel_count == 0U)) + { + rt_kprintf("adc session is not configured, run adc config first\n"); + return -RT_EINVAL; + } + + timeout_ms = adc_msh_parse_timeout(argv[2]); + count = device->session_ctrl.channel_count; + if (count > RT_ADC_MSH_VALUE_BUFFER_SIZE) + { + rt_kprintf("adc voltage count too large, max %u samples\n", (unsigned int)RT_ADC_MSH_VALUE_BUFFER_SIZE); + return -RT_EINVAL; + } + + result = rt_adc_voltage(device, values, count, timeout_ms); + if (result == RT_EOK) + { + for (index = 0U; index < count; index++) + { + rt_kprintf("[%u]=%lu mV\n", (unsigned int)index, (unsigned long)values[index]); + } + } + else if (result == -RT_EINVAL) + { + rt_kprintf("adc voltage failed, check adc config and VREF channel/default_vref\n"); + } + + return result; + } + + if (!rt_strcmp(argv[1], "seq")) + { + struct rt_adc_sequence_cfg sequence_cfg; + rt_size_t sequence_read_count; + + if (argc < 4) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + channels = 0U; + for (index = 0U; index < (rt_size_t)(argc - 3); index++) + { + result = adc_msh_parse_channel_mask(argv[index + 3], &channel_mask); + if (result != RT_EOK) + { + rt_kprintf("invalid adc channel: %s\n", argv[index + 3]); + return result; + } + channels |= channel_mask; + } + + count = rt_adc_channel_mask_count(channels); + if (count > RT_ADC_MSH_VALUE_BUFFER_SIZE) + { + rt_kprintf("adc seq count too large, max %u samples\n", (unsigned int)RT_ADC_MSH_VALUE_BUFFER_SIZE); + return -RT_EINVAL; + } + + rt_memset(&sequence_cfg, 0, sizeof(sequence_cfg)); + sequence_cfg.buffer = values; + sequence_cfg.buffer_length = count; + sequence_cfg.timeout_ms = adc_msh_parse_timeout(argv[2]); + + result = rt_adc_read_sequence(device, channels, &sequence_cfg, &sequence_read_count); + if (result != RT_EOK) + { + return result; + } + + for (index = 0U; index < sequence_read_count; index++) + { + rt_kprintf("[%u]=%lu\n", (unsigned int)index, (unsigned long)values[index]); + } + + return RT_EOK; + } + +#if defined(RT_ADC_USING_TRIGGER) + if (!rt_strcmp(argv[1], "trigger")) + { + return adc_msh_trigger(device, argc - 2, &argv[2]); + } +#endif /* defined(RT_ADC_USING_TRIGGER) */ + + if (!rt_strcmp(argv[1], "close")) + { + rt_err_t close_result; + + if (argc > 2) + { + adc_msh_usage(); + return -RT_EINVAL; + } + + close_result = rt_device_close(&device->parent); + if (close_result != RT_EOK) + { + rt_kprintf("close adc device %s failed: %d\n", device->parent.parent.name, close_result); + return close_result; + } + + rt_kprintf("close %s: %d\n", device->parent.parent.name, close_result); + device = RT_NULL; + return RT_EOK; + } + +#ifdef RT_ADC_USING_STREAM + if (!rt_strcmp(argv[1], "stream")) + { + return adc_msh_stream(device, argc - 2, &argv[2]); + } + +#if defined(RT_ADC_MSH_USING_FIFO_TEST) && defined(RT_ADC_STREAM_USING_FIFO) + if (!rt_strcmp(argv[1], "fifo")) + { + return adc_msh_fifo_test(device, argc - 2, &argv[2]); + } +#endif /* defined(RT_ADC_MSH_USING_FIFO_TEST) && defined(RT_ADC_STREAM_USING_FIFO) */ +#endif /* RT_ADC_USING_STREAM */ + + result = rt_adc_msh_special(device, argc - 1, &argv[1]); + if (result != -RT_ENOSYS) + { + return result; + } + + adc_msh_usage(); + return -RT_EINVAL; +} +MSH_CMD_EXPORT(adc, adc v2 command); +#endif /* defined(RT_USING_ADC_V2) && defined(RT_USING_FINSH) && defined(RT_ADC_V2_USING_MSH) */ diff --git a/components/drivers/adc/adc_v2_trigger.c b/components/drivers/adc/adc_v2_trigger.c new file mode 100644 index 00000000000..0521201c49b --- /dev/null +++ b/components/drivers/adc/adc_v2_trigger.c @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-05-20 wdfk-prog add ADC V2 timer trigger framework implementation + */ + +/** + * @file adc_v2_trigger.c + * @brief ADC V2 trigger framework implementation. + */ + +#include + +#if defined(RT_USING_ADC_V2) && defined(RT_ADC_USING_TRIGGER) + +#include +#include +#if defined(RT_ADC_TRIGGER_USING_TIMER) && defined(RT_USING_CLOCK_TIMER_TRIGGER) +#include +#endif /* defined(RT_ADC_TRIGGER_USING_TIMER) && defined(RT_USING_CLOCK_TIMER_TRIGGER) */ + +#define DBG_TAG "adc.v2.trigger" +#define DBG_LVL DBG_LOG +#include + +#include "adc_v2_internal.h" + +/** + * @brief Validate an ADC hardware trigger configuration at framework level. + * @param cfg Pointer to the trigger configuration object. + * @return Operation status. + */ +static rt_err_t adc_validate_trigger_cfg_common(const struct rt_adc_trigger_cfg *cfg) +{ + switch (cfg->type) + { + case RT_ADC_TRIGGER_TIMER_UPDATE: +#if defined(RT_ADC_TRIGGER_USING_TIMER) + if ((cfg->event.timer.timer == RT_NULL) || (cfg->event.timer.timer->type != RT_Device_Class_Timer) || + (cfg->event.timer.freq_hz == 0U)) + { + return -RT_EINVAL; + } + return RT_EOK; +#else + return -RT_ENOSYS; +#endif /* defined(RT_ADC_TRIGGER_USING_TIMER) */ + + case RT_ADC_TRIGGER_TIMER_COMPARE: +#if defined(RT_ADC_TRIGGER_USING_TIMER) + if ((cfg->event.timer.timer == RT_NULL) || (cfg->event.timer.timer->type != RT_Device_Class_Timer) || + (cfg->event.timer.channel == 0U) || (cfg->event.timer.freq_hz == 0U)) + { + return -RT_EINVAL; + } + return RT_EOK; +#else + return -RT_ENOSYS; +#endif /* defined(RT_ADC_TRIGGER_USING_TIMER) */ + + case RT_ADC_TRIGGER_ANALOG_COMPARE: +#if defined(RT_ADC_TRIGGER_USING_COMPARE) + if ((cfg->event.compare.channel == 0U) || (cfg->event.compare.edge == RT_ADC_TRIGGER_EDGE_NONE)) + { + return -RT_EINVAL; + } + return RT_EOK; +#else + return -RT_ENOSYS; +#endif /* defined(RT_ADC_TRIGGER_USING_COMPARE) */ + + case RT_ADC_TRIGGER_PWM_EDGE: + case RT_ADC_TRIGGER_EXTI_EDGE: + case RT_ADC_TRIGGER_BACKEND: + return -RT_ENOSYS; + + default: + return -RT_EINVAL; + } +} + +/** + * @brief Initialize the ADC trigger control state to software-started mode. + * @param device Pointer to the ADC device object. + */ +void adc_trigger_init(rt_adc_device_t device) +{ + rt_memset(&device->trigger_ctrl, 0, sizeof(device->trigger_ctrl)); +} + +/** + * @brief Get the active device-level ADC trigger configuration. + * @param device Pointer to the ADC device object. + * @return Pointer to the cached trigger configuration, or RT_NULL when no hardware trigger is configured. + */ +const struct rt_adc_trigger_cfg *adc_trigger_active_get(rt_adc_device_t device) +{ + if (device->trigger_ctrl.configured != RT_TRUE) + { + return RT_NULL; + } + + return &device->trigger_ctrl.cfg; +} + +#if defined(RT_ADC_TRIGGER_USING_TIMER) +/** + * @brief Configure and start a timer-based ADC trigger source. + * @param cfg Pointer to the active ADC trigger configuration object. + * @return Operation status. + */ +static rt_err_t adc_trigger_timer_source_start(const struct rt_adc_trigger_cfg *cfg) +{ +#if defined(RT_USING_CLOCK_TIMER_TRIGGER) + struct rt_clock_timer_trigger_cfg timer_cfg = {0}; + rt_err_t result; + + timer_cfg.freq_hz = cfg->event.timer.freq_hz; + timer_cfg.channel = cfg->event.timer.channel; + + switch (cfg->type) + { + case RT_ADC_TRIGGER_TIMER_UPDATE: + timer_cfg.event = CLOCK_TIMER_TRIGGER_EVENT_UPDATE; + timer_cfg.channel = 0U; + break; + + case RT_ADC_TRIGGER_TIMER_COMPARE: + timer_cfg.event = CLOCK_TIMER_TRIGGER_EVENT_COMPARE; + break; + + default: + return -RT_ENOSYS; + } + + result = rt_device_control(cfg->event.timer.timer, CLOCK_TIMER_CTRL_TRIGGER_CONFIG, &timer_cfg); + if (result != RT_EOK) + { + return result; + } + + result = rt_device_control(cfg->event.timer.timer, CLOCK_TIMER_CTRL_TRIGGER_START, RT_NULL); + if (result != RT_EOK) + { + (void)rt_device_control(cfg->event.timer.timer, CLOCK_TIMER_CTRL_TRIGGER_RELEASE, RT_NULL); + return result; + } + + return RT_EOK; +#else + RT_UNUSED(cfg); + return -RT_ENOSYS; +#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */ +} + +/** + * @brief Stop and release a timer-based ADC trigger source. + * @param cfg Pointer to the active ADC trigger configuration object. + * @return Operation status. + */ +static rt_err_t adc_trigger_timer_source_stop(const struct rt_adc_trigger_cfg *cfg) +{ +#if defined(RT_USING_CLOCK_TIMER_TRIGGER) + rt_err_t stop_result; + rt_err_t release_result; + + if ((cfg->type != RT_ADC_TRIGGER_TIMER_UPDATE) && (cfg->type != RT_ADC_TRIGGER_TIMER_COMPARE)) + { + return -RT_ENOSYS; + } + + stop_result = rt_device_control(cfg->event.timer.timer, CLOCK_TIMER_CTRL_TRIGGER_STOP, RT_NULL); + release_result = rt_device_control(cfg->event.timer.timer, CLOCK_TIMER_CTRL_TRIGGER_RELEASE, RT_NULL); + + return (release_result != RT_EOK) ? release_result : stop_result; +#else + RT_UNUSED(cfg); + return -RT_ENOSYS; +#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */ +} +#endif /* defined(RT_ADC_TRIGGER_USING_TIMER) */ + +/** + * @brief Start the active trigger source after the ADC conversion path is armed. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ +static rt_err_t adc_trigger_source_start(rt_adc_device_t device) +{ + const struct rt_adc_trigger_cfg *cfg; + + cfg = adc_trigger_active_get(device); + if (cfg == RT_NULL) + { + return RT_EOK; + } + + switch (cfg->type) + { +#if defined(RT_ADC_TRIGGER_USING_TIMER) + case RT_ADC_TRIGGER_TIMER_UPDATE: + case RT_ADC_TRIGGER_TIMER_COMPARE: + return adc_trigger_timer_source_start(cfg); +#endif /* defined(RT_ADC_TRIGGER_USING_TIMER) */ + + default: + return RT_EOK; + } +} + +/** + * @brief Stop the active trigger source before the ADC conversion path is disarmed. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ +static rt_err_t adc_trigger_source_stop(rt_adc_device_t device) +{ + const struct rt_adc_trigger_cfg *cfg; + + cfg = adc_trigger_active_get(device); + if (cfg == RT_NULL) + { + return RT_EOK; + } + + switch (cfg->type) + { +#if defined(RT_ADC_TRIGGER_USING_TIMER) + case RT_ADC_TRIGGER_TIMER_UPDATE: + case RT_ADC_TRIGGER_TIMER_COMPARE: + return adc_trigger_timer_source_stop(cfg); +#endif /* defined(RT_ADC_TRIGGER_USING_TIMER) */ + + default: + return RT_EOK; + } +} + +/** + * @brief Control the active trigger source around an armed ADC conversion path. + * @param device Pointer to the ADC device object. + * @param action Trigger-source lifecycle action. + * @param started Pointer to the trigger-start state. + * @param current_result Transfer result before trigger stop, ignored for start. + * @return For start, trigger-source start result; for stop, @p current_result unless trigger stop is the first + * observed failure. + */ +rt_err_t adc_trigger_source_control(rt_adc_device_t device, enum adc_trigger_source_action action, + rt_bool_t *started, rt_err_t current_result) +{ + rt_err_t stop_result; + rt_err_t result; + + switch (action) + { + case ADC_TRIGGER_SOURCE_START: + *started = RT_FALSE; + if (adc_trigger_active_get(device) == RT_NULL) + { + return RT_EOK; + } + + result = adc_trigger_source_start(device); + if (result != RT_EOK) + { + LOG_E("trigger source start failed: device=%s result=%d", device->parent.parent.name, result); + return result; + } + + *started = RT_TRUE; + return RT_EOK; + + case ADC_TRIGGER_SOURCE_STOP: + if (*started != RT_TRUE) + { + return current_result; + } + + stop_result = adc_trigger_source_stop(device); + if (stop_result != RT_EOK) + { + LOG_E("trigger source stop failed: device=%s result=%d", device->parent.parent.name, stop_result); + if (current_result == RT_EOK) + { + current_result = stop_result; + } + } + + *started = RT_FALSE; + return current_result; + + default: + return (current_result != RT_EOK) ? current_result : -RT_EINVAL; + } +} + +/** + * @brief Preconfigure the active device-level ADC trigger before hardware configuration. + * @param device Pointer to the ADC device object. + * @return RT_EOK on success, otherwise an RT-Thread error code. + * + * @note A null active trigger still has to be passed to the backend when the + * backend provides trigger_prepare(), because some backends cache the + * previously prepared hardware trigger selector. Passing RT_NULL asks the + * backend to prepare the software-start/default trigger path. + */ +rt_err_t adc_trigger_preconfig(rt_adc_device_t device) +{ + const struct rt_adc_trigger_cfg *cfg; + + cfg = adc_trigger_active_get(device); + + if ((device->ops == RT_NULL) || (device->ops->core == RT_NULL) || (device->ops->core->trigger_prepare == RT_NULL)) + { + return (cfg == RT_NULL) ? RT_EOK : -RT_ENOSYS; + } + + return device->ops->core->trigger_prepare(device, cfg); +} + +/** + * @brief Set one device-level ADC hardware trigger request. + * @param device Pointer to the ADC device object. + * @param cfg Pointer to the ADC trigger configuration object. + * @return Operation status. + * @note This function only checks the framework-level trigger structure and + * caches the request. It does not write ADC trigger registers immediately. + * Backend compatibility is reported when the cached trigger is + * preconfigured before a stream hardware configuration. + */ +rt_err_t rt_adc_trigger_set(rt_adc_device_t device, const struct rt_adc_trigger_cfg *cfg) +{ + struct rt_adc_trigger_cfg trigger_cfg; + rt_err_t result; + rt_atomic_t old_state; + + if ((device == RT_NULL) || (cfg == RT_NULL)) + { + return -RT_EINVAL; + } + + trigger_cfg = *cfg; + old_state = (rt_atomic_t)RT_ADC_STATE_IDLE; + if (rt_atomic_compare_exchange_strong(&device->state, &old_state, (rt_atomic_t)RT_ADC_STATE_LOCKED) == 0) + { + return -RT_EBUSY; + } + + result = adc_validate_trigger_cfg_common(&trigger_cfg); + if (result == RT_EOK) + { + device->trigger_ctrl.cfg = trigger_cfg; + device->trigger_ctrl.configured = RT_TRUE; + } + + rt_atomic_store(&device->state, (rt_atomic_t)RT_ADC_STATE_IDLE); + if (result != RT_EOK) + { + LOG_E("trigger set cache failed: device=%s result=%d", device->parent.parent.name, result); + } + return result; +} + +/** + * @brief Clear the cached ADC trigger configuration. + * @param device Pointer to the ADC device object. + * @return Operation status. + * @note The ADC device must be idle so the cached trigger cannot be cleared while an active conversion is using it. + */ +rt_err_t rt_adc_trigger_clear(rt_adc_device_t device) +{ + rt_atomic_t old_state; + + if (device == RT_NULL) + { + return -RT_EINVAL; + } + + old_state = (rt_atomic_t)RT_ADC_STATE_IDLE; + if (rt_atomic_compare_exchange_strong(&device->state, &old_state, (rt_atomic_t)RT_ADC_STATE_LOCKED) == 0) + { + return -RT_EBUSY; + } + + rt_memset(&device->trigger_ctrl, 0, sizeof(device->trigger_ctrl)); + rt_atomic_store(&device->state, (rt_atomic_t)RT_ADC_STATE_IDLE); + + LOG_D("trigger cleared: device=%s", device->parent.parent.name); + return RT_EOK; +} + +/** + * @brief Check whether one ADC device has a cached hardware trigger request. + * @param device Pointer to the ADC device object. + * @return RT_TRUE if a hardware trigger request is set, otherwise RT_FALSE. + */ +rt_bool_t rt_adc_trigger_is_set(rt_adc_device_t device) +{ + if (device == RT_NULL) + { + return RT_FALSE; + } + + return device->trigger_ctrl.configured; +} + +#endif /* defined(RT_USING_ADC_V2) && defined(RT_ADC_USING_TRIGGER) */ diff --git a/components/drivers/clock_time/Kconfig b/components/drivers/clock_time/Kconfig index d6259617aa0..46dd2714838 100644 --- a/components/drivers/clock_time/Kconfig +++ b/components/drivers/clock_time/Kconfig @@ -2,6 +2,17 @@ menuconfig RT_USING_CLOCK_TIME bool "Clock time subsystem" default n +config RT_USING_CLOCK_TIMER_TRIGGER + bool "Enable clock timer hardware trigger output" + depends on RT_USING_CLOCK_TIME + default n + help + Enable clock timer hardware trigger output controls. Timer backends + may use this to expose update/TRGO trigger events to ADC drivers. The + selected timer must be dedicated to trigger output; the framework does + not arbitrate shared use with clock-time timeouts, PWM, or other timer + consumers. + if RT_USING_CLOCK_TIME config CLOCK_TIMER_FREQ int "Clock time timer freq" diff --git a/components/drivers/include/drivers/adc_v2.h b/components/drivers/include/drivers/adc_v2.h new file mode 100644 index 00000000000..bf369e3a50c --- /dev/null +++ b/components/drivers/include/drivers/adc_v2.h @@ -0,0 +1,622 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-04-21 wdfk-prog add standalone adc v2 framework interface + */ + +/** + * @file adc_v2.h + * @brief Standalone ADC V2 framework declarations. + */ + +#ifndef __ADC_V2_H__ +#define __ADC_V2_H__ + +#include +#include "misc.h" +#if !defined(RT_USING_ADC_V2) +#error "ADC V2 interface requires RT_USING_ADC_V2." +#endif /* !defined(RT_USING_ADC_V2) */ + +#include +#include +#include + +#if defined(RT_ADC_USING_TRIGGER) +#include +#endif /* defined(RT_ADC_USING_TRIGGER) */ + +#if defined(RT_ADC_USING_STREAM) && defined(RT_ADC_STREAM_USING_FIFO) +#include +#include +#endif /* defined(RT_ADC_USING_STREAM) && defined(RT_ADC_STREAM_USING_FIFO) */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief ADC control command identifiers. + */ +enum rt_adc_control_cmd +{ + RT_ADC_CMD_GET_RESOLUTION = RT_DEVICE_CTRL_BASE(ADC) + 1, /**< Get resolution in bits. */ + RT_ADC_CMD_CALIBRATE, /**< Run ADC calibration. */ + RT_ADC_CMD_SET_VREF, /**< Set fallback VREF from rt_uint32_t mV. */ + RT_ADC_CMD_CALC_VREF, /**< Calculate VDDA from a raw VREF sample. */ + RT_ADC_CMD_GET_VREF_CHANNEL, /**< Get the backend VREF sample channel as rt_uint8_t. */ + RT_ADC_CMD_SET_SESSION, /**< Configure and cache conversion channels from rt_uint32_t mask. */ + RT_ADC_CMD_SET_CONFIG, /**< Set backend private device configuration. */ + RT_ADC_CMD_GET_CONFIG, /**< Get backend private device configuration. */ + RT_ADC_CMD_CLEAR_CHANNEL_CONFIG /**< Clear backend channel/rank configuration explicitly. */ +}; + +/** + * @brief ADC input mode request flags. + */ +enum rt_adc_input_mode +{ + RT_ADC_INPUT_MODE_SINGLE_ENDED = 0x01U, /**< Single-ended ADC input mode. */ + RT_ADC_INPUT_MODE_DIFFERENTIAL = 0x02U /**< Differential ADC input mode. */ +}; + +/** + * @brief Build an ADC channel mask from one logical channel index. + * @param _channel Logical ADC channel index. + */ +#define RT_ADC_CHANNEL_MASK(_channel) (1UL << (rt_uint32_t)(_channel)) + +/** + * @brief ADC framework runtime state. + */ +enum rt_adc_state +{ + RT_ADC_STATE_IDLE = 0, /**< The ADC device is idle. */ + RT_ADC_STATE_LOCKED, /**< The ADC device is temporarily locked by a framework operation. */ + RT_ADC_STATE_STREAM /**< The ADC device is owned by an active stream session. */ +}; + +struct rt_adc_device; +typedef struct rt_adc_device *rt_adc_device_t; + +struct rt_adc_sequence_cfg; +struct rt_adc_stream_cfg; + +/** + * @brief ADC core driver operation table. + */ +struct rt_adc_core_ops +{ + /** + * @brief Open and initialize the ADC hardware. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ + rt_err_t (*open)(struct rt_adc_device *device); + + /** + * @brief Close and deinitialize the ADC hardware. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ + rt_err_t (*close)(struct rt_adc_device *device); + + + /** + * @brief Configure one ADC conversion session before data transfer. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @return Operation status. + */ + rt_err_t (*session_config)(struct rt_adc_device *device, rt_uint32_t channels); + +#if defined(RT_ADC_USING_TRIGGER) + /** + * @brief Preconfigure the ADC backend trigger state for the next hardware configuration pass. + * @param device Pointer to the ADC device object. + * @param cfg Pointer to the active ADC trigger configuration object. + * @return Operation status. + * @note The implementation may only validate @p cfg, update pending driver + * state, or fill HAL initialization fields. It must not start the + * trigger source or arm ADC conversions. + */ + rt_err_t (*trigger_prepare)(struct rt_adc_device *device, const struct rt_adc_trigger_cfg *cfg); +#endif /* defined(RT_ADC_USING_TRIGGER) */ + + /** + * @brief Handle ADC control commands. + * @param device Pointer to the ADC device object. + * @param cmd Control command. + * @param args Pointer to the control argument buffer. + * @return Operation status. + */ + rt_err_t (*control)(struct rt_adc_device *device, int cmd, void *args); +}; + +/** + * @brief ADC finite-sequence operation table. + */ +struct rt_adc_sequence_ops +{ + /** + * @brief Start one active finite transfer session. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the sequence request object. + * @return Operation status. + */ + rt_err_t (*start)(struct rt_adc_device *device, rt_uint32_t channels, const struct rt_adc_sequence_cfg *cfg); + + /** + * @brief Read one converted sample from an active finite transfer session. + * @param device Pointer to the ADC device object. + * @param value Pointer to the output sample value. + * @param timeout_ms Read timeout in milliseconds; negative means wait forever. + * @return Operation status. + */ + rt_err_t (*read)(struct rt_adc_device *device, rt_uint32_t *value, rt_int32_t timeout_ms); + + /** + * @brief Stop one active finite transfer session. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ + rt_err_t (*stop)(struct rt_adc_device *device); +}; + +#ifdef RT_ADC_USING_STREAM +/** + * @brief ADC stream operation table. + */ +struct rt_adc_stream_ops +{ + /** + * @brief Start one active stream session. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the stream configuration object. + * @return Operation status. + */ + rt_err_t (*start)(struct rt_adc_device *device, rt_uint32_t channels, const struct rt_adc_stream_cfg *cfg); + + /** + * @brief Synchronize a backend DMA sample range before CPU access. + * @param device Pointer to the ADC device object. + * @param sample_buffer Pointer to the DMA sample buffer. + * @param sample_count Number of samples to synchronize. + * @return Operation status. + */ + rt_err_t (*sync)(struct rt_adc_device *device, const rt_uint32_t *sample_buffer, rt_size_t sample_count); + + /** + * @brief Stop one active stream session. + * @param device Pointer to the ADC device object. + * @param hardware_stopped Pointer to the hardware-stop state output. + * @return Operation status. + * + * The backend sets @p hardware_stopped to RT_TRUE after the ADC hardware + * conversion path has stopped. When this callback returns an error with + * @p hardware_stopped set to RT_TRUE, the framework treats it as a + * post-stop cleanup failure and moves the stream to IDLE. + */ + rt_err_t (*stop)(struct rt_adc_device *device, rt_bool_t *hardware_stopped); +}; +#endif /* RT_ADC_USING_STREAM */ + + +/** + * @brief ADC driver operation table. + */ +struct rt_adc_ops +{ + const struct rt_adc_core_ops *core; /**< Core operation table. */ + const struct rt_adc_sequence_ops *sequence; /**< Sequence-session operations. */ +#ifdef RT_ADC_USING_STREAM + const struct rt_adc_stream_ops *stream; /**< Stream-session operations. */ +#endif /* RT_ADC_USING_STREAM */ +}; + +/** + * @brief ADC synchronous one-frame sequence request. + */ +struct rt_adc_sequence_cfg +{ + rt_uint32_t *buffer; /**< Destination sample buffer. */ + rt_size_t buffer_length; /**< Destination buffer length in samples. */ + rt_int32_t timeout_ms; /**< Per-sample timeout; negative means wait forever. */ +}; + +#ifdef RT_ADC_USING_STREAM +/** + * @brief ADC stream backend event. + */ +enum rt_adc_stream_event +{ + RT_ADC_STREAM_EVENT_DMA_HALF = 0x01U, /**< ADC stream DMA half-transfer event. */ + RT_ADC_STREAM_EVENT_DMA_DONE = 0x02U, /**< ADC stream DMA transfer-complete event. */ + RT_ADC_STREAM_EVENT_ERROR = 0x03U /**< ADC stream backend error event. */ +}; + +/** + * @brief ADC stream buffering policy. + */ +enum rt_adc_stream_policy +{ +#ifdef RT_ADC_STREAM_USING_LATEST + /** + * @brief Keep only the latest ADC rank values. + * + * This policy is intended for slow-changing ADC values such as battery + * voltage, temperature, potentiometer input, resistor-divider voltage, or + * board status monitoring. Old values may be overwritten. + * + * In this policy, @ref rt_adc_stream_cfg::dma_buffer_length must be exactly + * equal to the active ADC frame length, namely the number of enabled ADC + * ranks. The backend must expose the DMA buffer as a single latest-frame + * layout: + * + * - dma_buffer[0] stores the latest value of ADC rank 1. + * - dma_buffer[1] stores the latest value of ADC rank 2. + * - dma_buffer[n] stores the latest value of ADC rank n + 1. + * + * STM32 regular scan conversion with circular DMA naturally satisfies this + * layout when the DMA length equals the ADC rank count. Backends for other + * platforms may also support this policy if their DMA engine writes samples + * in scan-rank order. If a backend produces packed, interleaved, + * descriptor-based, hardware-FIFO, or otherwise non-rank-ordered data, it + * must either convert the data into this latest-frame layout internally or + * reject the configuration with -RT_ENOSYS. + * + * @note Latest mode is a low-overhead lockless DMA-buffer view. CPU-side + * atomic operations, spin locks, mutexes, or read-write locks cannot + * prevent the DMA engine from updating memory concurrently, because + * DMA does not participate in CPU locking protocols. This mode only + * guarantees that each buffer index maps to the corresponding ADC rank + * latest value; it does not guarantee that the copied frame is a + * single hardware scan-cycle snapshot. Use RT_ADC_STREAM_POLICY_FIFO + * when ordered and frame-accurate samples are required. + */ + RT_ADC_STREAM_POLICY_LATEST = 0, +#endif /* RT_ADC_STREAM_USING_LATEST */ +#ifdef RT_ADC_STREAM_USING_FIFO + /** + * @brief Preserve ADC samples in FIFO order. + * + * This policy is intended for continuous and loss-sensitive sampling such + * as waveform, current, vibration, audio-like, motor-control, or + * control-loop data where each sample matters. + * + * The backend reports completed DMA blocks to the ADC framework. The + * framework copies those blocks into a ringbuffer and wakes blocking readers + * through a completion object. + */ + RT_ADC_STREAM_POLICY_FIFO, +#endif /* RT_ADC_STREAM_USING_FIFO */ +}; + +/** + * @brief ADC stream DMA data event mode. + */ +enum rt_adc_stream_dma_event_mode +{ + RT_ADC_STREAM_DMA_EVENT_AUTO = 0, /**< Use the default event mode for the selected stream policy. */ + RT_ADC_STREAM_DMA_EVENT_NONE, /**< Disable DMA half/full data events; DMA error events remain enabled. */ + RT_ADC_STREAM_DMA_EVENT_FULL_ONLY, /**< Report only DMA transfer-complete data events to reduce interrupt rate. */ + RT_ADC_STREAM_DMA_EVENT_HALF_FULL /**< Report both DMA half-transfer and transfer-complete data events. */ +}; + +/** + * @brief ADC stream FIFO data callback type. + * @param device Pointer to the ADC device object. + * @param sample_count Number of newly accepted samples. + * @param user_data Pointer to the user context. + * @note This callback is invoked from ADC stream ISR context. It must not + * block, sleep, or call APIs that may suspend the current context. + */ +typedef void (*rt_adc_stream_callback_t)(struct rt_adc_device *device, rt_size_t sample_count, void *user_data); + +/** + * @brief ADC stream configuration. + * @note The DMA buffer belongs to the caller and must remain valid until + * rt_adc_stream_stop() returns. The stream configuration object only + * needs to remain valid for the duration of rt_adc_stream_start(). A + * backend may use an internal cache-aligned DMA buffer when the caller + * buffer is not safe for platform cache maintenance. Backend drivers must + * copy scalar configuration fields they need after rt_adc_stream_start() + * returns. + */ +struct rt_adc_stream_cfg +{ + enum rt_adc_stream_policy policy; /**< Stream buffering policy. */ + enum rt_adc_stream_dma_event_mode dma_event_mode; /**< DMA half/full data event mode. */ + + /** + * @brief DMA circular staging buffer. + * + * For RT_ADC_STREAM_POLICY_LATEST, this buffer stores exactly one latest + * ADC scan frame. dma_buffer_length must equal the active frame length. + * Each element maps to one configured ADC rank. + * + * For RT_ADC_STREAM_POLICY_FIFO, this buffer is a DMA staging buffer. The + * default rt_adc_stream_start() entry validates only basic buffer presence + * and capacity. It does not require each DMA data-event block to end on an + * ADC scan-frame boundary. + * + * Use rt_adc_stream_start_frame_aligned_fifo() when continuous FIFO sampling + * requires a strict frame-aligned DMA/FIFO layout before the stream starts. + */ + rt_uint32_t *dma_buffer; + + /** + * @brief DMA buffer length in samples. + */ + rt_size_t dma_buffer_length; +#ifdef RT_ADC_STREAM_USING_FIFO + rt_uint32_t *fifo_buffer; /**< FIFO storage for FIFO policy. */ + rt_size_t fifo_buffer_length; /**< FIFO buffer length in samples. */ + rt_size_t watermark; /**< FIFO wakeup or callback threshold in samples. */ + rt_adc_stream_callback_t callback; /**< Optional ISR-context FIFO data callback. */ + void *user_data; /**< User data passed to the FIFO data callback. */ +#endif /* RT_ADC_STREAM_USING_FIFO */ +}; + +/** + * @brief ADC stream runtime control block owned by the ADC framework. + */ +struct rt_adc_stream_ctrl +{ + rt_bool_t active; /**< Whether a stream backend session is active. */ + enum rt_adc_stream_policy policy; /**< Active stream buffering policy. */ + enum rt_adc_stream_dma_event_mode dma_event_mode; /**< Active DMA data event mode. */ + rt_uint32_t *dma_buffer; /**< DMA circular staging buffer. */ + rt_size_t dma_buffer_length; /**< DMA buffer length in samples. */ + rt_size_t frame_length; /**< Samples in one ADC scan frame. */ +#ifdef RT_ADC_STREAM_USING_FIFO + struct rt_ringbuffer fifo; /**< FIFO storage for FIFO policy. */ + rt_bool_t fifo_enabled; /**< FIFO initialized flag. */ + /** + * @brief Reader wake completion for FIFO stream. + * + * The FIFO ringbuffer is the source of truth for available data. This + * completion object is only a wakeup edge for blocking reads. + */ + struct rt_completion rx_cpt; + rt_size_t overflow_count; /**< FIFO overrun count. */ + rt_size_t watermark; /**< FIFO wakeup or callback threshold. */ + rt_adc_stream_callback_t callback; /**< Optional FIFO data callback. */ + void *user_data; /**< Callback private data. */ +#endif /* RT_ADC_STREAM_USING_FIFO */ + rt_atomic_t last_error; /**< Atomic last stream backend error. */ +}; +#endif /* RT_ADC_USING_STREAM */ + +/** + * @brief ADC active session runtime control block. + */ +struct rt_adc_session_ctrl +{ + rt_uint32_t channels; /**< Cached active ADC channel selection mask. */ + rt_size_t channel_count; /**< Cached active session channel count. */ + rt_bool_t configured; /**< Whether the cached session configuration is valid. */ +}; + +/** + * @brief ADC device object. + */ +struct rt_adc_device +{ + struct rt_device parent; /**< RT-Thread device object. */ + const struct rt_adc_ops *ops; /**< ADC driver operation table. */ + rt_atomic_t state; /**< Atomic ADC runtime state. */ + struct rt_spinlock spinlock; /**< Protects ADC stream FIFO shared by thread context and ISR. */ + rt_uint32_t default_vref_mv; /**< Default reference voltage in millivolts. */ + struct rt_adc_session_ctrl session_ctrl; /**< ADC active session control block. */ +#if defined(RT_ADC_USING_TRIGGER) + struct rt_adc_trigger_ctrl trigger_ctrl; /**< ADC trigger runtime control block. */ +#endif /* defined(RT_ADC_USING_TRIGGER) */ +#ifdef RT_ADC_USING_STREAM + struct rt_adc_stream_ctrl stream_ctrl; /**< ADC stream runtime control block. */ +#endif /* RT_ADC_USING_STREAM */ +}; + +/** + * @brief Count selected ADC channels in one channel mask. + * @param channels ADC channel selection mask. + * @return Number of selected channels. + */ +rt_inline rt_size_t rt_adc_channel_mask_count(rt_uint32_t channels) +{ +#if defined(__GNUC__) || defined(__clang__) + return (rt_size_t)__builtin_popcount((unsigned int)channels); +#else + rt_size_t count; + + count = 0U; + while (channels != 0U) + { + channels &= channels - 1U; + count++; + } + + return count; +#endif /* defined(__GNUC__) || defined(__clang__) */ +} + +/** + * @brief Take the lowest selected ADC channel from one channel mask. + * @param channels Pointer to the ADC channel selection mask. + * @return Selected channel index, or 0xff if the mask is empty. + */ +rt_inline rt_uint8_t rt_adc_channel_mask_take_lsb(rt_uint32_t *channels) +{ + rt_uint8_t bit; + + if ((channels == RT_NULL) || (*channels == 0U)) + { + return 0xffU; + } + +#if defined(__GNUC__) || defined(__clang__) + bit = (rt_uint8_t)__builtin_ctz((unsigned int)*channels); +#else + for (bit = 0U; bit < 32U; bit++) + { + if ((*channels & RT_ADC_CHANNEL_MASK(bit)) != 0U) + { + break; + } + } +#endif /* defined(__GNUC__) || defined(__clang__) */ + + *channels &= ~RT_ADC_CHANNEL_MASK(bit); + return bit; +} + +/** + * @brief Register an ADC device with the RT-Thread device framework. + * @param device Pointer to the ADC device object. + * @param name Pointer to the ADC device name string. + * @param ops Pointer to the ADC driver operation table. + * @param user_data Pointer to driver private data. + * @return Operation status. + */ +rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const struct rt_adc_ops *ops, const void *user_data); + +/** + * @brief Get the raw sample index of one channel in an ADC session mask. + * @param session_channels Configured ADC session channel mask. + * @param channel Single-channel mask to locate. + * @param index Pointer to the output raw sample index. + * @return Operation status. + */ +rt_err_t rt_adc_session_channel_index(rt_uint32_t session_channels, rt_uint32_t channel, rt_size_t *index); + + +/** + * @brief Read one ADC conversion sequence frame. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the ADC sequence request object. + * @param read_count Pointer to the stored sample count. + * @return Operation status. + */ +rt_err_t rt_adc_read_sequence(rt_adc_device_t device, rt_uint32_t channels, + const struct rt_adc_sequence_cfg *cfg, rt_size_t *read_count); + +#ifdef RT_ADC_USING_STREAM +/** + * @brief Start one ADC stream session. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the ADC stream configuration object. + * @return Operation status. + */ +rt_err_t rt_adc_stream_start(rt_adc_device_t device, rt_uint32_t channels, const struct rt_adc_stream_cfg *cfg); + +#ifdef RT_ADC_STREAM_USING_FIFO +/** + * @brief Start one FIFO ADC stream with strict frame-aligned buffer layout. + * @param device Pointer to the ADC device object. + * @param channels ADC channel selection mask. + * @param cfg Pointer to the ADC stream configuration object. + * @return Operation status. + */ +rt_err_t rt_adc_stream_start_frame_aligned_fifo(rt_adc_device_t device, rt_uint32_t channels, const struct rt_adc_stream_cfg *cfg); +#endif /* RT_ADC_STREAM_USING_FIFO */ + +/** + * @brief Read converted samples from an active ADC stream session. + * @param device Pointer to the ADC device object. + * @param buffer Pointer to the destination sample buffer. + * @param sample_count Number of samples to read. + * @param timeout_ms Read timeout in milliseconds; negative means wait forever. + * @return Number of samples read, or a negative RT-Thread error code. + */ +rt_ssize_t rt_adc_stream_read(rt_adc_device_t device, rt_uint32_t *buffer, rt_size_t sample_count, rt_int32_t timeout_ms); + +/** + * @brief Cancel a blocked ADC stream reader before stream shutdown. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ +rt_err_t rt_adc_stream_cancel(rt_adc_device_t device); + +/** + * @brief Stop one ADC stream session. + * @param device Pointer to the ADC device object. + * @return Operation status. + */ +rt_err_t rt_adc_stream_stop(rt_adc_device_t device); + +/** + * @brief Notify the ADC framework of one stream backend event. + * @param device Pointer to the ADC device object. + * @param event ADC stream event reported by the backend or ISR. + * @param sample_buffer Pointer to the completed sample buffer block. + * @param sample_count Number of samples in @p sample_buffer. + * @return Operation status. + */ +rt_err_t rt_hw_adc_stream_isr(rt_adc_device_t device, enum rt_adc_stream_event event, + const rt_uint32_t *sample_buffer, rt_size_t sample_count); +#endif /* RT_ADC_USING_STREAM */ + +/** + * @brief Convert one raw ADC sample to millivolts. + * @param raw_value Raw ADC sample value. + * @param vref_mv ADC reference voltage in millivolts. + * @param resolution_bits ADC resolution in bits. + * @param voltage_mv Pointer to the output voltage in millivolts. + * @return Operation status. + */ +rt_err_t rt_adc_raw_to_voltage_mv(rt_uint32_t raw_value, rt_uint32_t vref_mv, rt_uint8_t resolution_bits, rt_uint32_t *voltage_mv); + +/** + * @brief Convert one ADC raw sample to a scaled voltage in millivolts. + * @param raw_value Raw ADC sample code. + * @param vref_mv ADC reference voltage in millivolts. + * @param resolution_bits ADC resolution in bits. + * @param scale_num Voltage scaling numerator. + * @param scale_den Voltage scaling denominator. + * @param voltage_mv Pointer to the output scaled voltage in millivolts. + * @return Operation status. + * + * The scaled voltage is calculated as: + * + * raw_to_voltage_mv(raw_value) * scale_num / scale_den + * + * @note @p scale_num and @p scale_den may describe any positive rational + * scaling ratio that does not overflow the internal calculation. The + * final scaled millivolt value must fit in rt_uint32_t. + * + * @retval RT_EOK The conversion completed successfully. + * @retval -RT_EINVAL A pointer is null, a scale argument is zero, the ADC + * conversion arguments are invalid, or the scaled result overflows + * rt_uint32_t. + */ +rt_err_t rt_adc_raw_to_scaled_voltage_mv(rt_uint32_t raw_value, rt_uint32_t vref_mv, rt_uint8_t resolution_bits, rt_uint32_t scale_num, rt_uint32_t scale_den, rt_uint32_t *voltage_mv); + +/** + * @brief Read ADC samples and convert them to millivolts. + * @param device Pointer to the ADC device object. + * @param voltages_mv Pointer to the output voltage buffer in millivolts. + * @param size Output voltage buffer length. + * @param timeout_ms Per-sample timeout in milliseconds; negative means wait forever. + * @return Operation status. + * + * @note This API reads the currently configured ADC session and does not modify + * the active channel mask. If default_vref_mv is zero, callers that need + * backend-calculated VDDA must include the backend VREF channel in the + * configured session. The VREF sample is used only as the reference for + * conversion and is not auto-inserted by this API. + */ +rt_err_t rt_adc_voltage(rt_adc_device_t device, rt_uint32_t *voltages_mv, rt_size_t size, rt_int32_t timeout_ms); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ADC_V2_H__ */ diff --git a/components/drivers/include/drivers/adc_v2_trigger.h b/components/drivers/include/drivers/adc_v2_trigger.h new file mode 100644 index 00000000000..bb328b8dba2 --- /dev/null +++ b/components/drivers/include/drivers/adc_v2_trigger.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-05-20 wdfk-prog add ADC V2 trigger declarations + */ + +/** + * @file adc_v2_trigger.h + * @brief ADC V2 trigger framework declarations. + */ + +#ifndef __ADC_V2_TRIGGER_H__ +#define __ADC_V2_TRIGGER_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if defined(RT_ADC_USING_TRIGGER) +struct rt_adc_device; +struct rt_device; + +/** + * @brief ADC hardware trigger event type. + * + * @note A platform backend may support only part of these trigger types. + * Unsupported trigger types shall be rejected by the framework or backend + * with an error such as -RT_ENOSYS. + */ +enum rt_adc_trigger_type +{ + RT_ADC_TRIGGER_TIMER_UPDATE = 0, /**< Use a timer update/TRGO event. */ + RT_ADC_TRIGGER_TIMER_COMPARE, /**< Use a timer compare event. */ + RT_ADC_TRIGGER_PWM_EDGE, /**< Use a PWM edge event. */ + RT_ADC_TRIGGER_EXTI_EDGE, /**< Use an external interrupt edge event. */ + RT_ADC_TRIGGER_ANALOG_COMPARE, /**< Use an analog comparator event. */ + RT_ADC_TRIGGER_BACKEND, /**< Use a backend-specific trigger event. */ +}; + +/** + * @brief ADC trigger edge selector. + */ +enum rt_adc_trigger_edge +{ + RT_ADC_TRIGGER_EDGE_NONE = 0, /**< No edge selection is required. */ + RT_ADC_TRIGGER_EDGE_RISING, /**< Use the rising edge. */ + RT_ADC_TRIGGER_EDGE_FALLING, /**< Use the falling edge. */ + RT_ADC_TRIGGER_EDGE_BOTH, /**< Use both rising and falling edges. */ +}; + +/** + * @brief Timer-based ADC trigger event. + */ +struct rt_adc_trigger_timer_event +{ + struct rt_device *timer; /**< Timer device used as trigger source. */ + rt_uint32_t freq_hz; /**< Timer trigger output frequency in hertz. */ + rt_uint16_t channel; /**< Timer channel, or 0 for update/TRGO event. */ + rt_uint16_t reserved; /**< Reserved for future extension. */ +}; + +/** + * @brief PWM-based ADC trigger event. + */ +struct rt_adc_trigger_pwm_event +{ + struct rt_device *pwm; /**< PWM device used as trigger source. */ + rt_uint16_t channel; /**< PWM channel. */ + enum rt_adc_trigger_edge edge; /**< PWM edge used as trigger event. */ +}; + +/** + * @brief External interrupt ADC trigger event. + */ +struct rt_adc_trigger_exti_event +{ + struct rt_device *pin; /**< Pin or GPIO controller device. */ + rt_uint16_t line; /**< External interrupt line or pin number. */ + enum rt_adc_trigger_edge edge; /**< Interrupt edge used as trigger event. */ +}; + +/** + * @brief Analog comparator ADC trigger event. + */ +struct rt_adc_trigger_compare_event +{ + struct rt_device *comparator; /**< Optional comparator device used as trigger source. */ + rt_uint16_t channel; /**< Comparator channel or instance index. */ + enum rt_adc_trigger_edge edge; /**< Comparator output edge used as trigger event. */ +}; + +/** + * @brief Backend-specific ADC trigger event. + */ +struct rt_adc_trigger_backend_event +{ + rt_uint32_t selector; /**< Backend-specific trigger selector. */ + rt_uint32_t edge; /**< Backend-specific edge selector. */ + const void *data; /**< Optional backend-specific configuration. */ + rt_size_t data_size; /**< Size of backend-specific configuration. */ +}; + +/** + * @brief ADC trigger configuration. + */ +struct rt_adc_trigger_cfg +{ + enum rt_adc_trigger_type type; /**< Trigger event type. */ + rt_uint32_t flags; /**< Common trigger flags, reserved for future extension. */ + + union + { + struct rt_adc_trigger_timer_event timer; /**< Timer trigger event. */ + struct rt_adc_trigger_pwm_event pwm; /**< PWM trigger event. */ + struct rt_adc_trigger_exti_event exti; /**< External interrupt trigger event. */ + struct rt_adc_trigger_compare_event compare; /**< Comparator trigger event. */ + struct rt_adc_trigger_backend_event backend; /**< Backend-specific trigger event. */ + } event; /**< Trigger event payload. */ +}; + +/** + * @brief ADC trigger runtime control block. + */ +struct rt_adc_trigger_ctrl +{ + struct rt_adc_trigger_cfg cfg; /**< Cached device-level hardware trigger configuration. */ + rt_bool_t configured; /**< Whether cfg contains a cached hardware trigger request. */ +}; + +/** + * @brief Set one device-level ADC hardware trigger request. + * @param device Pointer to the ADC device object. + * @param cfg Pointer to the ADC trigger configuration object. + * @return Operation status. + * @note This function only checks the framework-level trigger structure and + * caches the request. It does not write ADC trigger registers immediately. + * Backend compatibility is reported when the cached trigger is + * preconfigured before a conversion hardware configuration. + */ +rt_err_t rt_adc_trigger_set(struct rt_adc_device *device, const struct rt_adc_trigger_cfg *cfg); + +/** + * @brief Clear the cached device-level ADC hardware trigger request. + * @param device Pointer to the ADC device object. + * @return Operation status. + * @note This function does not write ADC trigger registers immediately. The + * next conversion hardware configuration preconfigures the backend + * software/default trigger state. + */ +rt_err_t rt_adc_trigger_clear(struct rt_adc_device *device); + +/** + * @brief Check whether one ADC device has a cached hardware trigger request. + * @param device Pointer to the ADC device object. + * @return RT_TRUE if a hardware trigger request is set, otherwise RT_FALSE. + */ +rt_bool_t rt_adc_trigger_is_set(struct rt_adc_device *device); +#endif /* defined(RT_ADC_USING_TRIGGER) */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ADC_V2_TRIGGER_H__ */ diff --git a/components/drivers/include/drivers/clock_time.h b/components/drivers/include/drivers/clock_time.h index 7374b97d005..c43c079eb0b 100644 --- a/components/drivers/include/drivers/clock_time.h +++ b/components/drivers/include/drivers/clock_time.h @@ -47,9 +47,41 @@ typedef enum CLOCK_TIMER_CTRL_FREQ_SET = RT_DEVICE_CTRL_BASE(Timer) + 0x01, CLOCK_TIMER_CTRL_STOP = RT_DEVICE_CTRL_BASE(Timer) + 0x02, CLOCK_TIMER_CTRL_INFO_GET = RT_DEVICE_CTRL_BASE(Timer) + 0x03, - CLOCK_TIMER_CTRL_MODE_SET = RT_DEVICE_CTRL_BASE(Timer) + 0x04 + CLOCK_TIMER_CTRL_MODE_SET = RT_DEVICE_CTRL_BASE(Timer) + 0x04, +#if defined(RT_USING_CLOCK_TIMER_TRIGGER) + CLOCK_TIMER_CTRL_TRIGGER_CONFIG = RT_DEVICE_CTRL_BASE(Timer) + 0x05, + CLOCK_TIMER_CTRL_TRIGGER_START = RT_DEVICE_CTRL_BASE(Timer) + 0x06, + CLOCK_TIMER_CTRL_TRIGGER_STOP = RT_DEVICE_CTRL_BASE(Timer) + 0x07, + CLOCK_TIMER_CTRL_TRIGGER_RELEASE = RT_DEVICE_CTRL_BASE(Timer) + 0x08 +#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */ } rt_clock_timer_ctrl_t; +#if defined(RT_USING_CLOCK_TIMER_TRIGGER) +/** + * @brief Hardware timer trigger output event type. + */ +enum rt_clock_timer_trigger_event +{ + CLOCK_TIMER_TRIGGER_EVENT_UPDATE = 0, /**< Generate trigger on timer update/overflow event. */ + CLOCK_TIMER_TRIGGER_EVENT_COMPARE, /**< Generate trigger on timer compare match event. */ + CLOCK_TIMER_TRIGGER_EVENT_PWM_EDGE, /**< Generate trigger on timer PWM output reference edge. */ + CLOCK_TIMER_TRIGGER_EVENT_BACKEND /**< Generate trigger from a backend-specific timer event. */ +}; + +/** + * @brief Hardware trigger output configuration. + * @note This interface does not arbitrate timer ownership. Callers must + * provide a timer dedicated to hardware trigger output. + */ +struct rt_clock_timer_trigger_cfg +{ + rt_uint32_t freq_hz; /**< Trigger output frequency in hertz. */ + enum rt_clock_timer_trigger_event event; /**< Timer event used as trigger output. */ + rt_uint16_t channel; /**< Timer compare channel, or 0 for update event. */ + rt_uint16_t reserved; /**< Reserved for future extension. */ +}; +#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */ + typedef enum { CLOCK_TIMER_MODE_ONESHOT = 0x01, diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index 3d5aa23c44a..6cb25e856bd 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -259,9 +259,11 @@ extern "C" { #include "drivers/dev_audio.h" #endif /* RT_USING_AUDIO */ -#ifdef RT_USING_ADC +#ifdef RT_USING_ADC_V2 +#include "drivers/adc_v2.h" +#elif defined(RT_USING_ADC) #include "drivers/adc.h" -#endif /* RT_USING_ADC */ +#endif /* RT_USING_ADC_V2 */ #ifdef RT_USING_DAC #include "drivers/dac.h" diff --git a/components/drivers/misc/Kconfig b/components/drivers/misc/Kconfig index 0a7788bce57..71f42ee67bf 100644 --- a/components/drivers/misc/Kconfig +++ b/components/drivers/misc/Kconfig @@ -1,11 +1,3 @@ -menuconfig RT_USING_ADC - bool "Using ADC device drivers" - default n - -if RT_USING_DM && RT_USING_ADC - osource "$(SOC_DM_ADC_DIR)/Kconfig" -endif - config RT_USING_DAC bool "Using DAC device drivers" default n diff --git a/components/drivers/misc/SConscript b/components/drivers/misc/SConscript index 5b74ac93e59..23727a5ce9b 100644 --- a/components/drivers/misc/SConscript +++ b/components/drivers/misc/SConscript @@ -5,9 +5,6 @@ src = [] CPPPATH = [cwd + '/../include'] group = [] -if GetDepend(['RT_USING_ADC']): - src = src + ['adc.c'] - if GetDepend(['RT_USING_DAC']): src = src + ['dac.c']