From 6ce00a2b0f4c464c2acee4ab21b991247fbbb9ee Mon Sep 17 00:00:00 2001 From: wdfk-prog <1425075683@qq.com> Date: Thu, 4 Jun 2026 10:32:57 +0800 Subject: [PATCH 1/6] feat[ADC V2]: add ADC V2 driver support add ADC V2 core APIs, session state management, and sequence read support add STM32 ADC V2 HAL backend with internal-channel and VREF handling add per-series STM32 ADC V2 default configuration headers wire ADC V2 Kconfig and SConscript integration for components and STM32 BSP drivers keep ADC V2 mutually exclusive with the legacy ADC driver path --- .../libraries/HAL_Drivers/drivers/Kconfig | 34 +- .../libraries/HAL_Drivers/drivers/SConscript | 3 + .../drivers/config/f0/adc_config_v2.h | 155 ++ .../drivers/config/f1/adc_config_v2.h | 148 ++ .../drivers/config/f2/adc_config_v2.h | 160 ++ .../drivers/config/f3/adc_config_v2.h | 187 +++ .../drivers/config/f4/adc_config_v2.h | 160 ++ .../drivers/config/f7/adc_config_v2.h | 160 ++ .../drivers/config/g0/adc_config_v2.h | 112 ++ .../drivers/config/g4/adc_config_v2.h | 194 +++ .../drivers/config/h5/adc_config_v2.h | 155 ++ .../drivers/config/h7/adc_config_v2.h | 169 ++ .../drivers/config/h7rs/adc_config_v2.h | 149 ++ .../drivers/config/l0/adc_config_v2.h | 121 ++ .../drivers/config/l4/adc_config_v2.h | 175 ++ .../drivers/config/l5/adc_config_v2.h | 137 ++ .../drivers/config/mp1/adc_config_v2.h | 160 ++ .../drivers/config/u5/adc_config_v2.h | 204 +++ .../drivers/config/wb/adc_config_v2.h | 151 ++ .../drivers/config/wl/adc_config_v2.h | 117 ++ .../HAL_Drivers/drivers/drv_adc_v2.c | 1404 +++++++++++++++++ .../HAL_Drivers/drivers/drv_adc_v2.h | 62 + .../HAL_Drivers/drivers/drv_adc_v2_private.h | 586 +++++++ .../HAL_Drivers/drivers/drv_config.h | 58 +- components/drivers/Kconfig | 1 + components/drivers/adc/Kconfig | 8 + components/drivers/adc/SConscript | 12 + components/drivers/adc/adc_v2.c | 945 +++++++++++ components/drivers/adc/adc_v2_internal.h | 18 + components/drivers/include/drivers/adc_v2.h | 328 ++++ components/drivers/include/rtdevice.h | 4 + 31 files changed, 6255 insertions(+), 22 deletions(-) create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/f0/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/f1/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/f2/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/f3/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/f4/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/f7/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/g0/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/g4/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/h5/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/h7/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/h7rs/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/l0/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/l4/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/l5/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/mp1/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/u5/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/wb/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/config/wl/adc_config_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.h create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h create mode 100644 components/drivers/adc/Kconfig create mode 100644 components/drivers/adc/SConscript create mode 100644 components/drivers/adc/adc_v2.c create mode 100644 components/drivers/adc/adc_v2_internal.h create mode 100644 components/drivers/include/drivers/adc_v2.h diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig index 0a918c1ccd3..841ef9cba31 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig @@ -24,6 +24,39 @@ if BSP_USING_USBD # "ULPI: UTMI+ Low Pin Interface" endif +menuconfig BSP_USING_ADC_V2 + bool "Enable ADC V2" + select RT_USING_ADC_V2 + depends on !RT_USING_ADC + 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 +endif + config BSP_USING_CRC bool "Enable CRC (CRC-32 0x04C11DB7 Polynomial)" select RT_USING_HWCRYPTO @@ -59,4 +92,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..3903468d9b8 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript @@ -49,6 +49,9 @@ if GetDepend(['BSP_USING_ETH', 'RT_USING_LWIP']) and not GetDepend(['SOC_STM32H7 if GetDepend(['RT_USING_ADC']): src += ['drv_adc.c'] +if GetDepend(['BSP_USING_ADC_V2']): + src += ['drv_adc_v2.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..2f975a89b32 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f0/adc_config_v2.h @@ -0,0 +1,155 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..03422b1fb6e --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f1/adc_config_v2.h @@ -0,0 +1,148 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..a7b2e961315 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f2/adc_config_v2.h @@ -0,0 +1,160 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..ede45bbece0 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f3/adc_config_v2.h @@ -0,0 +1,187 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..3109cbc3c5b --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f4/adc_config_v2.h @@ -0,0 +1,160 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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/f7/adc_config_v2.h b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f7/adc_config_v2.h new file mode 100644 index 00000000000..861863ffc0f --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/f7/adc_config_v2.h @@ -0,0 +1,160 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..b1aaf8a2461 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/g0/adc_config_v2.h @@ -0,0 +1,112 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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..75e637947ea --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/g4/adc_config_v2.h @@ -0,0 +1,194 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..4602cb376be --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/h5/adc_config_v2.h @@ -0,0 +1,155 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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..f3044982457 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/h7/adc_config_v2.h @@ -0,0 +1,169 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..c2f269880e6 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/h7rs/adc_config_v2.h @@ -0,0 +1,149 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..7c9f05b918f --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/l0/adc_config_v2.h @@ -0,0 +1,121 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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..f4b1a7c8f1a --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/l4/adc_config_v2.h @@ -0,0 +1,175 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..f02a5f6195d --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/l5/adc_config_v2.h @@ -0,0 +1,137 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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..db8a4fb06d1 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/mp1/adc_config_v2.h @@ -0,0 +1,160 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..1c345bf1fe3 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/u5/adc_config_v2.h @@ -0,0 +1,204 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..0a9149ca23d --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/wb/adc_config_v2.h @@ -0,0 +1,151 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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, \ + }, \ + } +#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, \ + }, \ + } +#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..db7c476efe2 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/config/wl/adc_config_v2.h @@ -0,0 +1,117 @@ +/* + * 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 + + +/* 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, \ + }, \ + } +#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..91443b76dab --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c @@ -0,0 +1,1404 @@ +/* + * 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 current ADC resolution in bits. + * @param adc Pointer to the STM32 ADC device object. + * @return Resolution in bits. + */ +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_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. + */ +static 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); +} + +/** + * @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 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, + .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, +}; + +/** + * @brief STM32 ADC operation table. + */ +static const struct rt_adc_ops stm32_adc_ops = { + .core = &stm32_adc_core_ops, + .sequence = &stm32_adc_sequence_ops, +}; + +/** + * @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_private.h b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h new file mode 100644 index 00000000000..e0c3a20a7bc --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h @@ -0,0 +1,586 @@ +/* + * 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(__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(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 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_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_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_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_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 */ + +#ifndef STM32_ADC_TEMP_INSTANCE_MASK +#if STM32_ADC_TEMP_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL +/** @brief ADC instances that can sample the temperature sensor. */ +#define STM32_ADC_TEMP_INSTANCE_MASK 0UL +#else +/** @brief ADC instances that can sample the temperature sensor. */ +#define STM32_ADC_TEMP_INSTANCE_MASK STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK +#endif /* STM32_ADC_TEMP_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#endif /* STM32_ADC_TEMP_INSTANCE_MASK */ + +#ifndef STM32_ADC_TEMP_CHANNEL +#if STM32_ADC_TEMP_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL +#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_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#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_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_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_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_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_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 */ + +#ifndef STM32_ADC_VBAT_INSTANCE_MASK +#if STM32_ADC_VBAT_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL +/** @brief ADC instances that can sample VBAT. */ +#define STM32_ADC_VBAT_INSTANCE_MASK 0UL +#else +/** @brief ADC instances that can sample VBAT. */ +#define STM32_ADC_VBAT_INSTANCE_MASK STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK +#endif /* STM32_ADC_VBAT_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#endif /* STM32_ADC_VBAT_INSTANCE_MASK */ + +#ifndef STM32_ADC_VBAT_CHANNEL +#if STM32_ADC_VBAT_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL +#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_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#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_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_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_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_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_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 */ + +#ifndef STM32_ADC_VREF_INSTANCE_MASK +#if STM32_ADC_VREF_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL +/** @brief ADC instances that can sample VREFINT. */ +#define STM32_ADC_VREF_INSTANCE_MASK 0UL +#else +/** @brief ADC instances that can sample VREFINT. */ +#define STM32_ADC_VREF_INSTANCE_MASK STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK +#endif /* STM32_ADC_VREF_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#endif /* STM32_ADC_VREF_INSTANCE_MASK */ + +#ifndef STM32_ADC_VREF_CHANNEL +#if STM32_ADC_VREF_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL +#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_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#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 */ + +/** + * @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. */ +}; + +/* + * 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 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 active ADC resolution in bits. + * @param adc Pointer to the STM32 ADC device object. + * @return ADC resolution in bits, or 0 if it cannot be determined. + */ +rt_uint8_t stm32_adc_get_resolution_bits(const struct stm32_adc *adc); + +/** + * @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); + +#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_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/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..a2a73047b58 --- /dev/null +++ b/components/drivers/adc/Kconfig @@ -0,0 +1,8 @@ +menuconfig RT_USING_ADC_V2 + bool "Using ADC V2 device drivers" + depends on !RT_USING_ADC + default n + help + Enable the standalone ADC V2 framework. ADC V2 currently uses the + legacy ADC public namespace, so it cannot be enabled together with + RT_USING_ADC. diff --git a/components/drivers/adc/SConscript b/components/drivers/adc/SConscript new file mode 100644 index 00000000000..2db72611014 --- /dev/null +++ b/components/drivers/adc/SConscript @@ -0,0 +1,12 @@ +from building import * + +cwd = GetCurrentDir() +src = [] +CPPPATH = [cwd + '/../include'] + +if GetDepend(['RT_USING_ADC_V2']): + src += ['adc_v2.c'] + +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_ADC_V2'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/adc/adc_v2.c b/components/drivers/adc/adc_v2.c new file mode 100644 index 00000000000..e5fc8f122b3 --- /dev/null +++ b/components/drivers/adc/adc_v2.c @@ -0,0 +1,945 @@ +/* + * 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"; + + default: + return "UNKNOWN"; + } +} + +#endif /* DBG_LVL >= DBG_LOG */ + +/** @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]; +} + +/** + * @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) +{ + if (device == RT_NULL) + { + return; + } + + device->session_ctrl.channels = 0U; + device->session_ctrl.channel_count = 0U; + device->session_ctrl.configured = RT_FALSE; +} + +/** + * @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; + } + + 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) + { + device->session_ctrl.channels = 0U; + device->session_ctrl.channel_count = 0U; + device->session_ctrl.configured = RT_FALSE; + } + + 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_atomic_store(&device->state, (rt_atomic_t)RT_ADC_STATE_IDLE); + device->default_vref_mv = 0; + adc_clear_session_ctrl(device); + 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); +} + +/** + * @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..4adeb244b29 --- /dev/null +++ b/components/drivers/adc/adc_v2_internal.h @@ -0,0 +1,18 @@ +/* + * 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 + +#endif /* __ADC_V2_INTERNAL_H__ */ diff --git a/components/drivers/include/drivers/adc_v2.h b/components/drivers/include/drivers/adc_v2.h new file mode 100644 index 00000000000..2323d3e81df --- /dev/null +++ b/components/drivers/include/drivers/adc_v2.h @@ -0,0 +1,328 @@ +/* + * 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) +#error "ADC V2 uses the legacy ADC namespace; disable RT_USING_ADC before enabling ADC V2." +#endif /* defined(RT_USING_ADC) */ + +#include +#include +#include + +#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. */ +}; + +struct rt_adc_device; +typedef struct rt_adc_device *rt_adc_device_t; + +struct rt_adc_sequence_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); + + /** + * @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); +}; + + +/** + * @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. */ +}; + +/** + * @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. */ +}; + +/** + * @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. */ + rt_uint32_t default_vref_mv; /**< Default reference voltage in millivolts. */ + struct rt_adc_session_ctrl session_ctrl; /**< ADC active session control block. */ +}; + +/** + * @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); + +/** + * @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/rtdevice.h b/components/drivers/include/rtdevice.h index 3d5aa23c44a..f71ddc919f5 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -263,6 +263,10 @@ extern "C" { #include "drivers/adc.h" #endif /* RT_USING_ADC */ +#ifdef RT_USING_ADC_V2 +#include "drivers/adc_v2.h" +#endif /* RT_USING_ADC_V2 */ + #ifdef RT_USING_DAC #include "drivers/dac.h" #endif /* RT_USING_DAC */ From f4ff1db8fd7654b8d29ef42f435c99e5f8d08887 Mon Sep 17 00:00:00 2001 From: wdfk-prog <1425075683@qq.com> Date: Thu, 4 Jun 2026 10:41:44 +0800 Subject: [PATCH 2/6] feat[ADC V2]: add ADC V2 MSH special channel read support add generic ADC V2 MSH commands for probing, configuring, raw reads, voltage reads, and sequence reads add STM32 ADC V2 backend special commands for VREFINT, temperature sensor, and VBAT reads add STM32 helper APIs for special logical channels, sampling time, resolution, and temperature calculation wire ADC V2 MSH sources through Kconfig and SConscript --- .../libraries/HAL_Drivers/drivers/SConscript | 3 + .../HAL_Drivers/drivers/drv_adc_v2.c | 231 ++++- .../HAL_Drivers/drivers/drv_adc_v2_msh.c | 810 ++++++++++++++++++ .../HAL_Drivers/drivers/drv_adc_v2_private.h | 162 +++- components/drivers/adc/Kconfig | 15 + components/drivers/adc/SConscript | 3 + components/drivers/adc/adc_v2_msh.c | 391 +++++++++ 7 files changed, 1593 insertions(+), 22 deletions(-) create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_msh.c create mode 100644 components/drivers/adc/adc_v2_msh.c diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript index 3903468d9b8..61070dff31f 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript @@ -52,6 +52,9 @@ if GetDepend(['RT_USING_ADC']): if GetDepend(['BSP_USING_ADC_V2']): src += ['drv_adc_v2.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/drv_adc_v2.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c index 91443b76dab..35c2c820d78 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c @@ -360,10 +360,64 @@ rt_err_t stm32_adc_get_vref_logical_channel(struct stm32_adc *adc, rt_uint8_t *c 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. + * @return Resolution in bits, or 12 when it cannot be determined. */ rt_uint8_t stm32_adc_get_resolution_bits(const struct stm32_adc *adc) { @@ -403,6 +457,179 @@ rt_uint8_t stm32_adc_get_resolution_bits(const struct stm32_adc *adc) #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. @@ -885,7 +1112,7 @@ static rt_err_t stm32_adc_get_single_diff(const struct stm32_adc_private_cfg *cf * @param sampling_time Pointer to the output HAL sampling-time value. * @return Operation status. */ -static rt_err_t stm32_adc_get_sampling_time(const struct stm32_adc_private_cfg *cfg, uint32_t *sampling_time) +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)) { 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 index e0c3a20a7bc..d9a1a9980f9 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h @@ -114,6 +114,26 @@ #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 @@ -348,39 +368,56 @@ #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_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL +#if STM32_ADC_TEMP_CHANNEL_AVAILABLE /** @brief ADC instances that can sample the temperature sensor. */ -#define STM32_ADC_TEMP_INSTANCE_MASK 0UL +#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 STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK -#endif /* STM32_ADC_TEMP_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#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_HAL_CHANNEL == STM32_ADC_INVALID_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 @@ -388,51 +425,71 @@ #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_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#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_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL +#if STM32_ADC_VBAT_CHANNEL_AVAILABLE /** @brief ADC instances that can sample VBAT. */ -#define STM32_ADC_VBAT_INSTANCE_MASK 0UL +#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 STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK -#endif /* STM32_ADC_VBAT_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#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_HAL_CHANNEL == STM32_ADC_INVALID_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 @@ -440,51 +497,71 @@ #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_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#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_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL +#if STM32_ADC_VREF_CHANNEL_AVAILABLE /** @brief ADC instances that can sample VREFINT. */ -#define STM32_ADC_VREF_INSTANCE_MASK 0UL +#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 STM32_ADC_INTERNAL_DEFAULT_INSTANCE_MASK -#endif /* STM32_ADC_VREF_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#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_HAL_CHANNEL == STM32_ADC_INVALID_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 @@ -492,7 +569,7 @@ #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_HAL_CHANNEL == STM32_ADC_INVALID_CHANNEL */ +#endif /* !STM32_ADC_VREF_CHANNEL_AVAILABLE */ #endif /* STM32_ADC_VREF_CHANNEL */ #ifndef STM32_ADC_TEMP_ALT_HAL_CHANNEL @@ -544,6 +621,14 @@ RT_STATIC_ASSERT(stm32_adc_handle_must_be_first, offsetof(struct stm32_adc, hand 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. @@ -561,12 +646,49 @@ rt_err_t stm32_adc_get_channel(rt_uint8_t channel, uint32_t *hal_channel); rt_err_t stm32_adc_get_vref_logical_channel(struct stm32_adc *adc, rt_uint8_t *channel); /** - * @brief Get the active ADC resolution in bits. + * @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 ADC resolution in bits, or 0 if it cannot be determined. + * @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. diff --git a/components/drivers/adc/Kconfig b/components/drivers/adc/Kconfig index a2a73047b58..acf7abd46af 100644 --- a/components/drivers/adc/Kconfig +++ b/components/drivers/adc/Kconfig @@ -6,3 +6,18 @@ menuconfig RT_USING_ADC_V2 Enable the standalone ADC V2 framework. ADC V2 currently uses the legacy ADC public namespace, so it cannot be enabled together with RT_USING_ADC. + +if RT_USING_ADC_V2 + +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. + +endif diff --git a/components/drivers/adc/SConscript b/components/drivers/adc/SConscript index 2db72611014..90ee471f4a4 100644 --- a/components/drivers/adc/SConscript +++ b/components/drivers/adc/SConscript @@ -7,6 +7,9 @@ CPPPATH = [cwd + '/../include'] if GetDepend(['RT_USING_ADC_V2']): src += ['adc_v2.c'] +if GetDepend(['RT_USING_ADC_V2', 'RT_USING_FINSH', 'RT_ADC_V2_USING_MSH']): + src += ['adc_v2_msh.c'] + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_ADC_V2'], CPPPATH = CPPPATH) Return('group') diff --git a/components/drivers/adc/adc_v2_msh.c b/components/drivers/adc/adc_v2_msh.c new file mode 100644 index 00000000000..cfec6b7d53b --- /dev/null +++ b/components/drivers/adc/adc_v2_msh.c @@ -0,0 +1,391 @@ +/* + * 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 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; +} + +/** + * @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"); + 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); +} + +static rt_adc_device_t device = RT_NULL; + +/** + * @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; + } + + 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 = 0; 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; + } + else 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 = 0; index < count; index++) + { + rt_kprintf("[%u]=%lu\n", (unsigned int)index, (unsigned long)values[index]); + } + } + return result; + } + else 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; + } + else 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 = 0; 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 = 0; index < sequence_read_count; index++) + { + rt_kprintf("[%u]=%lu\n", (unsigned int)index, (unsigned long)values[index]); + } + + return RT_EOK; + } + else 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; + } + + 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) */ From cd4ae557f8b1f873b24cd22f227ebcfd3ac7aaba Mon Sep 17 00:00:00 2001 From: wdfk-prog <1425075683@qq.com> Date: Thu, 4 Jun 2026 10:51:34 +0800 Subject: [PATCH 3/6] feat[ADC V2]: add ADC V2 stream DMA support add ADC V2 stream APIs with latest-frame and FIFO buffering policies wire STM32 ADC V2 to circular DMA stream mode with per-instance Kconfig options extend STM32 ADC config headers and DMA helpers for stream DMA configuration add FinSH stream commands for start, read, cancel, and stop operations handle Cortex-M7 cache-safe DMA buffers for STM32 stream sampling --- .../libraries/HAL_Drivers/drivers/Kconfig | 43 + .../drivers/config/f0/adc_config_v2.h | 217 +++++ .../drivers/config/f1/adc_config_v2.h | 217 +++++ .../drivers/config/f2/adc_config_v2.h | 217 +++++ .../drivers/config/f3/adc_config_v2.h | 218 +++++ .../drivers/config/f4/adc_config_v2.h | 217 +++++ .../drivers/config/f4/dma_config.h | 26 +- .../drivers/config/f7/adc_config_v2.h | 217 +++++ .../drivers/config/g0/adc_config_v2.h | 215 +++++ .../drivers/config/g4/adc_config_v2.h | 218 +++++ .../drivers/config/h5/adc_config_v2.h | 216 +++++ .../drivers/config/h7/adc_config_v2.h | 217 +++++ .../drivers/config/h7rs/adc_config_v2.h | 217 +++++ .../drivers/config/l0/adc_config_v2.h | 215 +++++ .../drivers/config/l4/adc_config_v2.h | 217 +++++ .../drivers/config/l5/adc_config_v2.h | 216 +++++ .../drivers/config/mp1/adc_config_v2.h | 217 +++++ .../drivers/config/u5/adc_config_v2.h | 218 +++++ .../drivers/config/wb/adc_config_v2.h | 217 +++++ .../drivers/config/wl/adc_config_v2.h | 215 +++++ .../HAL_Drivers/drivers/drv_adc_v2.c | 575 ++++++++++++ .../HAL_Drivers/drivers/drv_adc_v2_private.h | 20 + .../libraries/HAL_Drivers/drivers/drv_dma.h | 6 + components/drivers/adc/Kconfig | 63 +- components/drivers/adc/adc_v2.c | 834 +++++++++++++++++- components/drivers/adc/adc_v2_msh.c | 545 +++++++++++- components/drivers/include/drivers/adc_v2.h | 278 +++++- 27 files changed, 6254 insertions(+), 37 deletions(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig index 841ef9cba31..a270bd1d575 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig @@ -55,6 +55,49 @@ if BSP_USING_ADC_V2 bool "Enable ADC4" depends on (SOC_SERIES_STM32F3 || SOC_SERIES_STM32G4 || SOC_SERIES_STM32U5) default n + + 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 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 index 2f975a89b32..c1e0fa87320 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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. */ @@ -101,6 +315,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -122,6 +337,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -143,6 +359,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ 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 index 03422b1fb6e..7632d2b2d69 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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. */ @@ -94,6 +308,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -115,6 +330,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -136,6 +352,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ 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 index a7b2e961315..994405a8596 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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. */ @@ -106,6 +320,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -127,6 +342,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -148,6 +364,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ 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 index ede45bbece0..778fec24bbc 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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. */ @@ -112,6 +326,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -133,6 +348,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -154,6 +370,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ @@ -175,6 +392,7 @@ extern "C" { { \ .Instance = ADC4, \ }, \ + ADC4_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC4 */ 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 index 3109cbc3c5b..d4849e22131 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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. */ @@ -106,6 +320,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -127,6 +342,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -148,6 +364,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ 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 index 861863ffc0f..7273dafb92c 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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. */ @@ -106,6 +320,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -127,6 +342,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -148,6 +364,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ 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 index b1aaf8a2461..9ea98c58648 100644 --- 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 @@ -66,6 +66,220 @@ extern "C" { /** @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) @@ -100,6 +314,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ 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 index 75e637947ea..3556ee03473 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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) @@ -119,6 +333,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -140,6 +355,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -161,6 +377,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ @@ -182,6 +399,7 @@ extern "C" { { \ .Instance = ADC4, \ }, \ + ADC4_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC4 */ 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 index 4602cb376be..eca8588e7ea 100644 --- 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 @@ -66,6 +66,220 @@ extern "C" { /** @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) @@ -123,6 +337,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ #ifdef BSP_USING_ADC2 @@ -143,6 +358,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ 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 index f3044982457..707fc29d2d5 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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) @@ -115,6 +329,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -136,6 +351,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -157,6 +373,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ 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 index c2f269880e6..9909efa3e71 100644 --- 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 @@ -66,6 +66,220 @@ extern "C" { /** @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) @@ -97,6 +311,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ #ifdef BSP_USING_ADC2 @@ -117,6 +332,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ #ifdef BSP_USING_ADC3 @@ -137,6 +353,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ 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 index 7c9f05b918f..437dcb17537 100644 --- 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 @@ -66,6 +66,220 @@ extern "C" { /** @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. */ @@ -109,6 +323,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ 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 index f4b1a7c8f1a..98d9e621369 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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) @@ -121,6 +335,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -142,6 +357,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -163,6 +379,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ 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 index f02a5f6195d..88fbfdbea99 100644 --- 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 @@ -66,6 +66,220 @@ extern "C" { /** @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) @@ -105,6 +319,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ #ifdef BSP_USING_ADC2 @@ -125,6 +340,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ 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 index db8a4fb06d1..1789573e4dd 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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) @@ -106,6 +320,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -127,6 +342,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -148,6 +364,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ 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 index 1c345bf1fe3..fbc97bc98f5 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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. */ @@ -129,6 +343,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -150,6 +365,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -171,6 +387,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ @@ -192,6 +409,7 @@ extern "C" { { \ .Instance = ADC4, \ }, \ + ADC4_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC4 */ 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 index 0a9149ca23d..6895ecae0c4 100644 --- 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 @@ -58,6 +58,220 @@ extern "C" { /** @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) @@ -97,6 +311,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ @@ -118,6 +333,7 @@ extern "C" { { \ .Instance = ADC2, \ }, \ + ADC2_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC2 */ @@ -139,6 +355,7 @@ extern "C" { { \ .Instance = ADC3, \ }, \ + ADC3_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC3 */ 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 index db7c476efe2..3be4a47f759 100644 --- 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 @@ -66,6 +66,220 @@ extern "C" { /** @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) @@ -105,6 +319,7 @@ extern "C" { { \ .Instance = ADC1, \ }, \ + ADC1_V2_DMA_CONFIG_FIELD \ } #endif /* BSP_USING_ADC1 */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c index 35c2c820d78..20ffa8d95ab 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c @@ -1342,6 +1342,66 @@ static rt_err_t stm32_adc_apply_regular_config(struct stm32_adc *adc, rt_uint32_ 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; + } + + 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) */ + adc->handle.Init.ContinuousConvMode = ENABLE; + + 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. @@ -1452,6 +1512,507 @@ static rt_err_t stm32_adc_sequence_stop(struct rt_adc_device *device) 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. @@ -1593,12 +2154,26 @@ static const struct rt_adc_sequence_ops stm32_adc_sequence_ops = { .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 */ }; /** 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 index d9a1a9980f9..b1447ac7ae2 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h @@ -98,6 +98,11 @@ #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(__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) */ @@ -596,6 +601,14 @@ #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 */ + /** * @brief STM32 ADC device object. * @@ -609,6 +622,13 @@ struct stm32_adc 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 */ }; /* 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/components/drivers/adc/Kconfig b/components/drivers/adc/Kconfig index acf7abd46af..dd7e9598568 100644 --- a/components/drivers/adc/Kconfig +++ b/components/drivers/adc/Kconfig @@ -9,6 +9,63 @@ menuconfig RT_USING_ADC_V2 if RT_USING_ADC_V2 + +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 @@ -18,6 +75,10 @@ config RT_ADC_V2_USING_MSH This option exports the "adc" shell command for probing ADC devices, configuring channels, reading raw samples, reading voltage values, and - reading one ADC sequence. + 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 diff --git a/components/drivers/adc/adc_v2.c b/components/drivers/adc/adc_v2.c index e5fc8f122b3..84f3cf48124 100644 --- a/components/drivers/adc/adc_v2.c +++ b/components/drivers/adc/adc_v2.c @@ -53,13 +53,16 @@ static const char *adc_state_name(enum rt_adc_state state) 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"; } } -#endif /* DBG_LVL >= DBG_LOG */ - /** @brief ADC control command string table offset base. */ #define RT_ADC_CMD_NAME_BASE RT_ADC_CMD_GET_RESOLUTION @@ -100,6 +103,34 @@ static const char *rt_adc_control_cmd_name(int cmd) 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. @@ -117,14 +148,7 @@ static void adc_set_state(rt_adc_device_t device, enum rt_adc_state state) */ static void adc_clear_session_ctrl(rt_adc_device_t device) { - if (device == RT_NULL) - { - return; - } - - device->session_ctrl.channels = 0U; - device->session_ctrl.channel_count = 0U; - device->session_ctrl.configured = RT_FALSE; + rt_memset(&device->session_ctrl, 0, sizeof(device->session_ctrl)); } /** @@ -355,6 +379,23 @@ static rt_err_t adc_close_device(rt_device_t dev) 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; @@ -503,9 +544,7 @@ static rt_err_t adc_control_device(rt_device_t dev, int cmd, void *args) result = device->ops->core->control(device, cmd, RT_NULL); if (result == RT_EOK) { - device->session_ctrl.channels = 0U; - device->session_ctrl.channel_count = 0U; - device->session_ctrl.configured = RT_FALSE; + adc_clear_session_ctrl(device); } adc_set_state(device, RT_ADC_STATE_IDLE); @@ -610,9 +649,13 @@ rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const stru 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); +#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); @@ -704,6 +747,769 @@ rt_err_t rt_adc_read_sequence(rt_adc_device_t device, rt_uint32_t channels, 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; + + 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; + } + + + 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; + } + + + 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 (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; + } + + trigger_result = RT_EOK; + + 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. @@ -864,7 +1670,7 @@ rt_err_t rt_adc_voltage(rt_adc_device_t device, rt_uint32_t *voltages_mv, rt_siz 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); + &sequence_cfg, size, &read_count); if ((result == RT_EOK) && (read_count != size)) { result = -RT_ERROR; diff --git a/components/drivers/adc/adc_v2_msh.c b/components/drivers/adc/adc_v2_msh.c index cfec6b7d53b..b6106f7e405 100644 --- a/components/drivers/adc/adc_v2_msh.c +++ b/components/drivers/adc/adc_v2_msh.c @@ -31,6 +31,15 @@ /** @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. */ @@ -54,6 +63,23 @@ rt_weak rt_err_t rt_adc_msh_special(rt_adc_device_t device, int argc, char **arg return -RT_ENOSYS; } + +#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. */ @@ -68,6 +94,11 @@ static void adc_msh_usage(void) 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_STREAM) + adc_msh_usage_stream(); +#endif /* defined(RT_ADC_USING_STREAM) */ + rt_adc_msh_special_help(); } @@ -113,7 +144,477 @@ static rt_int32_t adc_msh_parse_timeout(const char *arg) return (rt_int32_t)strtol(arg, RT_NULL, 0); } + +#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 */ + + + +#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. @@ -150,6 +651,15 @@ static int adc(int argc, char **argv) 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) { @@ -210,7 +720,7 @@ static int adc(int argc, char **argv) } channels = 0U; - for (index = 0; index < (rt_size_t)(argc - 2); index++) + 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) @@ -229,7 +739,8 @@ static int adc(int argc, char **argv) } return result; } - else if (!rt_strcmp(argv[1], "read")) + + if (!rt_strcmp(argv[1], "read")) { if (argc > 2) { @@ -262,14 +773,15 @@ static int adc(int argc, char **argv) else { result = RT_EOK; - for (index = 0; index < count; index++) + for (index = 0U; index < count; index++) { rt_kprintf("[%u]=%lu\n", (unsigned int)index, (unsigned long)values[index]); } } return result; } - else if (!rt_strcmp(argv[1], "voltage")) + + if (!rt_strcmp(argv[1], "voltage")) { rt_int32_t timeout_ms; @@ -308,7 +820,8 @@ static int adc(int argc, char **argv) return result; } - else if (!rt_strcmp(argv[1], "seq")) + + if (!rt_strcmp(argv[1], "seq")) { struct rt_adc_sequence_cfg sequence_cfg; rt_size_t sequence_read_count; @@ -320,7 +833,7 @@ static int adc(int argc, char **argv) } channels = 0U; - for (index = 0; index < (rt_size_t)(argc - 3); index++) + 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) @@ -349,14 +862,16 @@ static int adc(int argc, char **argv) return result; } - for (index = 0; index < sequence_read_count; index++) + for (index = 0U; index < sequence_read_count; index++) { rt_kprintf("[%u]=%lu\n", (unsigned int)index, (unsigned long)values[index]); } return RT_EOK; } - else if (!rt_strcmp(argv[1], "close")) + + + if (!rt_strcmp(argv[1], "close")) { rt_err_t close_result; @@ -378,6 +893,20 @@ static int adc(int argc, char **argv) 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) { diff --git a/components/drivers/include/drivers/adc_v2.h b/components/drivers/include/drivers/adc_v2.h index 2323d3e81df..280925a4c3a 100644 --- a/components/drivers/include/drivers/adc_v2.h +++ b/components/drivers/include/drivers/adc_v2.h @@ -26,6 +26,12 @@ #include #include + +#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 */ @@ -67,13 +73,15 @@ enum rt_adc_input_mode 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_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. @@ -103,6 +111,7 @@ struct rt_adc_core_ops */ rt_err_t (*session_config)(struct rt_adc_device *device, rt_uint32_t channels); + /** * @brief Handle ADC control commands. * @param device Pointer to the ADC device object. @@ -144,6 +153,45 @@ struct rt_adc_sequence_ops 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. @@ -152,6 +200,9 @@ 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 */ }; /** @@ -164,6 +215,170 @@ struct rt_adc_sequence_cfg 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. */ @@ -182,8 +397,12 @@ 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. */ +#ifdef RT_ADC_USING_STREAM + struct rt_adc_stream_ctrl stream_ctrl; /**< ADC stream runtime control block. */ +#endif /* RT_ADC_USING_STREAM */ }; /** @@ -270,6 +489,63 @@ rt_err_t rt_adc_session_channel_index(rt_uint32_t session_channels, rt_uint32_t 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. From f65af7396a311798968bd75ec1ac8d452da15e03 Mon Sep 17 00:00:00 2001 From: wdfk-prog <1425075683@qq.com> Date: Thu, 4 Jun 2026 11:00:44 +0800 Subject: [PATCH 4/6] feat[ADC V2]: add timer trigger support for ADC V2 streams add ADC V2 trigger configuration, validation, and lifecycle coordination add timer update trigger support through clock timer TRGO controls map STM32 ADC V2 timer update triggers to HAL external trigger selector fields add Kconfig, SConscript, and MSH entries for ADC trigger setup and inspection --- .../libraries/HAL_Drivers/drivers/Kconfig | 22 + .../libraries/HAL_Drivers/drivers/SConscript | 3 + .../HAL_Drivers/drivers/drv_adc_v2.c | 27 ++ .../HAL_Drivers/drivers/drv_adc_v2_private.h | 47 +++ .../HAL_Drivers/drivers/drv_adc_v2_trigger.c | 381 ++++++++++++++++++ .../libraries/HAL_Drivers/drivers/drv_tim.c | 337 +++++++++++++++- components/drivers/adc/Kconfig | 16 + components/drivers/adc/SConscript | 3 + components/drivers/adc/adc_v2.c | 28 ++ components/drivers/adc/adc_v2_internal.h | 44 ++ components/drivers/adc/adc_v2_msh.c | 182 +++++++++ components/drivers/adc/adc_v2_trigger.c | 371 +++++++++++++++++ components/drivers/clock_time/Kconfig | 11 + components/drivers/include/drivers/adc_v2.h | 18 + .../drivers/include/drivers/adc_v2_trigger.h | 171 ++++++++ .../drivers/include/drivers/clock_time.h | 29 +- 16 files changed, 1688 insertions(+), 2 deletions(-) create mode 100644 bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_trigger.c create mode 100644 components/drivers/adc/adc_v2_trigger.c create mode 100644 components/drivers/include/drivers/adc_v2_trigger.h diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig index a270bd1d575..731d599e5ff 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig @@ -56,6 +56,28 @@ if BSP_USING_ADC_V2 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 update trigger 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 to ADC external trigger selector + mapping for ADC V2 stream pacing. + config BSP_ADC_USING_STREAM_DMA bool diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript index 61070dff31f..15369e06c8f 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript @@ -52,6 +52,9 @@ if GetDepend(['RT_USING_ADC']): 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'] diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c index 20ffa8d95ab..ecdfec6e4c7 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c @@ -1374,6 +1374,22 @@ static rt_err_t stm32_adc_apply_stream_regular_config(struct stm32_adc *adc, rt_ 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; @@ -1389,7 +1405,15 @@ static rt_err_t stm32_adc_apply_stream_regular_config(struct stm32_adc *adc, rt_ #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) @@ -2142,6 +2166,9 @@ 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, }; 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 index b1447ac7ae2..05209355e9b 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h @@ -103,6 +103,16 @@ #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-update 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(__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) */ @@ -609,6 +619,18 @@ #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. * @@ -629,6 +651,10 @@ struct stm32_adc 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) */ }; /* @@ -717,6 +743,27 @@ rt_err_t stm32_adc_calc_temperature(rt_adc_device_t device, rt_uint32_t raw_valu */ 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 */ 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..e3598a0b2bd --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_trigger.c @@ -0,0 +1,381 @@ +/* + * 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 timer 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 Fill software-start trigger fields. + * @param fields Pointer to the STM32 trigger fields to fill. + */ +static void stm32_adc_trigger_fields_set_software(struct stm32_adc_trigger_fields *fields) +{ + fields->selector = ADC_SOFTWARE_START; +#if defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) + fields->edge = ADC_EXTERNALTRIGCONVEDGE_NONE; +#else + fields->edge = 0U; +#endif /* defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) */ +} + +#if defined(STM32_ADC_USING_TIMER_TRIGGER) +/** + * @brief Resolve TIMx update/TRGO selector for one STM32 ADC trigger source. + * @param tim Pointer to the STM32 HAL timer handle. + * @param selector Pointer to the output HAL ADC selector. + * @return Operation status. + */ +static rt_err_t stm32_adc_timer_update_selector_get(const TIM_HandleTypeDef *tim, rt_uint32_t *selector) +{ + if ((tim == RT_NULL) || (selector == RT_NULL)) + { + return -RT_EINVAL; + } + +#if defined(TIM1) && (defined(ADC_EXTERNALTRIGCONV_T1_TRGO) || defined(ADC_EXTERNALTRIG_T1_TRGO)) + if (tim->Instance == TIM1) + { +#if defined(ADC_EXTERNALTRIGCONV_T1_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T1_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T1_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T1_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM1) && (defined(ADC_EXTERNALTRIGCONV_T1_TRGO) || defined(ADC_EXTERNALTRIG_T1_TRGO)) */ +#if defined(TIM2) && (defined(ADC_EXTERNALTRIGCONV_T2_TRGO) || defined(ADC_EXTERNALTRIG_T2_TRGO)) + if (tim->Instance == TIM2) + { +#if defined(ADC_EXTERNALTRIGCONV_T2_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T2_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T2_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T2_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM2) && (defined(ADC_EXTERNALTRIGCONV_T2_TRGO) || defined(ADC_EXTERNALTRIG_T2_TRGO)) */ +#if defined(TIM3) && (defined(ADC_EXTERNALTRIGCONV_T3_TRGO) || defined(ADC_EXTERNALTRIG_T3_TRGO)) + if (tim->Instance == TIM3) + { +#if defined(ADC_EXTERNALTRIGCONV_T3_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T3_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T3_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T3_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM3) && (defined(ADC_EXTERNALTRIGCONV_T3_TRGO) || defined(ADC_EXTERNALTRIG_T3_TRGO)) */ +#if defined(TIM4) && (defined(ADC_EXTERNALTRIGCONV_T4_TRGO) || defined(ADC_EXTERNALTRIG_T4_TRGO)) + if (tim->Instance == TIM4) + { +#if defined(ADC_EXTERNALTRIGCONV_T4_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T4_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T4_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T4_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM4) && (defined(ADC_EXTERNALTRIGCONV_T4_TRGO) || defined(ADC_EXTERNALTRIG_T4_TRGO)) */ +#if defined(TIM5) && (defined(ADC_EXTERNALTRIGCONV_T5_TRGO) || defined(ADC_EXTERNALTRIG_T5_TRGO)) + if (tim->Instance == TIM5) + { +#if defined(ADC_EXTERNALTRIGCONV_T5_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T5_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T5_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T5_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM5) && (defined(ADC_EXTERNALTRIGCONV_T5_TRGO) || defined(ADC_EXTERNALTRIG_T5_TRGO)) */ +#if defined(TIM6) && (defined(ADC_EXTERNALTRIGCONV_T6_TRGO) || defined(ADC_EXTERNALTRIG_T6_TRGO)) + if (tim->Instance == TIM6) + { +#if defined(ADC_EXTERNALTRIGCONV_T6_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T6_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T6_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T6_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM6) && (defined(ADC_EXTERNALTRIGCONV_T6_TRGO) || defined(ADC_EXTERNALTRIG_T6_TRGO)) */ +#if defined(TIM7) && (defined(ADC_EXTERNALTRIGCONV_T7_TRGO) || defined(ADC_EXTERNALTRIG_T7_TRGO)) + if (tim->Instance == TIM7) + { +#if defined(ADC_EXTERNALTRIGCONV_T7_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T7_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T7_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T7_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM7) && (defined(ADC_EXTERNALTRIGCONV_T7_TRGO) || defined(ADC_EXTERNALTRIG_T7_TRGO)) */ +#if defined(TIM8) && (defined(ADC_EXTERNALTRIGCONV_T8_TRGO) || defined(ADC_EXTERNALTRIG_T8_TRGO)) + if (tim->Instance == TIM8) + { +#if defined(ADC_EXTERNALTRIGCONV_T8_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T8_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T8_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T8_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM8) && (defined(ADC_EXTERNALTRIGCONV_T8_TRGO) || defined(ADC_EXTERNALTRIG_T8_TRGO)) */ +#if defined(TIM9) && (defined(ADC_EXTERNALTRIGCONV_T9_TRGO) || defined(ADC_EXTERNALTRIG_T9_TRGO)) + if (tim->Instance == TIM9) + { +#if defined(ADC_EXTERNALTRIGCONV_T9_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T9_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T9_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T9_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM9) && (defined(ADC_EXTERNALTRIGCONV_T9_TRGO) || defined(ADC_EXTERNALTRIG_T9_TRGO)) */ +#if defined(TIM10) && (defined(ADC_EXTERNALTRIGCONV_T10_TRGO) || defined(ADC_EXTERNALTRIG_T10_TRGO)) + if (tim->Instance == TIM10) + { +#if defined(ADC_EXTERNALTRIGCONV_T10_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T10_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T10_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T10_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM10) && (defined(ADC_EXTERNALTRIGCONV_T10_TRGO) || defined(ADC_EXTERNALTRIG_T10_TRGO)) */ +#if defined(TIM11) && (defined(ADC_EXTERNALTRIGCONV_T11_TRGO) || defined(ADC_EXTERNALTRIG_T11_TRGO)) + if (tim->Instance == TIM11) + { +#if defined(ADC_EXTERNALTRIGCONV_T11_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T11_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T11_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T11_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM11) && (defined(ADC_EXTERNALTRIGCONV_T11_TRGO) || defined(ADC_EXTERNALTRIG_T11_TRGO)) */ +#if defined(TIM12) && (defined(ADC_EXTERNALTRIGCONV_T12_TRGO) || defined(ADC_EXTERNALTRIG_T12_TRGO)) + if (tim->Instance == TIM12) + { +#if defined(ADC_EXTERNALTRIGCONV_T12_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T12_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T12_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T12_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM12) && (defined(ADC_EXTERNALTRIGCONV_T12_TRGO) || defined(ADC_EXTERNALTRIG_T12_TRGO)) */ +#if defined(TIM13) && (defined(ADC_EXTERNALTRIGCONV_T13_TRGO) || defined(ADC_EXTERNALTRIG_T13_TRGO)) + if (tim->Instance == TIM13) + { +#if defined(ADC_EXTERNALTRIGCONV_T13_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T13_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T13_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T13_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM13) && (defined(ADC_EXTERNALTRIGCONV_T13_TRGO) || defined(ADC_EXTERNALTRIG_T13_TRGO)) */ +#if defined(TIM14) && (defined(ADC_EXTERNALTRIGCONV_T14_TRGO) || defined(ADC_EXTERNALTRIG_T14_TRGO)) + if (tim->Instance == TIM14) + { +#if defined(ADC_EXTERNALTRIGCONV_T14_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T14_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T14_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T14_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM14) && (defined(ADC_EXTERNALTRIGCONV_T14_TRGO) || defined(ADC_EXTERNALTRIG_T14_TRGO)) */ +#if defined(TIM15) && (defined(ADC_EXTERNALTRIGCONV_T15_TRGO) || defined(ADC_EXTERNALTRIG_T15_TRGO)) + if (tim->Instance == TIM15) + { +#if defined(ADC_EXTERNALTRIGCONV_T15_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T15_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T15_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T15_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM15) && (defined(ADC_EXTERNALTRIGCONV_T15_TRGO) || defined(ADC_EXTERNALTRIG_T15_TRGO)) */ +#if defined(TIM16) && (defined(ADC_EXTERNALTRIGCONV_T16_TRGO) || defined(ADC_EXTERNALTRIG_T16_TRGO)) + if (tim->Instance == TIM16) + { +#if defined(ADC_EXTERNALTRIGCONV_T16_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T16_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T16_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T16_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM16) && (defined(ADC_EXTERNALTRIGCONV_T16_TRGO) || defined(ADC_EXTERNALTRIG_T16_TRGO)) */ +#if defined(TIM17) && (defined(ADC_EXTERNALTRIGCONV_T17_TRGO) || defined(ADC_EXTERNALTRIG_T17_TRGO)) + if (tim->Instance == TIM17) + { +#if defined(ADC_EXTERNALTRIGCONV_T17_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T17_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T17_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T17_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM17) && (defined(ADC_EXTERNALTRIGCONV_T17_TRGO) || defined(ADC_EXTERNALTRIG_T17_TRGO)) */ +#if defined(TIM18) && (defined(ADC_EXTERNALTRIGCONV_T18_TRGO) || defined(ADC_EXTERNALTRIG_T18_TRGO)) + if (tim->Instance == TIM18) + { +#if defined(ADC_EXTERNALTRIGCONV_T18_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T18_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T18_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T18_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM18) && (defined(ADC_EXTERNALTRIGCONV_T18_TRGO) || defined(ADC_EXTERNALTRIG_T18_TRGO)) */ +#if defined(TIM19) && (defined(ADC_EXTERNALTRIGCONV_T19_TRGO) || defined(ADC_EXTERNALTRIG_T19_TRGO)) + if (tim->Instance == TIM19) + { +#if defined(ADC_EXTERNALTRIGCONV_T19_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T19_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T19_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T19_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM19) && (defined(ADC_EXTERNALTRIGCONV_T19_TRGO) || defined(ADC_EXTERNALTRIG_T19_TRGO)) */ +#if defined(TIM20) && (defined(ADC_EXTERNALTRIGCONV_T20_TRGO) || defined(ADC_EXTERNALTRIG_T20_TRGO)) + if (tim->Instance == TIM20) + { +#if defined(ADC_EXTERNALTRIGCONV_T20_TRGO) + *selector = ADC_EXTERNALTRIGCONV_T20_TRGO; +#else + *selector = ADC_EXTERNALTRIG_T20_TRGO; +#endif /* defined(ADC_EXTERNALTRIGCONV_T20_TRGO) */ + return RT_EOK; + } +#endif /* defined(TIM20) && (defined(ADC_EXTERNALTRIGCONV_T20_TRGO) || defined(ADC_EXTERNALTRIG_T20_TRGO)) */ + + return -RT_ENOSYS; +} +#endif /* defined(STM32_ADC_USING_TIMER_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) +{ +#if defined(STM32_ADC_USING_TIMER_TRIGGER) + TIM_HandleTypeDef *tim; +#endif /* defined(STM32_ADC_USING_TIMER_TRIGGER) */ + rt_err_t result; + + if (cfg == RT_NULL) + { + stm32_adc_trigger_fields_set_software(fields); + return RT_EOK; + } + + switch (cfg->type) + { + case RT_ADC_TRIGGER_TIMER_UPDATE: +#if defined(STM32_ADC_USING_TIMER_TRIGGER) + if (cfg->event.timer.timer == RT_NULL) + { + return -RT_EINVAL; + } + + tim = (TIM_HandleTypeDef *)cfg->event.timer.timer->user_data; + if (tim == RT_NULL) + { + return -RT_EINVAL; + } + + result = stm32_adc_timer_update_selector_get(tim, &fields->selector); + if (result != RT_EOK) + { + LOG_E("%s timer update trigger selector unsupported", adc->name); + return result; + } +#if defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) && defined(ADC_EXTERNALTRIGCONVEDGE_RISING) + fields->edge = ADC_EXTERNALTRIGCONVEDGE_RISING; +#elif defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) + return -RT_ENOSYS; +#else + fields->edge = 0U; +#endif /* defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) && defined(ADC_EXTERNALTRIGCONVEDGE_RISING) */ + return RT_EOK; +#else + return -RT_ENOSYS; +#endif /* defined(STM32_ADC_USING_TIMER_TRIGGER) */ + + case RT_ADC_TRIGGER_TIMER_COMPARE: + case RT_ADC_TRIGGER_PWM_EDGE: + case RT_ADC_TRIGGER_EXTI_EDGE: + case RT_ADC_TRIGGER_ANALOG_COMPARE: + case RT_ADC_TRIGGER_BACKEND: + return -RT_ENOSYS; + + default: + return -RT_EINVAL; + } +} + +/** + * @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_tim.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_tim.c index b236a7ffdd5..aa4b13d888c 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,9 @@ 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. */ +#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */ }; static struct stm32_clock_timer stm32_clock_timer_obj[] = @@ -485,6 +526,268 @@ 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 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; + 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 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) + { + 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); + return timer_trigger_update_config(timer_device, prescaler, period); +} + +/** + * @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; + 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); + __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) +{ + TIM_HandleTypeDef *tim; + rt_err_t result; + + tim = (TIM_HandleTypeDef *)timer->parent.user_data; + if (tim == RT_NULL) + { + return -RT_EINVAL; + } + + 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; + 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 +795,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 +805,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 +889,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/adc/Kconfig b/components/drivers/adc/Kconfig index dd7e9598568..06ff649f67d 100644 --- a/components/drivers/adc/Kconfig +++ b/components/drivers/adc/Kconfig @@ -10,6 +10,22 @@ menuconfig RT_USING_ADC_V2 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 update trigger support" + depends on RT_ADC_USING_TRIGGER + default n + help + Enable timer update/TRGO events as ADC stream trigger sources. + + config RT_ADC_USING_STREAM bool "Enable ADC stream framework" default n diff --git a/components/drivers/adc/SConscript b/components/drivers/adc/SConscript index 90ee471f4a4..621601ff22a 100644 --- a/components/drivers/adc/SConscript +++ b/components/drivers/adc/SConscript @@ -7,6 +7,9 @@ CPPPATH = [cwd + '/../include'] 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'] diff --git a/components/drivers/adc/adc_v2.c b/components/drivers/adc/adc_v2.c index 84f3cf48124..9ec3b6ac111 100644 --- a/components/drivers/adc/adc_v2.c +++ b/components/drivers/adc/adc_v2.c @@ -653,6 +653,9 @@ rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const stru 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 */ @@ -1126,6 +1129,9 @@ rt_err_t rt_adc_stream_start(rt_adc_device_t device, rt_uint32_t channels, const 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); @@ -1140,6 +1146,13 @@ rt_err_t rt_adc_stream_start(rt_adc_device_t device, rt_uint32_t channels, const 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); @@ -1154,6 +1167,13 @@ rt_err_t rt_adc_stream_start(rt_adc_device_t device, rt_uint32_t channels, const 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; @@ -1163,6 +1183,9 @@ rt_err_t rt_adc_stream_start(rt_adc_device_t device, rt_uint32_t channels, const { 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) { @@ -1366,7 +1389,12 @@ rt_err_t rt_adc_stream_stop(rt_adc_device_t device) 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); diff --git a/components/drivers/adc/adc_v2_internal.h b/components/drivers/adc/adc_v2_internal.h index 4adeb244b29..1f97f17dd8b 100644 --- a/components/drivers/adc/adc_v2_internal.h +++ b/components/drivers/adc/adc_v2_internal.h @@ -15,4 +15,48 @@ #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 index b6106f7e405..2fcdc07043c 100644 --- a/components/drivers/adc/adc_v2_msh.c +++ b/components/drivers/adc/adc_v2_msh.c @@ -63,6 +63,19 @@ rt_weak rt_err_t rt_adc_msh_special(rt_adc_device_t device, int argc, char **arg 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"); +#endif /* defined(RT_ADC_TRIGGER_USING_TIMER) */ + rt_kprintf(" adc trigger clear\n"); + rt_kprintf(" adc trigger status\n"); +} +#endif /* defined(RT_ADC_USING_TRIGGER) */ #if defined(RT_ADC_USING_STREAM) /** @@ -94,6 +107,9 @@ static void adc_msh_usage(void) 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(); @@ -144,6 +160,61 @@ 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) +/** + * @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; +} + +/** + * @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) */ #ifdef RT_ADC_USING_STREAM /** @@ -194,6 +265,111 @@ static rt_uint32_t stream_fifo_buffer[RT_ADC_MSH_FIFO_TEST_FIFO_BUFFER_SIZE]; #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 +#endif /* defined(RT_ADC_TRIGGER_USING_TIMER) */ + + { + 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 /** @@ -870,6 +1046,12 @@ static int adc(int argc, char **argv) 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")) { diff --git a/components/drivers/adc/adc_v2_trigger.c b/components/drivers/adc/adc_v2_trigger.c new file mode 100644 index 00000000000..dbb8b45cda8 --- /dev/null +++ b/components/drivers/adc/adc_v2_trigger.c @@ -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-20 wdfk-prog add ADC V2 timer trigger framework implementation + */ + +/** + * @file adc_v2_trigger.c + * @brief ADC V2 timer 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: + case RT_ADC_TRIGGER_PWM_EDGE: + case RT_ADC_TRIGGER_EXTI_EDGE: + case RT_ADC_TRIGGER_ANALOG_COMPARE: + 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; + + if (cfg->type != RT_ADC_TRIGGER_TIMER_UPDATE) + { + return -RT_ENOSYS; + } + + timer_cfg.freq_hz = cfg->event.timer.freq_hz; + timer_cfg.event = CLOCK_TIMER_TRIGGER_EVENT_UPDATE; + + 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) + { + 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: + 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: + 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. + */ +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. + */ +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 index 280925a4c3a..969a33701bf 100644 --- a/components/drivers/include/drivers/adc_v2.h +++ b/components/drivers/include/drivers/adc_v2.h @@ -26,6 +26,9 @@ #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 @@ -111,6 +114,18 @@ struct rt_adc_core_ops */ 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. @@ -400,6 +415,9 @@ struct rt_adc_device 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 */ 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..4ce7d1cb6d3 100644 --- a/components/drivers/include/drivers/clock_time.h +++ b/components/drivers/include/drivers/clock_time.h @@ -47,9 +47,36 @@ 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 trigger output event type. + */ +enum rt_clock_timer_trigger_event +{ + CLOCK_TIMER_TRIGGER_EVENT_UPDATE = 0 /**< Generate trigger on timer update 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. */ +}; +#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */ + typedef enum { CLOCK_TIMER_MODE_ONESHOT = 0x01, From 00e9c8db991bac5169773e0131dcf516f3c1cfe1 Mon Sep 17 00:00:00 2001 From: wdfk-prog <1425075683@qq.com> Date: Thu, 4 Jun 2026 11:12:46 +0800 Subject: [PATCH 5/6] feat[ADCV2]: add timer and comparator trigger selectors add ADC V2 timer compare and analog comparator trigger configuration support extend clock timer trigger config with compare event and channel fields wire STM32 ADC external trigger selector mappings for TIM update, TIM compare, and COMP output add FinSH trigger_set commands and Kconfig switches for timer and comparator trigger backends --- .../libraries/HAL_Drivers/drivers/Kconfig | 18 +- .../HAL_Drivers/drivers/drv_adc_v2.c | 8 +- .../HAL_Drivers/drivers/drv_adc_v2_private.h | 14 +- .../HAL_Drivers/drivers/drv_adc_v2_trigger.c | 1184 ++++++++++++++--- .../libraries/HAL_Drivers/drivers/drv_tim.c | 197 ++- components/drivers/adc/Kconfig | 13 +- components/drivers/adc/adc_v2_msh.c | 127 +- components/drivers/adc/adc_v2_trigger.c | 54 +- .../drivers/include/drivers/clock_time.h | 9 +- 9 files changed, 1399 insertions(+), 225 deletions(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig index 731d599e5ff..3a02c8e6f23 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig @@ -67,7 +67,7 @@ if BSP_USING_ADC_V2 owned by the ADC trigger framework and timer trigger backend. config BSP_ADC_USING_TIMER_TRIGGER - bool "Enable ADC V2 timer update trigger backend" + 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 @@ -75,8 +75,20 @@ if BSP_USING_ADC_V2 select RT_USING_CLOCK_TIMER_TRIGGER default n help - Enable STM32 TIMx update/TRGO to ADC external trigger selector - mapping for ADC V2 stream pacing. + 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 diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c index ecdfec6e4c7..6c3c8bb5284 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2.c @@ -246,7 +246,7 @@ rt_bool_t stm32_adc_instance_match(ADC_TypeDef *instance, rt_uint32_t mask) */ 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) + if ((stm32_adc_hal_channel_valid(hal_channel) != RT_TRUE)) { return RT_FALSE; } @@ -1325,7 +1325,8 @@ static rt_err_t stm32_adc_apply_regular_config(struct stm32_adc *adc, rt_uint32_ 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 + /* + * 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. */ @@ -1342,7 +1343,6 @@ static rt_err_t stm32_adc_apply_regular_config(struct stm32_adc *adc, rt_uint32_ 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. @@ -1505,7 +1505,6 @@ static rt_err_t stm32_adc_sequence_read(struct rt_adc_device *device, rt_uint32_ return stm32_hal_status_to_rt_err(status); } - /** * @brief Stop one STM32 ADC sequence session. * @param device Pointer to the ADC device object. @@ -1740,7 +1739,6 @@ static rt_err_t stm32_adc_stream_start(struct rt_adc_device *device, rt_uint32_t { goto exit; } - status = HAL_ADC_Start_DMA(&adc->handle, dma_buffer, (uint32_t)cfg->dma_buffer_length); if (status != HAL_OK) { 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 index 05209355e9b..99d2ee9ff8d 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_private.h @@ -109,10 +109,17 @@ #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-update trigger selector backend is compiled in. */ +/** @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) */ @@ -190,6 +197,11 @@ #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) 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 index e3598a0b2bd..59a4d4c8c91 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_trigger.c +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_adc_v2_trigger.c @@ -10,7 +10,7 @@ /** * @file drv_adc_v2_trigger.c - * @brief STM32 ADC V2 timer trigger selector backend. + * @brief STM32 ADC V2 trigger selector backend. */ #include @@ -26,323 +26,1117 @@ #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 Fill software-start trigger fields. - * @param fields Pointer to the STM32 trigger fields to fill. + * @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 void stm32_adc_trigger_fields_set_software(struct stm32_adc_trigger_fields *fields) +static rt_err_t stm32_adc_trigger_edge_encode(enum rt_adc_trigger_edge edge, rt_uint32_t *hal_edge) { - fields->selector = ADC_SOFTWARE_START; + if (hal_edge == RT_NULL) + { + return -RT_EINVAL; + } + #if defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) - fields->edge = ADC_EXTERNALTRIGCONVEDGE_NONE; + 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 - fields->edge = 0U; + 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 Resolve TIMx update/TRGO selector for one STM32 ADC trigger source. - * @param tim Pointer to the STM32 HAL timer handle. - * @param selector Pointer to the output HAL ADC selector. - * @return Operation status. + * @brief STM32 timer to ADC trigger selector mapping entry. */ -static rt_err_t stm32_adc_timer_update_selector_get(const TIM_HandleTypeDef *tim, rt_uint32_t *selector) +struct stm32_adc_timer_trigger_map { - if ((tim == RT_NULL) || (selector == RT_NULL)) - { - return -RT_EINVAL; - } + 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]; +}; -#if defined(TIM1) && (defined(ADC_EXTERNALTRIGCONV_T1_TRGO) || defined(ADC_EXTERNALTRIG_T1_TRGO)) - if (tim->Instance == TIM1) +/** + * @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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T1_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T1_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM1) && (defined(ADC_EXTERNALTRIGCONV_T1_TRGO) || defined(ADC_EXTERNALTRIG_T1_TRGO)) */ -#if defined(TIM2) && (defined(ADC_EXTERNALTRIGCONV_T2_TRGO) || defined(ADC_EXTERNALTRIG_T2_TRGO)) - if (tim->Instance == TIM2) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T2_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T2_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM2) && (defined(ADC_EXTERNALTRIGCONV_T2_TRGO) || defined(ADC_EXTERNALTRIG_T2_TRGO)) */ -#if defined(TIM3) && (defined(ADC_EXTERNALTRIGCONV_T3_TRGO) || defined(ADC_EXTERNALTRIG_T3_TRGO)) - if (tim->Instance == TIM3) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T3_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T3_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM3) && (defined(ADC_EXTERNALTRIGCONV_T3_TRGO) || defined(ADC_EXTERNALTRIG_T3_TRGO)) */ -#if defined(TIM4) && (defined(ADC_EXTERNALTRIGCONV_T4_TRGO) || defined(ADC_EXTERNALTRIG_T4_TRGO)) - if (tim->Instance == TIM4) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T4_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T4_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM4) && (defined(ADC_EXTERNALTRIGCONV_T4_TRGO) || defined(ADC_EXTERNALTRIG_T4_TRGO)) */ -#if defined(TIM5) && (defined(ADC_EXTERNALTRIGCONV_T5_TRGO) || defined(ADC_EXTERNALTRIG_T5_TRGO)) - if (tim->Instance == TIM5) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T5_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T5_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM5) && (defined(ADC_EXTERNALTRIGCONV_T5_TRGO) || defined(ADC_EXTERNALTRIG_T5_TRGO)) */ -#if defined(TIM6) && (defined(ADC_EXTERNALTRIGCONV_T6_TRGO) || defined(ADC_EXTERNALTRIG_T6_TRGO)) - if (tim->Instance == TIM6) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T6_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T6_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM6) && (defined(ADC_EXTERNALTRIGCONV_T6_TRGO) || defined(ADC_EXTERNALTRIG_T6_TRGO)) */ -#if defined(TIM7) && (defined(ADC_EXTERNALTRIGCONV_T7_TRGO) || defined(ADC_EXTERNALTRIG_T7_TRGO)) - if (tim->Instance == TIM7) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T7_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T7_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM7) && (defined(ADC_EXTERNALTRIGCONV_T7_TRGO) || defined(ADC_EXTERNALTRIG_T7_TRGO)) */ -#if defined(TIM8) && (defined(ADC_EXTERNALTRIGCONV_T8_TRGO) || defined(ADC_EXTERNALTRIG_T8_TRGO)) - if (tim->Instance == TIM8) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T8_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T8_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM8) && (defined(ADC_EXTERNALTRIGCONV_T8_TRGO) || defined(ADC_EXTERNALTRIG_T8_TRGO)) */ -#if defined(TIM9) && (defined(ADC_EXTERNALTRIGCONV_T9_TRGO) || defined(ADC_EXTERNALTRIG_T9_TRGO)) - if (tim->Instance == TIM9) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T9_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T9_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM9) && (defined(ADC_EXTERNALTRIGCONV_T9_TRGO) || defined(ADC_EXTERNALTRIG_T9_TRGO)) */ -#if defined(TIM10) && (defined(ADC_EXTERNALTRIGCONV_T10_TRGO) || defined(ADC_EXTERNALTRIG_T10_TRGO)) - if (tim->Instance == TIM10) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T10_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T10_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM10) && (defined(ADC_EXTERNALTRIGCONV_T10_TRGO) || defined(ADC_EXTERNALTRIG_T10_TRGO)) */ -#if defined(TIM11) && (defined(ADC_EXTERNALTRIGCONV_T11_TRGO) || defined(ADC_EXTERNALTRIG_T11_TRGO)) - if (tim->Instance == TIM11) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T11_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T11_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM11) && (defined(ADC_EXTERNALTRIGCONV_T11_TRGO) || defined(ADC_EXTERNALTRIG_T11_TRGO)) */ -#if defined(TIM12) && (defined(ADC_EXTERNALTRIGCONV_T12_TRGO) || defined(ADC_EXTERNALTRIG_T12_TRGO)) - if (tim->Instance == TIM12) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T12_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T12_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM12) && (defined(ADC_EXTERNALTRIGCONV_T12_TRGO) || defined(ADC_EXTERNALTRIG_T12_TRGO)) */ -#if defined(TIM13) && (defined(ADC_EXTERNALTRIGCONV_T13_TRGO) || defined(ADC_EXTERNALTRIG_T13_TRGO)) - if (tim->Instance == TIM13) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T13_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T13_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM13) && (defined(ADC_EXTERNALTRIGCONV_T13_TRGO) || defined(ADC_EXTERNALTRIG_T13_TRGO)) */ -#if defined(TIM14) && (defined(ADC_EXTERNALTRIGCONV_T14_TRGO) || defined(ADC_EXTERNALTRIG_T14_TRGO)) - if (tim->Instance == TIM14) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T14_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T14_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM14) && (defined(ADC_EXTERNALTRIGCONV_T14_TRGO) || defined(ADC_EXTERNALTRIG_T14_TRGO)) */ -#if defined(TIM15) && (defined(ADC_EXTERNALTRIGCONV_T15_TRGO) || defined(ADC_EXTERNALTRIG_T15_TRGO)) - if (tim->Instance == TIM15) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T15_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T15_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM15) && (defined(ADC_EXTERNALTRIGCONV_T15_TRGO) || defined(ADC_EXTERNALTRIG_T15_TRGO)) */ -#if defined(TIM16) && (defined(ADC_EXTERNALTRIGCONV_T16_TRGO) || defined(ADC_EXTERNALTRIG_T16_TRGO)) - if (tim->Instance == TIM16) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T16_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T16_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM16) && (defined(ADC_EXTERNALTRIGCONV_T16_TRGO) || defined(ADC_EXTERNALTRIG_T16_TRGO)) */ -#if defined(TIM17) && (defined(ADC_EXTERNALTRIGCONV_T17_TRGO) || defined(ADC_EXTERNALTRIG_T17_TRGO)) - if (tim->Instance == TIM17) + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T17_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T17_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM17) && (defined(ADC_EXTERNALTRIGCONV_T17_TRGO) || defined(ADC_EXTERNALTRIG_T17_TRGO)) */ -#if defined(TIM18) && (defined(ADC_EXTERNALTRIGCONV_T18_TRGO) || defined(ADC_EXTERNALTRIG_T18_TRGO)) - if (tim->Instance == TIM18) - { + { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T18_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T18_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM18) && (defined(ADC_EXTERNALTRIGCONV_T18_TRGO) || defined(ADC_EXTERNALTRIG_T18_TRGO)) */ -#if defined(TIM19) && (defined(ADC_EXTERNALTRIGCONV_T19_TRGO) || defined(ADC_EXTERNALTRIG_T19_TRGO)) - if (tim->Instance == TIM19) { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T19_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T19_TRGO) */ - return RT_EOK; - } -#endif /* defined(TIM19) && (defined(ADC_EXTERNALTRIGCONV_T19_TRGO) || defined(ADC_EXTERNALTRIG_T19_TRGO)) */ -#if defined(TIM20) && (defined(ADC_EXTERNALTRIGCONV_T20_TRGO) || defined(ADC_EXTERNALTRIG_T20_TRGO)) - if (tim->Instance == TIM20) { +#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) - *selector = 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 - *selector = ADC_EXTERNALTRIG_T20_TRGO; + STM32_ADC_TRIGGER_SELECTOR_NONE, #endif /* defined(ADC_EXTERNALTRIGCONV_T20_TRGO) */ - return RT_EOK; + { +#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; } -#endif /* defined(TIM20) && (defined(ADC_EXTERNALTRIGCONV_T20_TRGO) || defined(ADC_EXTERNALTRIG_T20_TRGO)) */ - return -RT_ENOSYS; + return RT_FALSE; } -#endif /* defined(STM32_ADC_USING_TIMER_TRIGGER) */ /** - * @brief Resolve STM32 ADC trigger selector fields. + * @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, or RT_NULL for software start. - * @param fields Pointer to the output STM32 trigger fields. + * @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. */ -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) +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) { -#if defined(STM32_ADC_USING_TIMER_TRIGGER) TIM_HandleTypeDef *tim; -#endif /* defined(STM32_ADC_USING_TIMER_TRIGGER) */ + rt_uint16_t channel; rt_err_t result; - if (cfg == RT_NULL) + if (cfg->event.timer.timer == RT_NULL) { - stm32_adc_trigger_fields_set_software(fields); - return RT_EOK; + 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: -#if defined(STM32_ADC_USING_TIMER_TRIGGER) - if (cfg->event.timer.timer == RT_NULL) - { - return -RT_EINVAL; - } + channel = 0U; + break; - tim = (TIM_HandleTypeDef *)cfg->event.timer.timer->user_data; - if (tim == RT_NULL) + 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; - result = stm32_adc_timer_update_selector_get(tim, &fields->selector); - if (result != RT_EOK) - { - LOG_E("%s timer update trigger selector unsupported", adc->name); - return result; - } -#if defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) && defined(ADC_EXTERNALTRIGCONVEDGE_RISING) - fields->edge = ADC_EXTERNALTRIGCONVEDGE_RISING; -#elif defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) - return -RT_ENOSYS; -#else - fields->edge = 0U; -#endif /* defined(STM32_ADC_HAS_INIT_EXT_TRIG_EDGE) && defined(ADC_EXTERNALTRIGCONVEDGE_RISING) */ - return RT_EOK; -#else + 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: - case RT_ADC_TRIGGER_PWM_EDGE: - case RT_ADC_TRIGGER_EXTI_EDGE: + 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: - case RT_ADC_TRIGGER_BACKEND: - return -RT_ENOSYS; + result = stm32_adc_encode_compare_trigger(adc, cfg, selector, edge); + break; +#endif /* defined(STM32_ADC_USING_ANALOG_COMPARE_TRIGGER) */ + default: - return -RT_EINVAL; + 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); } /** diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_tim.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_tim.c index aa4b13d888c..a443bc1494f 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_tim.c +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_tim.c @@ -344,6 +344,7 @@ struct stm32_clock_timer 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) */ }; @@ -586,6 +587,56 @@ static rt_err_t timer_trigger_calc(rt_clock_timer_t *timer, rt_uint32_t freq_hz, 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. @@ -638,6 +689,7 @@ static rt_err_t timer_trigger_update_config(struct stm32_clock_timer *timer_devi } 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); @@ -651,6 +703,93 @@ static rt_err_t timer_trigger_update_config(struct stm32_clock_timer *timer_devi #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. @@ -669,7 +808,8 @@ static rt_err_t timer_trigger_config(rt_clock_timer_t *timer, const struct rt_cl return -RT_EINVAL; } - if (cfg->event != CLOCK_TIMER_TRIGGER_EVENT_UPDATE) + if ((cfg->event != CLOCK_TIMER_TRIGGER_EVENT_UPDATE) && + (cfg->event != CLOCK_TIMER_TRIGGER_EVENT_COMPARE)) { return -RT_EINVAL; } @@ -687,7 +827,18 @@ static rt_err_t timer_trigger_config(rt_clock_timer_t *timer, const struct rt_cl } stm32_tim_enable_clock(&timer_device->tim_handle); - return timer_trigger_update_config(timer_device, prescaler, period); + + 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; + } } /** @@ -698,6 +849,7 @@ static rt_err_t timer_trigger_config(rt_clock_timer_t *timer, const struct rt_cl 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; @@ -709,8 +861,19 @@ static rt_err_t timer_trigger_start(rt_clock_timer_t *timer) tim = &timer_device->tim_handle; tim->Instance->CR1 &= (~TIM_OPMODE_SINGLE); __HAL_TIM_SET_COUNTER(tim, 0); - __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE); + 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; } @@ -721,19 +884,36 @@ static rt_err_t timer_trigger_start(rt_clock_timer_t *timer) */ 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; - tim = (TIM_HandleTypeDef *)timer->parent.user_data; - if (tim == RT_NULL) + timer_device = (struct stm32_clock_timer *)timer; + if (timer_device->time_device.parent.user_data == RT_NULL) { return -RT_EINVAL; } - 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); + 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; } @@ -783,6 +963,7 @@ static rt_err_t timer_trigger_release(rt_clock_timer_t *timer) } timer_device->trigger_event = CLOCK_TIMER_TRIGGER_EVENT_UPDATE; + timer_device->trigger_channel = 0U; return result; } diff --git a/components/drivers/adc/Kconfig b/components/drivers/adc/Kconfig index 06ff649f67d..b4202ad5690 100644 --- a/components/drivers/adc/Kconfig +++ b/components/drivers/adc/Kconfig @@ -19,11 +19,19 @@ config RT_ADC_USING_TRIGGER start/stop are delegated to the timer trigger backend. config RT_ADC_TRIGGER_USING_TIMER - bool "Enable ADC timer update trigger support" + bool "Enable ADC timer trigger selector support" depends on RT_ADC_USING_TRIGGER default n help - Enable timer update/TRGO events as ADC stream trigger sources. + 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 @@ -98,3 +106,4 @@ config RT_ADC_V2_USING_MSH the ADC V2 framework and driver APIs available. endif + diff --git a/components/drivers/adc/adc_v2_msh.c b/components/drivers/adc/adc_v2_msh.c index 2fcdc07043c..7bc42f6cbf5 100644 --- a/components/drivers/adc/adc_v2_msh.c +++ b/components/drivers/adc/adc_v2_msh.c @@ -71,7 +71,11 @@ 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"); } @@ -160,7 +164,7 @@ 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) +#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. @@ -189,6 +193,43 @@ static rt_err_t adc_msh_parse_ulong(const char *arg, unsigned long max_value, un 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. @@ -214,7 +255,7 @@ static rt_err_t adc_msh_find_trigger_source(const char *name, rt_device_t *sourc *source = dev; return RT_EOK; } -#endif /* defined(RT_ADC_USING_TRIGGER) && defined(RT_ADC_TRIGGER_USING_TIMER) */ +#endif /* defined(RT_ADC_USING_TRIGGER) && (defined(RT_ADC_TRIGGER_USING_TIMER) || defined(RT_ADC_TRIGGER_USING_COMPARE)) */ #ifdef RT_ADC_USING_STREAM /** @@ -350,9 +391,91 @@ static rt_err_t adc_msh_trigger(rt_adc_device_t device, int argc, char **argv) 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; diff --git a/components/drivers/adc/adc_v2_trigger.c b/components/drivers/adc/adc_v2_trigger.c index dbb8b45cda8..0521201c49b 100644 --- a/components/drivers/adc/adc_v2_trigger.c +++ b/components/drivers/adc/adc_v2_trigger.c @@ -10,7 +10,7 @@ /** * @file adc_v2_trigger.c - * @brief ADC V2 timer trigger framework implementation. + * @brief ADC V2 trigger framework implementation. */ #include @@ -51,9 +51,30 @@ static rt_err_t adc_validate_trigger_cfg_common(const struct rt_adc_trigger_cfg #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_ANALOG_COMPARE: case RT_ADC_TRIGGER_BACKEND: return -RT_ENOSYS; @@ -98,14 +119,24 @@ static rt_err_t adc_trigger_timer_source_start(const struct rt_adc_trigger_cfg * struct rt_clock_timer_trigger_cfg timer_cfg = {0}; rt_err_t result; - if (cfg->type != RT_ADC_TRIGGER_TIMER_UPDATE) + 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; } - timer_cfg.freq_hz = cfg->event.timer.freq_hz; - timer_cfg.event = CLOCK_TIMER_TRIGGER_EVENT_UPDATE; - result = rt_device_control(cfg->event.timer.timer, CLOCK_TIMER_CTRL_TRIGGER_CONFIG, &timer_cfg); if (result != RT_EOK) { @@ -137,7 +168,7 @@ static rt_err_t adc_trigger_timer_source_stop(const struct rt_adc_trigger_cfg *c rt_err_t stop_result; rt_err_t release_result; - if (cfg->type != RT_ADC_TRIGGER_TIMER_UPDATE) + if ((cfg->type != RT_ADC_TRIGGER_TIMER_UPDATE) && (cfg->type != RT_ADC_TRIGGER_TIMER_COMPARE)) { return -RT_ENOSYS; } @@ -172,6 +203,7 @@ static rt_err_t adc_trigger_source_start(rt_adc_device_t device) { #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) */ @@ -199,6 +231,7 @@ static rt_err_t adc_trigger_source_stop(rt_adc_device_t device) { #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) */ @@ -269,12 +302,18 @@ rt_err_t adc_trigger_source_control(rt_adc_device_t device, enum adc_trigger_sou * @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; @@ -330,6 +369,7 @@ rt_err_t rt_adc_trigger_set(rt_adc_device_t device, const struct rt_adc_trigger_ * @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) { diff --git a/components/drivers/include/drivers/clock_time.h b/components/drivers/include/drivers/clock_time.h index 4ce7d1cb6d3..c43c079eb0b 100644 --- a/components/drivers/include/drivers/clock_time.h +++ b/components/drivers/include/drivers/clock_time.h @@ -58,11 +58,14 @@ typedef enum #if defined(RT_USING_CLOCK_TIMER_TRIGGER) /** - * @brief Hardware trigger output event type. + * @brief Hardware timer trigger output event type. */ enum rt_clock_timer_trigger_event { - CLOCK_TIMER_TRIGGER_EVENT_UPDATE = 0 /**< Generate trigger on timer update 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. */ }; /** @@ -74,6 +77,8 @@ 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) */ From ed0167724e5cb56fa04335d915a69c2f3491884a Mon Sep 17 00:00:00 2001 From: CYFS <2805686936@qq.com> Date: Thu, 4 Jun 2026 16:22:41 +0800 Subject: [PATCH 6/6] fix[ADC V2]: resolve ADC V1 compatibility Kconfig loop --- .../libraries/HAL_Drivers/drivers/Kconfig | 2 +- .../libraries/HAL_Drivers/drivers/SConscript | 2 +- components/drivers/adc/Kconfig | 26 ++++++++++++++----- components/drivers/adc/SConscript | 7 ++++- components/drivers/{misc => adc}/adc.c | 0 components/drivers/include/drivers/adc_v2.h | 6 ++--- components/drivers/include/rtdevice.h | 6 ++--- components/drivers/misc/Kconfig | 8 ------ components/drivers/misc/SConscript | 3 --- 9 files changed, 32 insertions(+), 28 deletions(-) rename components/drivers/{misc => adc}/adc.c (100%) diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig index 3a02c8e6f23..633ffd2dd26 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/Kconfig @@ -26,8 +26,8 @@ endif menuconfig BSP_USING_ADC_V2 bool "Enable ADC V2" + select RT_USING_ADC select RT_USING_ADC_V2 - depends on !RT_USING_ADC default n if BSP_USING_ADC_V2 diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript index 15369e06c8f..be974a8bc8f 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript +++ b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript @@ -46,7 +46,7 @@ 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']): diff --git a/components/drivers/adc/Kconfig b/components/drivers/adc/Kconfig index b4202ad5690..28d9ec47a00 100644 --- a/components/drivers/adc/Kconfig +++ b/components/drivers/adc/Kconfig @@ -1,11 +1,22 @@ -menuconfig RT_USING_ADC_V2 - bool "Using ADC V2 device drivers" - depends on !RT_USING_ADC +menuconfig RT_USING_ADC + bool "Using ADC device drivers" default n - help - Enable the standalone ADC V2 framework. ADC V2 currently uses the - legacy ADC public namespace, so it cannot be enabled together with - RT_USING_ADC. + +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 @@ -107,3 +118,4 @@ config RT_ADC_V2_USING_MSH endif +endif diff --git a/components/drivers/adc/SConscript b/components/drivers/adc/SConscript index 621601ff22a..94101138f0e 100644 --- a/components/drivers/adc/SConscript +++ b/components/drivers/adc/SConscript @@ -3,6 +3,10 @@ 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'] @@ -13,6 +17,7 @@ if GetDepend(['RT_USING_ADC_V2', 'RT_ADC_USING_TRIGGER']): if GetDepend(['RT_USING_ADC_V2', 'RT_USING_FINSH', 'RT_ADC_V2_USING_MSH']): src += ['adc_v2_msh.c'] -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_ADC_V2'], CPPPATH = CPPPATH) +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/include/drivers/adc_v2.h b/components/drivers/include/drivers/adc_v2.h index 969a33701bf..bf369e3a50c 100644 --- a/components/drivers/include/drivers/adc_v2.h +++ b/components/drivers/include/drivers/adc_v2.h @@ -18,9 +18,9 @@ #include #include "misc.h" -#if defined(RT_USING_ADC) -#error "ADC V2 uses the legacy ADC namespace; disable RT_USING_ADC before enabling ADC V2." -#endif /* defined(RT_USING_ADC) */ +#if !defined(RT_USING_ADC_V2) +#error "ADC V2 interface requires RT_USING_ADC_V2." +#endif /* !defined(RT_USING_ADC_V2) */ #include #include diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index f71ddc919f5..6cb25e856bd 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -259,12 +259,10 @@ extern "C" { #include "drivers/dev_audio.h" #endif /* RT_USING_AUDIO */ -#ifdef RT_USING_ADC -#include "drivers/adc.h" -#endif /* 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_V2 */ #ifdef RT_USING_DAC 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']