This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 72c1377e970eb8d673f688b8ab000202986dda97 Author: Darryl Ring <[email protected]> AuthorDate: Tue Oct 6 16:32:13 2026 -0700 arch/arm/stm32h5: Add capture support Clone the capture support from the STM32H7. Assisted-by: Claude:claude-sonnet-5-5 Signed-off-by: Darryl Ring <[email protected]> --- .../arm/stm32h5/boards/nucleo-h563zi/index.rst | 9 + Documentation/platforms/arm/stm32h5/index.rst | 28 + arch/arm/src/common/stm32/Kconfig.tim | 80 +- arch/arm/src/stm32h5/CMakeLists.txt | 7 + arch/arm/src/stm32h5/Make.defs | 7 + arch/arm/src/stm32h5/hardware/stm32h50xxx_pinmap.h | 48 + arch/arm/src/stm32h5/hardware/stm32h56xxx_pinmap.h | 68 + arch/arm/src/stm32h5/stm32_capture.c | 1331 ++++++++++++++++++++ arch/arm/src/stm32h5/stm32_capture.h | 240 ++++ arch/arm/src/stm32h5/stm32_capture_lowerhalf.c | 529 ++++++++ .../nucleo-h563zi/configs/capture/defconfig | 56 + boards/arm/stm32h5/nucleo-h563zi/include/board.h | 7 + .../arm/stm32h5/nucleo-h563zi/src/stm32_bringup.c | 83 ++ 13 files changed, 2457 insertions(+), 36 deletions(-) diff --git a/Documentation/platforms/arm/stm32h5/boards/nucleo-h563zi/index.rst b/Documentation/platforms/arm/stm32h5/boards/nucleo-h563zi/index.rst index 18244d39b2d..460a1f6ac7e 100644 --- a/Documentation/platforms/arm/stm32h5/boards/nucleo-h563zi/index.rst +++ b/Documentation/platforms/arm/stm32h5/boards/nucleo-h563zi/index.rst @@ -159,6 +159,15 @@ accessed at pin D6 on the CN10 A0 connector. TIM1_CH1 is configured as a pwm output at /dev/pwm0, and can be tested with the example pwm application. +capture: +-------- + +This configuration configures TIM4 as a capture timer to measure the frequency and +the duty cycle of a PWM input signal on TIM4_CH1 (pin PB6). It is registered at +/dev/cap0 and can be tested with the example capture application (``cap``), which prints +the measured frequency and duty cycle. The capture counter runs at 100 kHz, so only +input signals that have a period of up to 655 ms (down to about 1.5 Hz) can be measured. + adc_watchdog: -------------- diff --git a/Documentation/platforms/arm/stm32h5/index.rst b/Documentation/platforms/arm/stm32h5/index.rst index 5cd754c7890..c3a7021b5b4 100644 --- a/Documentation/platforms/arm/stm32h5/index.rst +++ b/Documentation/platforms/arm/stm32h5/index.rst @@ -116,6 +116,34 @@ Options: - STM32H5_USBDRD_DESCSIZE - Maximum size of a descriptor. Default: 128 +Timer Capture +------------- + +The STM32H5 timer capture driver measures the frequency and the duty cycle of +a PWM input signal using the PWM input mode of the timer. It is registered as +``/dev/cap0``, ``/dev/cap1``, ... (see ``include/nuttx/timers/capture.h``). + +Only the timers with two input channels can be used: TIM1, TIM2, TIM3, TIM4, +TIM5, TIM8, TIM12 and TIM15. + +Pre-requisites: + +- ``CONFIG_CAPTURE`` - Enable the upper-half capture driver +- ``CONFIG_STM32_TIMn`` and ``CONFIG_STM32_TIMn_CAP`` - Reserve timer ``n`` for capture + +Options: + +- ``CONFIG_STM32_TIMn_CHANNEL`` - The input channel, 1 or 2. The signal is measured + on the pin of that channel. The other channel is mapped internally to the same input. +- ``CONFIG_STM32_TIMn_CLOCK`` - The counter frequency. It limits the resolution + of the measurement and the lowest frequency that can be measured (the counter must not + overflow within a period of the input signal). + +The board must define the pin of the selected channel in ``board.h``, e.g. +``GPIO_TIM4_CH1IN`` (see ``GPIO_TIMn_CHmIN_x`` in the pin map) and register the drivers +with ``stm32_cap_initialize()`` and ``cap_register_multiple()``, see the nucleo-h563zi +board for an example. + OTP --- diff --git a/arch/arm/src/common/stm32/Kconfig.tim b/arch/arm/src/common/stm32/Kconfig.tim index aae4d6ba70a..333d51695b9 100644 --- a/arch/arm/src/common/stm32/Kconfig.tim +++ b/arch/arm/src/common/stm32/Kconfig.tim @@ -137,7 +137,7 @@ endmenu # Timer Configuration config STM32_TIMX_CAP bool "Helpers for Capture Drivers" - depends on ARCH_CHIP_STM32H7 + depends on ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5 default n choice @@ -1229,8 +1229,9 @@ config STM32_TIM1_CH6OUT config STM32_TIM1_CHANNEL int "TIM1 PWM Output Channel" - depends on (STM32_TIM1_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM1_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7)) + depends on (STM32_TIM1_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM1_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5)) default 1 + range 1 2 if ARCH_CHIP_STM32H5 && STM32_TIM1_CAP range 1 6 if ARCH_CHIP_STM32H7 && STM32_TIM1_CAP range 1 4 if !ARCH_CHIP_STM32H7 || !STM32_TIM1_CAP ---help--- @@ -1373,8 +1374,9 @@ config STM32_TIM2_CH4OUT config STM32_TIM2_CHANNEL int "TIM2 PWM Output Channel" - depends on (STM32_TIM2_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM2_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7)) + depends on (STM32_TIM2_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM2_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5)) default 1 + range 1 2 if ARCH_CHIP_STM32H5 && STM32_TIM2_CAP range 1 4 ---help--- If TIM2 is enabled for PWM usage, you also need specifies the timer output @@ -1516,8 +1518,9 @@ config STM32_TIM3_CH4OUT config STM32_TIM3_CHANNEL int "TIM3 PWM Output Channel" - depends on (STM32_TIM3_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM3_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7)) + depends on (STM32_TIM3_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM3_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5)) default 1 + range 1 2 if ARCH_CHIP_STM32H5 && STM32_TIM3_CAP range 1 4 ---help--- If TIM3 is enabled for PWM usage, you also need specifies the timer output @@ -1659,8 +1662,9 @@ config STM32_TIM4_CH4OUT config STM32_TIM4_CHANNEL int "TIM4 PWM Output Channel" - depends on (STM32_TIM4_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM4_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7)) + depends on (STM32_TIM4_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM4_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5)) default 1 + range 1 2 if ARCH_CHIP_STM32H5 && STM32_TIM4_CAP range 1 4 ---help--- If TIM4 is enabled for PWM usage, you also need specifies the timer output @@ -1802,8 +1806,9 @@ config STM32_TIM5_CH4OUT config STM32_TIM5_CHANNEL int "TIM5 PWM Output Channel" - depends on (STM32_TIM5_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM5_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7)) + depends on (STM32_TIM5_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM5_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5)) default 1 + range 1 2 if ARCH_CHIP_STM32H5 && STM32_TIM5_CAP range 1 4 ---help--- If TIM5 is enabled for PWM usage, you also need specifies the timer output @@ -2042,8 +2047,9 @@ config STM32_TIM8_CH6OUT config STM32_TIM8_CHANNEL int "TIM8 PWM Output Channel" - depends on (STM32_TIM8_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM8_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7)) + depends on (STM32_TIM8_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM8_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5)) default 1 + range 1 2 if ARCH_CHIP_STM32H5 && STM32_TIM8_CAP range 1 6 if ARCH_CHIP_STM32H7 && STM32_TIM8_CAP range 1 4 if !ARCH_CHIP_STM32H7 || !STM32_TIM8_CAP ---help--- @@ -2305,8 +2311,9 @@ config STM32_TIM12_CH2OUT config STM32_TIM12_CHANNEL int "TIM12 PWM Output Channel" - depends on (STM32_TIM12_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM12_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7)) + depends on (STM32_TIM12_PWM && !STM32_PWM_MULTICHAN) || (STM32_TIM12_CAP && ((STM32_HAVE_IP_TIMERS && STM32_TIM) || ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5)) default 1 + range 1 2 if ARCH_CHIP_STM32H5 && STM32_TIM12_CAP range 1 4 if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM12_CAP range 1 2 if !STM32_HAVE_IP_TIMERS || !STM32_TIM12_CAP ---help--- @@ -2531,8 +2538,9 @@ config STM32_TIM15_CH2OUT config STM32_TIM15_CHANNEL int "TIM15 PWM Output Channel" - depends on (STM32_TIM15_PWM && !STM32_PWM_MULTICHAN) || (ARCH_CHIP_STM32H7 && STM32_TIM15_CAP) + depends on (STM32_TIM15_PWM && !STM32_PWM_MULTICHAN) || ((ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM15_CAP) default 1 + range 1 2 if ARCH_CHIP_STM32H5 && STM32_TIM15_CAP range 1 2 ---help--- If TIM15 is enabled for PWM usage, you also need specifies the timer output @@ -2799,7 +2807,7 @@ config STM32_TIM1_CAP bool "TIM1 Capture" depends on STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM1 || (STM32_COMMON_F7_H7_H5) && STM32_TIM1 || STM32_COMMON_L4_L5_U5 && STM32_HAVE_TIM1 select STM32_CAP if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM1 - select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM1 + select STM32_TIMX_CAP if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM1 ---help--- Reserve timer 1 for use by Capture @@ -2808,9 +2816,9 @@ config STM32_TIM1_CAP config STM32_TIM1_CLOCK int "TIM1 work frequency for capture" - depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM1_CAP) || (ARCH_CHIP_STM32H7 && STM32_TIM1_CAP) + depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM1_CAP) || ((ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM1_CAP) default 1000000 if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM1_CAP - default 100000 if ARCH_CHIP_STM32H7 && STM32_TIM1_CAP + default 100000 if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM1_CAP ---help--- This clock frequency limiting the count rate at the expense of resolution. @@ -2818,7 +2826,7 @@ config STM32_TIM2_CAP bool "TIM2 Capture" depends on STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM2 || (STM32_COMMON_F7_H7_H5) && STM32_TIM2 || STM32_COMMON_L4_L5_U5 && STM32_HAVE_TIM2 select STM32_CAP if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM2 - select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM2 + select STM32_TIMX_CAP if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM2 ---help--- Reserve timer 2 for use by Capture @@ -2827,9 +2835,9 @@ config STM32_TIM2_CAP config STM32_TIM2_CLOCK int "TIM2 work frequency for capture" - depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM2_CAP) || (ARCH_CHIP_STM32H7 && STM32_TIM2_CAP) + depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM2_CAP) || ((ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM2_CAP) default 1000000 if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM2_CAP - default 100000 if ARCH_CHIP_STM32H7 && STM32_TIM2_CAP + default 100000 if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM2_CAP ---help--- This clock frequency limiting the count rate at the expense of resolution. @@ -2837,7 +2845,7 @@ config STM32_TIM3_CAP bool "TIM3 Capture" depends on STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM3 || (STM32_COMMON_F7_H7_H5) && STM32_TIM3 || STM32_COMMON_L4_L5_U5 && STM32_HAVE_TIM3 select STM32_CAP if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM3 - select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM3 + select STM32_TIMX_CAP if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM3 ---help--- Reserve timer 3 for use by Capture @@ -2846,9 +2854,9 @@ config STM32_TIM3_CAP config STM32_TIM3_CLOCK int "TIM3 work frequency for capture" - depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM3_CAP) || (ARCH_CHIP_STM32H7 && STM32_TIM3_CAP) + depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM3_CAP) || ((ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM3_CAP) default 1000000 if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM3_CAP - default 100000 if ARCH_CHIP_STM32H7 && STM32_TIM3_CAP + default 100000 if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM3_CAP ---help--- This clock frequency limiting the count rate at the expense of resolution. @@ -2856,7 +2864,7 @@ config STM32_TIM4_CAP bool "TIM4 Capture" depends on STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM4 || (STM32_COMMON_F7_H7_H5) && STM32_TIM4 || STM32_COMMON_L4_L5_U5 && STM32_HAVE_TIM4 select STM32_CAP if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM4 - select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM4 + select STM32_TIMX_CAP if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM4 ---help--- Reserve timer 4 for use by Capture @@ -2865,9 +2873,9 @@ config STM32_TIM4_CAP config STM32_TIM4_CLOCK int "TIM4 work frequency for capture" - depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM4_CAP) || (ARCH_CHIP_STM32H7 && STM32_TIM4_CAP) + depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM4_CAP) || ((ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM4_CAP) default 1000000 if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM4_CAP - default 100000 if ARCH_CHIP_STM32H7 && STM32_TIM4_CAP + default 100000 if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM4_CAP ---help--- This clock frequency limiting the count rate at the expense of resolution. @@ -2875,7 +2883,7 @@ config STM32_TIM5_CAP bool "TIM5 Capture" depends on STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM5 || (STM32_COMMON_F7_H7_H5) && STM32_TIM5 || STM32_COMMON_L4_L5_U5 && STM32_HAVE_TIM5 select STM32_CAP if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM5 - select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM5 + select STM32_TIMX_CAP if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM5 ---help--- Reserve timer 5 for use by Capture @@ -2884,9 +2892,9 @@ config STM32_TIM5_CAP config STM32_TIM5_CLOCK int "TIM5 work frequency for capture" - depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM5_CAP) || (ARCH_CHIP_STM32H7 && STM32_TIM5_CAP) + depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM5_CAP) || ((ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM5_CAP) default 1000000 if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM5_CAP - default 100000 if ARCH_CHIP_STM32H7 && STM32_TIM5_CAP + default 100000 if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM5_CAP ---help--- This clock frequency limiting the count rate at the expense of resolution. @@ -2894,7 +2902,7 @@ config STM32_TIM8_CAP bool "TIM8 Capture" depends on STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM8 || (STM32_COMMON_F7_H7_H5) && STM32_TIM8 || STM32_COMMON_L4_L5_U5 && STM32_HAVE_TIM8 select STM32_CAP if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM8 - select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM8 + select STM32_TIMX_CAP if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM8 ---help--- Reserve timer 8 for use by Capture @@ -2903,9 +2911,9 @@ config STM32_TIM8_CAP config STM32_TIM8_CLOCK int "TIM8 work frequency for capture" - depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM8_CAP) || (ARCH_CHIP_STM32H7 && STM32_TIM8_CAP) + depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM8_CAP) || ((ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM8_CAP) default 1000000 if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM8_CAP - default 100000 if ARCH_CHIP_STM32H7 && STM32_TIM8_CAP + default 100000 if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM8_CAP ---help--- This clock frequency limiting the count rate at the expense of resolution. @@ -2943,7 +2951,7 @@ config STM32_TIM12_CAP bool "TIM12 Capture" depends on STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM12 || (STM32_COMMON_F7_H7_H5) && STM32_TIM12 select STM32_CAP if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM12 - select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM12 + select STM32_TIMX_CAP if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM12 ---help--- Reserve timer 12 for use by Capture @@ -2952,15 +2960,15 @@ config STM32_TIM12_CAP config STM32_TIM12_CLOCK int "TIM12 work frequency for capture" - depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM12_CAP) || (ARCH_CHIP_STM32H7 && STM32_TIM12_CAP) + depends on (STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM12_CAP) || ((ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM12_CAP) default 1000000 if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM12_CAP - default 100000 if ARCH_CHIP_STM32H7 && STM32_TIM12_CAP + default 100000 if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM12_CAP ---help--- This clock frequency limiting the count rate at the expense of resolution. config STM32_TIM13_CAP bool "TIM13 Capture" - depends on STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM13 || (STM32_COMMON_F7_H7_H5) && STM32_TIM13 + depends on STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM13 || (STM32_COMMON_F7_H7) && STM32_TIM13 select STM32_CAP if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM13 select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM13 ---help--- @@ -2979,7 +2987,7 @@ config STM32_TIM13_CLOCK config STM32_TIM14_CAP bool "TIM14 Capture" - depends on STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM14 || (STM32_COMMON_F7_H7_H5) && STM32_TIM14 + depends on STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM14 || (STM32_COMMON_F7_H7) && STM32_TIM14 select STM32_CAP if STM32_HAVE_IP_TIMERS && STM32_TIM && STM32_TIM14 select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM14 ---help--- @@ -3893,27 +3901,27 @@ config STM32_TIM17_CH1NOUT config STM32_TIM15_CAP bool "TIM15 Capture" depends on STM32_COMMON_H7_H5 && STM32_TIM15 - select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM15 + select STM32_TIMX_CAP if (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM15 ---help--- Reserve timer 15 for use by the capture driver. config STM32_TIM16_CAP bool "TIM16 Capture" - depends on STM32_COMMON_H7_H5 && STM32_TIM16 + depends on ARCH_CHIP_STM32H7 && STM32_TIM16 select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM16 ---help--- Reserve timer 16 for use by the capture driver. config STM32_TIM17_CAP bool "TIM17 Capture" - depends on STM32_COMMON_H7_H5 && STM32_TIM17 + depends on ARCH_CHIP_STM32H7 && STM32_TIM17 select STM32_TIMX_CAP if ARCH_CHIP_STM32H7 && STM32_TIM17 ---help--- Reserve timer 17 for use by the capture driver. config STM32_TIM15_CLOCK int "TIM15 capture frequency (Hz)" - depends on ARCH_CHIP_STM32H7 && STM32_TIM15_CAP + depends on (ARCH_CHIP_STM32H7 || ARCH_CHIP_STM32H5) && STM32_TIM15_CAP default 100000 ---help--- This clock frequency determines the timer's counting rate. diff --git a/arch/arm/src/stm32h5/CMakeLists.txt b/arch/arm/src/stm32h5/CMakeLists.txt index 6d7386c87a5..1284ecfa936 100644 --- a/arch/arm/src/stm32h5/CMakeLists.txt +++ b/arch/arm/src/stm32h5/CMakeLists.txt @@ -104,6 +104,13 @@ if(CONFIG_STM32_PWM) list(APPEND SRCS stm32_pwm.c) endif() +if(CONFIG_STM32_TIMX_CAP) + list(APPEND SRCS stm32_capture.c) + if(CONFIG_CAPTURE) + list(APPEND SRCS stm32_capture_lowerhalf.c) + endif() +endif() + # Required chip type specific files if(CONFIG_STM32_STM32H5XXXX) diff --git a/arch/arm/src/stm32h5/Make.defs b/arch/arm/src/stm32h5/Make.defs index 99525ed6615..1c620a10773 100644 --- a/arch/arm/src/stm32h5/Make.defs +++ b/arch/arm/src/stm32h5/Make.defs @@ -112,6 +112,13 @@ ifeq ($(CONFIG_STM32_PWM),y) CHIP_CSRCS += stm32_pwm.c endif +ifeq ($(CONFIG_STM32_TIMX_CAP),y) +CHIP_CSRCS += stm32_capture.c +ifeq ($(CONFIG_CAPTURE),y) +CHIP_CSRCS += stm32_capture_lowerhalf.c +endif +endif + ifeq ($(CONFIG_PM),y) CHIP_CSRCS += stm32_pmstandby.c stm32_pmstop.c ifneq ($(CONFIG_ARCH_CUSTOM_PMINIT),y) diff --git a/arch/arm/src/stm32h5/hardware/stm32h50xxx_pinmap.h b/arch/arm/src/stm32h5/hardware/stm32h50xxx_pinmap.h index e4d36129a10..6aa32be6aea 100644 --- a/arch/arm/src/stm32h5/hardware/stm32h50xxx_pinmap.h +++ b/arch/arm/src/stm32h5/hardware/stm32h50xxx_pinmap.h @@ -164,18 +164,26 @@ /* Timers */ #define GPIO_TIM1_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) +#define GPIO_TIM1_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN8) #define GPIO_TIM1_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN13) +#define GPIO_TIM1_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN13) #define GPIO_TIM1_CH1OUT_3 (GPIO_ALT|GPIO_AF14|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7) +#define GPIO_TIM1_CH1IN_3 (GPIO_ALT|GPIO_AF14|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN7) #define GPIO_TIM1_CH1OUT_4 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM1_CH1IN_4 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6) #define GPIO_TIM1_CH1NOUT_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN3) #define GPIO_TIM1_CH1NOUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN7) #define GPIO_TIM1_CH1NOUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN13) #define GPIO_TIM1_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9) +#define GPIO_TIM1_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN9) #define GPIO_TIM1_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN14) +#define GPIO_TIM1_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN14) #define GPIO_TIM1_CH2OUT_3 (GPIO_ALT|GPIO_AF14|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN4) +#define GPIO_TIM1_CH2IN_3 (GPIO_ALT|GPIO_AF14|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN4) #define GPIO_TIM1_CH2OUT_4 (GPIO_ALT|GPIO_AF14|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6) +#define GPIO_TIM1_CH2IN_4 (GPIO_ALT|GPIO_AF14|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN6) #define GPIO_TIM1_CH2NOUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN4) #define GPIO_TIM1_CH2NOUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN0) @@ -184,18 +192,26 @@ #define GPIO_TIM1_CH2NOUT_5 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN14) #define GPIO_TIM1_CH3OUT_1 (GPIO_ALT|GPIO_AF14|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM1_CH3IN_1 (GPIO_ALT|GPIO_AF14|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1) #define GPIO_TIM1_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10) +#define GPIO_TIM1_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN10) #define GPIO_TIM1_CH3OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) +#define GPIO_TIM1_CH3IN_3 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN5) #define GPIO_TIM1_CH3OUT_4 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM1_CH3IN_4 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8) #define GPIO_TIM1_CH3NOUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN1) #define GPIO_TIM1_CH3NOUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN6) #define GPIO_TIM1_CH3NOUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN15) #define GPIO_TIM1_CH4OUT_1 (GPIO_ALT|GPIO_AF14|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM1_CH4IN_1 (GPIO_ALT|GPIO_AF14|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) #define GPIO_TIM1_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) +#define GPIO_TIM1_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN11) #define GPIO_TIM1_CH4OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM1_CH4IN_3 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9) #define GPIO_TIM1_CH4OUT_4 (GPIO_ALT|GPIO_AF14|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN12) +#define GPIO_TIM1_CH4IN_4 (GPIO_ALT|GPIO_AF14|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN12) #define GPIO_TIM1_CH4NOUT_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN8) #define GPIO_TIM1_CH4NOUT_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN14) @@ -203,44 +219,76 @@ #define GPIO_TIM1_CH4NOUT_4 (GPIO_ALT|GPIO_AF1|GPIO_PORTC|GPIO_PIN5) #define GPIO_TIM2_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM2_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) #define GPIO_TIM2_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN5) +#define GPIO_TIM2_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5) #define GPIO_TIM2_CH1OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN15) +#define GPIO_TIM2_CH1IN_3 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15) #define GPIO_TIM2_CH1OUT_4 (GPIO_ALT|GPIO_AF14|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN2) +#define GPIO_TIM2_CH1IN_4 (GPIO_ALT|GPIO_AF14|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN2) #define GPIO_TIM2_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM2_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1) #define GPIO_TIM2_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN3) +#define GPIO_TIM2_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN3) #define GPIO_TIM2_CH2OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN11) +#define GPIO_TIM2_CH2IN_3 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN11) #define GPIO_TIM2_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM2_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) #define GPIO_TIM2_CH3OUT_2 (GPIO_ALT|GPIO_AF14|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM2_CH3IN_2 (GPIO_ALT|GPIO_AF14|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7) #define GPIO_TIM2_CH3OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10) +#define GPIO_TIM2_CH3IN_3 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN10) #define GPIO_TIM2_CH3OUT_4 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN2) +#define GPIO_TIM2_CH3IN_4 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN2) #define GPIO_TIM2_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM2_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) #define GPIO_TIM2_CH4OUT_2 (GPIO_ALT|GPIO_AF14|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12) +#define GPIO_TIM2_CH4IN_2 (GPIO_ALT|GPIO_AF14|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN12) #define GPIO_TIM2_CH4OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN4) +#define GPIO_TIM2_CH4IN_3 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN4) #define GPIO_TIM2_CH4OUT_4 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN12) +#define GPIO_TIM2_CH4IN_4 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN12) #define GPIO_TIM3_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM3_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) #define GPIO_TIM3_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM3_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6) #define GPIO_TIM3_CH1OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN14) +#define GPIO_TIM3_CH1IN_3 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN14) #define GPIO_TIM3_CH1OUT_4 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN4) +#define GPIO_TIM3_CH1IN_4 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN4) #define GPIO_TIM3_CH1OUT_5 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM3_CH1IN_5 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6) #define GPIO_TIM3_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM3_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7) #define GPIO_TIM3_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) +#define GPIO_TIM3_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN11) #define GPIO_TIM3_CH2OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) +#define GPIO_TIM3_CH2IN_3 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN5) #define GPIO_TIM3_CH2OUT_4 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM3_CH2IN_4 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7) #define GPIO_TIM3_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) +#define GPIO_TIM3_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN8) #define GPIO_TIM3_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM3_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN0) #define GPIO_TIM3_CH3OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6) +#define GPIO_TIM3_CH3IN_3 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN6) #define GPIO_TIM3_CH3OUT_4 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM3_CH3IN_4 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8) #define GPIO_TIM3_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12) +#define GPIO_TIM3_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN12) #define GPIO_TIM3_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1) +#define GPIO_TIM3_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN1) #define GPIO_TIM3_CH4OUT_3 (GPIO_ALT|GPIO_AF14|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN15) +#define GPIO_TIM3_CH4IN_3 (GPIO_ALT|GPIO_AF14|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN15) #define GPIO_TIM3_CH4OUT_4 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM3_CH4IN_4 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9) /* USART/UART/LPUART */ diff --git a/arch/arm/src/stm32h5/hardware/stm32h56xxx_pinmap.h b/arch/arm/src/stm32h5/hardware/stm32h56xxx_pinmap.h index d88cd64d27c..aca8a176521 100644 --- a/arch/arm/src/stm32h5/hardware/stm32h56xxx_pinmap.h +++ b/arch/arm/src/stm32h5/hardware/stm32h56xxx_pinmap.h @@ -368,8 +368,11 @@ /* TIM1 (AF1) */ #define GPIO_TIM1_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) /* PA8 */ +#define GPIO_TIM1_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN8) /* PA8 */ #define GPIO_TIM1_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN9) /* PE9 */ +#define GPIO_TIM1_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN9) /* PE9 */ #define GPIO_TIM1_CH1OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN11) /* PH11 */ +#define GPIO_TIM1_CH1IN_3 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN11) /* PH11 */ #define GPIO_TIM1_CH1NOUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN7) /* PA7 */ #define GPIO_TIM1_CH1NOUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN13) /* PB13 */ @@ -377,8 +380,11 @@ #define GPIO_TIM1_CH1NOUT_4 (GPIO_ALT|GPIO_AF1|GPIO_PORTH|GPIO_PIN10) /* PH10 */ #define GPIO_TIM1_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9) /* PA9 */ +#define GPIO_TIM1_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN9) /* PA9 */ #define GPIO_TIM1_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN11) /* PE11 */ +#define GPIO_TIM1_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN11) /* PE11 */ #define GPIO_TIM1_CH2OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9) /* PH9 */ +#define GPIO_TIM1_CH2IN_3 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN9) /* PH9 */ #define GPIO_TIM1_CH2NOUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN0) /* PB0 */ #define GPIO_TIM1_CH2NOUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN14) /* PB14 */ @@ -386,8 +392,11 @@ #define GPIO_TIM1_CH2NOUT_4 (GPIO_ALT|GPIO_AF1|GPIO_PORTH|GPIO_PIN8) /* PH8 */ #define GPIO_TIM1_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10) /* PA10 */ +#define GPIO_TIM1_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN10) /* PA10 */ #define GPIO_TIM1_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN13) /* PE13 */ +#define GPIO_TIM1_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN13) /* PE13 */ #define GPIO_TIM1_CH3OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN7) /* PH7 */ +#define GPIO_TIM1_CH3IN_3 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN7) /* PH7 */ #define GPIO_TIM1_CH3NOUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN1) /* PB1 */ #define GPIO_TIM1_CH3NOUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN15) /* PB15 */ @@ -395,7 +404,9 @@ #define GPIO_TIM1_CH3NOUT_4 (GPIO_ALT|GPIO_AF1|GPIO_PORTH|GPIO_PIN6) /* PH6 */ #define GPIO_TIM1_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) /* PA11 */ +#define GPIO_TIM1_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN11) /* PA11 */ #define GPIO_TIM1_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN14) /* PE14 */ +#define GPIO_TIM1_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN14) /* PE14 */ #define GPIO_TIM1_CH4NOUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN15) /* PE15 */ #define GPIO_TIM1_CH4NOUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTC|GPIO_PIN5) /* PC5 */ @@ -403,62 +414,98 @@ /* TIM2 (AF1) */ #define GPIO_TIM2_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) /* PA0 */ +#define GPIO_TIM2_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) /* PA0 */ #define GPIO_TIM2_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN5) /* PA5 */ +#define GPIO_TIM2_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5) /* PA5 */ #define GPIO_TIM2_CH1OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN15) /* PA15 */ +#define GPIO_TIM2_CH1IN_3 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15) /* PA15 */ #define GPIO_TIM2_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) /* PA1 */ +#define GPIO_TIM2_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1) /* PA1 */ #define GPIO_TIM2_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN3) /* PB3 */ +#define GPIO_TIM2_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN3) /* PB3 */ #define GPIO_TIM2_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) /* PA2 */ +#define GPIO_TIM2_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) /* PA2 */ #define GPIO_TIM2_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10) /* PB10 */ +#define GPIO_TIM2_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN10) /* PB10 */ #define GPIO_TIM2_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) /* PA3 */ +#define GPIO_TIM2_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) /* PA3 */ #define GPIO_TIM2_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) /* PB11 */ +#define GPIO_TIM2_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN11) /* PB11 */ #define GPIO_TIM2_CH4OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN4) /* PC4 */ +#define GPIO_TIM2_CH4IN_3 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN4) /* PC4 */ /* TIM3 (AF2) */ #define GPIO_TIM3_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6) /* PA6 */ +#define GPIO_TIM3_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6) /* PA6 */ #define GPIO_TIM3_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN4) /* PB4 */ +#define GPIO_TIM3_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN4) /* PB4 */ #define GPIO_TIM3_CH1OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) /* PC6 */ +#define GPIO_TIM3_CH1IN_3 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6) /* PC6 */ #define GPIO_TIM3_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7) /* PA7 */ +#define GPIO_TIM3_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7) /* PA7 */ #define GPIO_TIM3_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) /* PB5 */ +#define GPIO_TIM3_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN5) /* PB5 */ #define GPIO_TIM3_CH2OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) /* PC7 */ +#define GPIO_TIM3_CH2IN_3 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7) /* PC7 */ #define GPIO_TIM3_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0) /* PB0 */ +#define GPIO_TIM3_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN0) /* PB0 */ #define GPIO_TIM3_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) /* PC8 */ +#define GPIO_TIM3_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8) /* PC8 */ #define GPIO_TIM3_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1) /* PB1 */ +#define GPIO_TIM3_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN1) /* PB1 */ #define GPIO_TIM3_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) /* PC9 */ +#define GPIO_TIM3_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9) /* PC9 */ /* TIM4 (AF2) */ #define GPIO_TIM4_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6) /* PB6 */ +#define GPIO_TIM4_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN6) /* PB6 */ #define GPIO_TIM4_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7) /* PB7 */ +#define GPIO_TIM4_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN7) /* PB7 */ #define GPIO_TIM4_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) /* PB8 */ +#define GPIO_TIM4_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8) /* PB8 */ #define GPIO_TIM4_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) /* PB9 */ +#define GPIO_TIM4_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9) /* PB9 */ #define GPIO_TIM4_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN2) /* PC2 */ +#define GPIO_TIM4_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN2) /* PC2 */ /* TIM5 (AF2) */ #define GPIO_TIM5_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) /* PA0 */ +#define GPIO_TIM5_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) /* PA0 */ #define GPIO_TIM5_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN10) /* PH10 */ +#define GPIO_TIM5_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10) /* PH10 */ #define GPIO_TIM5_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) /* PA1 */ +#define GPIO_TIM5_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1) /* PA1 */ #define GPIO_TIM5_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN11) /* PH11 */ +#define GPIO_TIM5_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN11) /* PH11 */ #define GPIO_TIM5_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) /* PA2 */ +#define GPIO_TIM5_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) /* PA2 */ #define GPIO_TIM5_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN12) /* PH12 */ +#define GPIO_TIM5_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN12) /* PH12 */ #define GPIO_TIM5_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) /* PA3 */ +#define GPIO_TIM5_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) /* PA3 */ #define GPIO_TIM5_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN0) /* PI0 */ +#define GPIO_TIM5_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN0) /* PI0 */ /* TIM8 (AF3) */ #define GPIO_TIM8_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) /* PC6 */ +#define GPIO_TIM8_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6) /* PC6 */ #define GPIO_TIM8_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN5) /* PI5 */ +#define GPIO_TIM8_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN5) /* PI5 */ #define GPIO_TIM8_CH1OUT_3 (GPIO_ALT|GPIO_AF3|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6) /* PH6 */ +#define GPIO_TIM8_CH1IN_3 (GPIO_ALT|GPIO_AF3|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN6) /* PH6 */ #define GPIO_TIM8_CH1NOUT_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN5) /* PA5 */ #define GPIO_TIM8_CH1NOUT_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN7) /* PA7 */ @@ -466,8 +513,11 @@ #define GPIO_TIM8_CH1NOUT_4 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN13) /* PH13 */ #define GPIO_TIM8_CH2OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) /* PC7 */ +#define GPIO_TIM8_CH2IN_1 (GPIO_ALT|GPIO_AF3|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7) /* PC7 */ #define GPIO_TIM8_CH2OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN6) /* PI6 */ +#define GPIO_TIM8_CH2IN_2 (GPIO_ALT|GPIO_AF3|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN6) /* PI6 */ #define GPIO_TIM8_CH2OUT_3 (GPIO_ALT|GPIO_AF3|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN8) /* PH8 */ +#define GPIO_TIM8_CH2IN_3 (GPIO_ALT|GPIO_AF3|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN8) /* PH8 */ #define GPIO_TIM8_CH2NOUT_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN0) /* PB0 */ #define GPIO_TIM8_CH2NOUT_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN14) /* PB14 */ @@ -475,8 +525,11 @@ #define GPIO_TIM8_CH2NOUT_4 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN14) /* PH14 */ #define GPIO_TIM8_CH3OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) /* PC8 */ +#define GPIO_TIM8_CH3IN_1 (GPIO_ALT|GPIO_AF3|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8) /* PC8 */ #define GPIO_TIM8_CH3OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN10) /* PH10 */ +#define GPIO_TIM8_CH3IN_2 (GPIO_ALT|GPIO_AF3|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10) /* PH10 */ #define GPIO_TIM8_CH3OUT_3 (GPIO_ALT|GPIO_AF3|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN7) /* PI7 */ +#define GPIO_TIM8_CH3IN_3 (GPIO_ALT|GPIO_AF3|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN7) /* PI7 */ #define GPIO_TIM8_CH3NOUT_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN1) /* PB1 */ #define GPIO_TIM8_CH3NOUT_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN15) /* PB15 */ @@ -484,41 +537,56 @@ #define GPIO_TIM8_CH3NOUT_4 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN15) /* PH15 */ #define GPIO_TIM8_CH4OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) /* PC9 */ +#define GPIO_TIM8_CH4IN_1 (GPIO_ALT|GPIO_AF3|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9) /* PC9 */ #define GPIO_TIM8_CH4OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN2) /* PI2 */ +#define GPIO_TIM8_CH4IN_2 (GPIO_ALT|GPIO_AF3|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN2) /* PI2 */ #define GPIO_TIM8_CH4NOUT_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN2) /* PB2 */ /* TIM12 (AF2) */ #define GPIO_TIM12_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN14) /* PB14 */ +#define GPIO_TIM12_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN14) /* PB14 */ #define GPIO_TIM12_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6) /* PH6 */ +#define GPIO_TIM12_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN6) /* PH6 */ #define GPIO_TIM12_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN15) /* PB15 */ +#define GPIO_TIM12_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN15) /* PB15 */ #define GPIO_TIM12_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9) /* PH9 */ +#define GPIO_TIM12_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN9) /* PH9 */ /* TIM15 (AF2/AF4, per pin) */ #define GPIO_TIM15_CH1OUT_1 (GPIO_ALT|GPIO_AF4|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) /* PA2 */ +#define GPIO_TIM15_CH1IN_1 (GPIO_ALT|GPIO_AF4|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) /* PA2 */ #define GPIO_TIM15_CH1OUT_2 (GPIO_ALT|GPIO_AF4|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN5) /* PE5 */ +#define GPIO_TIM15_CH1IN_2 (GPIO_ALT|GPIO_AF4|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN5) /* PE5 */ #define GPIO_TIM15_CH1OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN12) /* PC12 */ +#define GPIO_TIM15_CH1IN_3 (GPIO_ALT|GPIO_AF2|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN12) /* PC12 */ #define GPIO_TIM15_CH1NOUT_1 (GPIO_ALT|GPIO_AF4|GPIO_PORTA|GPIO_PIN1) /* PA1 */ #define GPIO_TIM15_CH1NOUT_2 (GPIO_ALT|GPIO_AF4|GPIO_PORTE|GPIO_PIN4) /* PE4 */ #define GPIO_TIM15_CH2OUT_1 (GPIO_ALT|GPIO_AF4|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) /* PA3 */ +#define GPIO_TIM15_CH2IN_1 (GPIO_ALT|GPIO_AF4|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) /* PA3 */ #define GPIO_TIM15_CH2OUT_2 (GPIO_ALT|GPIO_AF4|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN6) /* PE6 */ +#define GPIO_TIM15_CH2IN_2 (GPIO_ALT|GPIO_AF4|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN6) /* PE6 */ /* TIM16 (AF1) */ #define GPIO_TIM16_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) /* PB8 */ +#define GPIO_TIM16_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8) /* PB8 */ #define GPIO_TIM16_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN6) /* PF6 */ +#define GPIO_TIM16_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN6) /* PF6 */ #define GPIO_TIM16_CH1NOUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN6) /* PB6 */ #define GPIO_TIM16_CH1NOUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTF|GPIO_PIN8) /* PF8 */ /* TIM17 (AF1) */ #define GPIO_TIM17_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) /* PB9 */ +#define GPIO_TIM17_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9) /* PB9 */ #define GPIO_TIM17_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN7) /* PF7 */ +#define GPIO_TIM17_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN7) /* PF7 */ #define GPIO_TIM17_CH1NOUT_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN7) /* PB7 */ #define GPIO_TIM17_CH1NOUT_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTF|GPIO_PIN9) /* PF9 */ diff --git a/arch/arm/src/stm32h5/stm32_capture.c b/arch/arm/src/stm32h5/stm32_capture.c new file mode 100644 index 00000000000..2c86a07ccae --- /dev/null +++ b/arch/arm/src/stm32h5/stm32_capture.c @@ -0,0 +1,1331 @@ +/**************************************************************************** + * arch/arm/src/stm32h5/stm32_capture.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/arch.h> +#include <nuttx/irq.h> + +#include <sys/types.h> +#include <stdint.h> +#include <stdbool.h> +#include <assert.h> +#include <errno.h> +#include <nuttx/debug.h> + +#include <arch/board/board.h> + +#include "chip.h" +#include "arm_internal.h" +#include "stm32.h" +#include "stm32_gpio.h" +#include "stm32_capture.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Timer Channel Configuration **********************************************/ + +/* This module only compiles if there are enabled timers that are not + * intended for some other purpose. + */ + +#if defined(CONFIG_STM32_TIMX_CAP) + +/* Check if any channel is enabled. + * This is done to simplify the logic below. + */ + +#if defined(GPIO_TIM1_CH1IN) || defined(GPIO_TIM2_CH1IN) || defined(GPIO_TIM3_CH1IN) || \ + defined(GPIO_TIM4_CH1IN) || defined(GPIO_TIM5_CH1IN) || defined(GPIO_TIM8_CH1IN) || \ + defined(GPIO_TIM12_CH1IN) || defined(GPIO_TIM15_CH1IN) +# define HAVE_CH1IN 1 +#endif + +#if defined(GPIO_TIM1_CH2IN) || defined(GPIO_TIM2_CH2IN) || defined(GPIO_TIM3_CH2IN) || \ + defined(GPIO_TIM4_CH2IN) || defined(GPIO_TIM5_CH2IN) || defined(GPIO_TIM8_CH2IN) || \ + defined(GPIO_TIM12_CH2IN) || defined(GPIO_TIM15_CH2IN) +# define HAVE_CH2IN 1 +#endif + +#if defined(GPIO_TIM1_CH3IN) || defined(GPIO_TIM2_CH3IN) || defined(GPIO_TIM3_CH3IN) || \ + defined(GPIO_TIM4_CH3IN) || defined(GPIO_TIM5_CH3IN) || defined(GPIO_TIM8_CH3IN) +# define HAVE_CH3IN 1 +#endif + +#if defined(GPIO_TIM1_CH4IN) || defined(GPIO_TIM2_CH4IN) || defined(GPIO_TIM3_CH4IN) || \ + defined(GPIO_TIM4_CH4IN) || defined(GPIO_TIM5_CH4IN) || defined(GPIO_TIM8_CH4IN) +# define HAVE_CH4IN 1 +#endif + +#if defined(GPIO_TIM1_CH5IN) || defined(GPIO_TIM8_CH5IN) +# define HAVE_CH5IN 1 +#endif + +#if defined(GPIO_TIM1_CH6IN) || defined(GPIO_TIM8_CH6IN) +# define HAVE_CH6IN 1 +#endif + +/* Check if we have any advanced timers */ + +#if defined(CONFIG_STM32_TIM1_CAP) || defined(CONFIG_STM32_TIM8_CAP) +# define USE_ADVANCED_TIM 1 +#endif + +/* Check if we have any general purpose timers */ + +#if defined(CONFIG_STM32_TIM2_CAP) || defined(CONFIG_STM32_TIM3_CAP) || \ + defined(CONFIG_STM32_TIM4_CAP) || defined(CONFIG_STM32_TIM5_CAP) || \ + defined(CONFIG_STM32_TIM12_CAP) || defined(CONFIG_STM32_TIM15_CAP) +# define USE_GENERAL_TIM 1 +#endif + +/* Check for external clock signal */ + +#if defined(GPIO_TIM1_ETR_IN) || defined(GPIO_TIM2_ETR_IN) || defined(GPIO_TIM3_ETR_IN) || \ + defined(GPIO_TIM4_ETR_IN) || defined(GPIO_TIM5_ETR_IN) || defined(GPIO_TIM8_ETR_IN) +# define USE_EXT_CLOCK 1 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* TIM Device Structure */ + +struct stm32_cap_priv_s +{ + const struct stm32_cap_ops_s *ops; + const uint32_t base; /* TIMn base address */ +#ifdef USE_EXT_CLOCK + const uint32_t gpio_clk; /* TIMn base address */ +#endif + const int irq; /* irq vector */ +#ifdef USE_ADVANCED_TIM + const int irq_of; /* irq timer overflow is deferent in advanced timer */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Get a 16-bit register value by offset */ + +static inline +uint16_t stm32_getreg16(const struct stm32_cap_priv_s *priv, + uint8_t offset) +{ + return getreg16(priv->base + offset); +} + +/* Put a 16-bit register value by offset */ + +static inline void stm32_putreg16(const struct stm32_cap_priv_s *priv, + uint8_t offset, uint16_t value) +{ + putreg16(value, priv->base + offset); +} + +/* Modify a 16-bit register value by offset */ + +static inline void stm32_modifyreg16(const struct stm32_cap_priv_s *priv, + uint8_t offset, uint16_t clearbits, + uint16_t setbits) +{ + modifyreg16(priv->base + offset, clearbits, setbits); +} + +/* Get a 32-bit register value by offset. This applies only for the STM32 F4 + * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2 and TIM5. + */ + +static inline +uint32_t stm32_getreg32(const struct stm32_cap_priv_s *priv, + uint8_t offset) +{ + return getreg32(priv->base + offset); +} + +/* Put a 32-bit register value by offset. This applies only for the STM32 F4 + * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2 and TIM5. + */ + +static inline void stm32_putreg32(const struct stm32_cap_priv_s *priv, + uint8_t offset, uint32_t value) +{ + putreg32(value, priv->base + offset); +} + +/**************************************************************************** + * gpio Functions + ****************************************************************************/ + +static inline +uint32_t stm32_cap_gpio(const struct stm32_cap_priv_s *priv, + int channel) +{ + if (channel < 0) /* Special case: return first available channel */ + { + uint32_t gpio; + + /* Try counter channel first */ + + gpio = stm32_cap_gpio(priv, STM32_CAP_CHANNEL_COUNTER); + if (gpio) + { + return gpio; + } + + /* Then try channels 1..4 */ + + for (int ch = 1; ch <= 4; ch++) + { + gpio = stm32_cap_gpio(priv, ch); + if (gpio) + { + return gpio; + } + } + + return 0; /* None found */ + } + + switch (priv->base) + { +#ifdef CONFIG_STM32_TIM1_CAP + case STM32_TIM1_BASE: + switch (channel) + { +#ifdef GPIO_TIM1_EXT_CLK_IN + case STM32_CAP_CHANNEL_COUNTER: + return GPIO_TIM1_EXT_CLK_IN; +#endif +#ifdef GPIO_TIM1_CH1IN + case 1: + return GPIO_TIM1_CH1IN; +#endif +#ifdef GPIO_TIM1_CH2IN + case 2: + return GPIO_TIM1_CH2IN; +#endif +#ifdef GPIO_TIM1_CH3IN + case 3: + return GPIO_TIM1_CH3IN; +#endif +#ifdef GPIO_TIM1_CH4IN + case 4: + return GPIO_TIM1_CH4IN; +#endif + } + break; +#endif + +#ifdef CONFIG_STM32_TIM2_CAP + case STM32_TIM2_BASE: + switch (channel) + { +#ifdef GPIO_TIM2_EXT_CLK_IN + case STM32_CAP_CHANNEL_COUNTER: + return GPIO_TIM2_EXT_CLK_IN; +#endif +#ifdef GPIO_TIM2_CH1IN + case 1: + return GPIO_TIM2_CH1IN; +#endif +#ifdef GPIO_TIM2_CH2IN + case 2: + return GPIO_TIM2_CH2IN; +#endif +#ifdef GPIO_TIM2_CH3IN + case 3: + return GPIO_TIM2_CH3IN; +#endif +#ifdef GPIO_TIM2_CH4IN + case 4: + return GPIO_TIM2_CH4IN; +#endif + } + break; +#endif + +#ifdef CONFIG_STM32_TIM3_CAP + case STM32_TIM3_BASE: + switch (channel) + { +#ifdef GPIO_TIM3_EXT_CLK_IN + case STM32_CAP_CHANNEL_COUNTER: + return GPIO_TIM3_EXT_CLK_IN; +#endif +#ifdef GPIO_TIM3_CH1IN + case 1: + return GPIO_TIM3_CH1IN; +#endif +#ifdef GPIO_TIM3_CH2IN + case 2: + return GPIO_TIM3_CH2IN; +#endif +#ifdef GPIO_TIM3_CH3IN + case 3: + return GPIO_TIM3_CH3IN; +#endif +#ifdef GPIO_TIM3_CH4IN + case 4: + return GPIO_TIM3_CH4IN; +#endif + } + break; +#endif + +#ifdef CONFIG_STM32_TIM4_CAP + case STM32_TIM4_BASE: + switch (channel) + { +#ifdef GPIO_TIM4_EXT_CLK_IN + case STM32_CAP_CHANNEL_COUNTER: + return GPIO_TIM4_EXT_CLK_IN; +#endif +#ifdef GPIO_TIM4_CH1IN + case 1: + return GPIO_TIM4_CH1IN; +#endif +#ifdef GPIO_TIM4_CH2IN + case 2: + return GPIO_TIM4_CH2IN; +#endif +#ifdef GPIO_TIM4_CH3IN + case 3: + return GPIO_TIM4_CH3IN; +#endif +#ifdef GPIO_TIM4_CH4IN + case 4: + return GPIO_TIM4_CH4IN; +#endif + } + break; +#endif + +#ifdef CONFIG_STM32_TIM5_CAP + case STM32_TIM5_BASE: + switch (channel) + { +#ifdef GPIO_TIM5_EXT_CLK_IN + case STM32_CAP_CHANNEL_COUNTER: + return GPIO_TIM5_EXT_CLK_IN; +#endif +#ifdef GPIO_TIM5_CH1IN + case 1: + return GPIO_TIM5_CH1IN; +#endif +#ifdef GPIO_TIM5_CH2IN + case 2: + return GPIO_TIM5_CH2IN; +#endif +#ifdef GPIO_TIM5_CH3IN + case 3: + return GPIO_TIM5_CH3IN; +#endif +#ifdef GPIO_TIM5_CH4IN + case 4: + return GPIO_TIM5_CH4IN; +#endif + } + break; +#endif + + /* TIM6 and TIM7 cannot be used in capture */ + +#ifdef CONFIG_STM32_TIM8_CAP + case STM32_TIM8_BASE: + switch (channel) + { +#ifdef GPIO_TIM8_EXT_CLK_IN + case STM32_CAP_CHANNEL_COUNTER: + return GPIO_TIM8_EXT_CLK_IN; +#endif +#ifdef GPIO_TIM8_CH1IN + case 1: + return GPIO_TIM8_CH1IN; +#endif +#ifdef GPIO_TIM8_CH2IN + case 2: + return GPIO_TIM8_CH2IN; +#endif +#ifdef GPIO_TIM8_CH3IN + case 3: + return GPIO_TIM8_CH3IN; +#endif +#ifdef GPIO_TIM8_CH4IN + case 4: + return GPIO_TIM8_CH4IN; +#endif + } + break; +#endif + +#ifdef CONFIG_STM32_TIM12_CAP + case STM32_TIM12_BASE: + switch (channel) + { +#ifdef GPIO_TIM12_EXT_CLK_IN + case STM32_CAP_CHANNEL_COUNTER: + return GPIO_TIM12_EXT_CLK_IN; +#endif +#ifdef GPIO_TIM12_CH1IN + case 1: + return GPIO_TIM12_CH1IN; +#endif +#ifdef GPIO_TIM12_CH2IN + case 2: + return GPIO_TIM12_CH2IN; +#endif + } + break; +#endif + +#ifdef CONFIG_STM32_TIM15_CAP + case STM32_TIM15_BASE: + switch (channel) + { +#ifdef GPIO_TIM15_EXT_CLK_IN + case STM32_CAP_CHANNEL_COUNTER: + return GPIO_TIM15_EXT_CLK_IN; +#endif +#ifdef GPIO_TIM15_CH1IN + case 1: + return GPIO_TIM15_CH1IN; +#endif +#ifdef GPIO_TIM15_CH2IN + case 2: + return GPIO_TIM15_CH2IN; +#endif + } + break; +#endif + } + + return 0; +} + +static inline int stm32_cap_set_rcc(const struct stm32_cap_priv_s *priv, + bool on) +{ + uint32_t offset = 0; + uint32_t mask = 0; + + switch (priv->base) + { + /* APB2 Timers */ + +#ifdef CONFIG_STM32_TIM1_CAP + case STM32_TIM1_BASE: + offset = STM32_RCC_APB2ENR; + mask = RCC_APB2ENR_TIM1EN; + break; +#endif +#ifdef CONFIG_STM32_TIM8_CAP + case STM32_TIM8_BASE: + offset = STM32_RCC_APB2ENR; + mask = RCC_APB2ENR_TIM8EN; + break; +#endif +#ifdef CONFIG_STM32_TIM15_CAP + case STM32_TIM15_BASE: + offset = STM32_RCC_APB2ENR; + mask = RCC_APB2ENR_TIM15EN; + break; +#endif + + /* APB1L Timers */ + +#ifdef CONFIG_STM32_TIM2_CAP + case STM32_TIM2_BASE: + offset = STM32_RCC_APB1LENR; + mask = RCC_APB1LENR_TIM2EN; + break; +#endif +#ifdef CONFIG_STM32_TIM3_CAP + case STM32_TIM3_BASE: + offset = STM32_RCC_APB1LENR; + mask = RCC_APB1LENR_TIM3EN; + break; +#endif +#ifdef CONFIG_STM32_TIM4_CAP + case STM32_TIM4_BASE: + offset = STM32_RCC_APB1LENR; + mask = RCC_APB1LENR_TIM4EN; + break; +#endif +#ifdef CONFIG_STM32_TIM5_CAP + case STM32_TIM5_BASE: + offset = STM32_RCC_APB1LENR; + mask = RCC_APB1LENR_TIM5EN; + break; +#endif + /* TIM6 and TIM7 cannot be used in capture */ +#ifdef CONFIG_STM32_TIM12_CAP + case STM32_TIM12_BASE: + offset = STM32_RCC_APB1LENR; + mask = RCC_APB1LENR_TIM12EN; + break; +#endif + + /* APB4 Timers */ + + default: + return -EINVAL; + } + + if (on) + { + modifyreg32(offset, 0, mask); + } + else + { + modifyreg32(offset, mask, 0); + } + + return OK; +} + +/**************************************************************************** + * Basic Functions + ****************************************************************************/ + +static int stm32_cap_setclock(struct stm32_cap_dev_s *dev, + uint32_t freq, uint32_t max) +{ + const struct stm32_cap_priv_s *priv = (const struct stm32_cap_priv_s *)dev; + uint32_t freqin; + int prescaler; + + /* Disable Timer? */ + + if (freq == 0) + { + /* Disable Timer */ + + stm32_modifyreg16(priv, STM32_BTIM_CR1_OFFSET, ATIM_CR1_CEN, 0); + return 0; + } + + /* Get the input clock frequency for this timer. These vary with + * different timer clock sources, MCU-specific timer configuration, and + * board-specific clock configuration. The correct input clock frequency + * must be defined in the board.h header file. + */ + + switch (priv->base) + { +#ifdef CONFIG_STM32_TIM1 + case STM32_TIM1_BASE: + freqin = STM32_TIM1_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM2 + case STM32_TIM2_BASE: + freqin = STM32_TIM2_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM3 + case STM32_TIM3_BASE: + freqin = STM32_TIM3_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM4 + case STM32_TIM4_BASE: + freqin = STM32_TIM4_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM5 + case STM32_TIM5_BASE: + freqin = STM32_TIM5_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM8 + case STM32_TIM8_BASE: + freqin = STM32_TIM8_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM12 + case STM32_TIM12_BASE: + freqin = STM32_TIM12_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM15 + case STM32_TIM15_BASE: + freqin = STM32_TIM15_CLKIN; + break; +#endif + + default: + return -EINVAL; + } + + /* Select a pre-scaler value for this timer using the input clock + * frequency. + */ + + prescaler = freqin / freq; + + /* We need to decrement value for '1', but only, if we are allowed to + * not to cause underflow. Check for overflow. + */ + + if (prescaler > 0) + { + prescaler--; + } + + if (prescaler > 0xffff) + { + prescaler = 0xffff; + } + + /* Set Maximum */ + + stm32_putreg32(priv, STM32_BTIM_ARR_OFFSET, max); + + /* Set prescaler */ + + stm32_putreg16(priv, STM32_BTIM_PSC_OFFSET, prescaler); + + /* Reset counter timer */ + + stm32_modifyreg16(priv, STM32_BTIM_EGR_OFFSET, 0, BTIM_EGR_UG); + + /* Enable timer */ + + stm32_modifyreg16(priv, STM32_BTIM_CR1_OFFSET, 0, BTIM_CR1_CEN); + +#ifdef USE_ADVANCED_TIM + /* Advanced registers require Main Output Enable */ + + if (priv->base == STM32_TIM1_BASE || priv->base == STM32_TIM8_BASE) + { + stm32_modifyreg16(priv, STM32_ATIM_BDTR_OFFSET, 0, ATIM_BDTR_MOE); + } +#endif + + return prescaler; +} + +/**************************************************************************** + * Name: stm32_cap_setsmc + * + * Description: + * set slave mode control register + * + * Input Parameters: + * dev - A pointer of the stm32 capture device structure. + * cfg - Slave mode control register configure of timer. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_cap_setsmc(struct stm32_cap_dev_s *dev, + stm32_cap_smc_cfg_t cfg) +{ + const struct stm32_cap_priv_s *priv = (const struct stm32_cap_priv_s *)dev; + uint16_t regval = 0; + uint16_t mask = 0; + + switch (cfg & STM32_CAP_SMS_MASK) + { + case STM32_CAP_SMS_INT: + regval |= GTIM_SMCR_DISAB; + break; + + case STM32_CAP_SMS_ENC1: + regval |= GTIM_SMCR_ENCMD1; + break; + + case STM32_CAP_SMS_ENC2: + regval |= GTIM_SMCR_ENCMD2; + break; + + case STM32_CAP_SMS_ENC3: + regval |= GTIM_SMCR_ENCMD3; + break; + + case STM32_CAP_SMS_RST: + regval |= GTIM_SMCR_RESET; + break; + + case STM32_CAP_SMS_GAT: + regval |= GTIM_SMCR_GATED; + break; + + case STM32_CAP_SMS_TRG: + regval |= GTIM_SMCR_TRIGGER; + break; + + case STM32_CAP_SMS_EXT: + regval |= GTIM_SMCR_EXTCLK1; + break; + + default: + break; + } + + switch (cfg & STM32_CAP_TS_MASK) + { + case STM32_CAP_TS_ITR0: + regval |= GTIM_SMCR_ITR0; + break; + + case STM32_CAP_TS_ITR1: + regval |= GTIM_SMCR_ITR1; + break; + + case STM32_CAP_TS_ITR2: + regval |= GTIM_SMCR_ITR2; + break; + + case STM32_CAP_TS_ITR3: + regval |= GTIM_SMCR_ITR3; + break; + + case STM32_CAP_TS_TI1FED: + regval |= GTIM_SMCR_TI1FED; + break; + + case STM32_CAP_TS_TI1FP1: + regval |= GTIM_SMCR_TI1FP1; + break; + + case STM32_CAP_TS_TI2FP2: + regval |= GTIM_SMCR_TI2FP2; + break; + + case STM32_CAP_TS_ETRF: + regval |= GTIM_SMCR_ETRF; + break; + + default: + break; + } + + if (cfg & STM32_CAP_MSM_MASK) + { + regval |= STM32_CAP_MSM_MASK; + } + + mask = (STM32_CAP_SMS_MASK | STM32_CAP_TS_MASK | STM32_CAP_MSM_MASK); + stm32_modifyreg16(priv, STM32_GTIM_SMCR_OFFSET, mask, regval); + + return OK; +} + +static int stm32_cap_setisr(struct stm32_cap_dev_s *dev, xcpt_t handler, + void *arg) +{ + const struct stm32_cap_priv_s *priv = (const struct stm32_cap_priv_s *)dev; + int irq; +#ifdef USE_ADVANCED_TIM + int irq_of; +#endif + + DEBUGASSERT(dev != NULL); + + irq = priv->irq; +#ifdef USE_ADVANCED_TIM + irq_of = priv->irq_of; +#endif + + /* Disable interrupt when callback is removed */ + + if (!handler) + { + up_disable_irq(irq); + irq_detach(irq); + +#ifdef USE_ADVANCED_TIM + if (priv->irq_of) + { + up_disable_irq(irq_of); + irq_detach(irq_of); + } +#endif + + return OK; + } + + /* Otherwise set callback and enable interrupt */ + + irq_attach(irq, handler, arg); + up_enable_irq(irq); + +#ifdef USE_ADVANCED_TIM + if (priv->irq_of) + { + irq_attach(priv->irq_of, handler, arg); + up_enable_irq(priv->irq_of); + } +#endif + + return OK; +} + +static void stm32_cap_enableint(struct stm32_cap_dev_s *dev, + stm32_cap_flags_t src, bool on) +{ + const struct stm32_cap_priv_s *priv = (const struct stm32_cap_priv_s *)dev; + uint16_t mask = 0; + + DEBUGASSERT(dev != NULL); + + if (src & STM32_CAP_FLAG_IRQ_COUNTER) + { + mask |= ATIM_DIER_UIE; + } + + if (src & STM32_CAP_FLAG_IRQ_CH_1) + { + mask |= ATIM_DIER_CC1IE; + } + + if (src & STM32_CAP_FLAG_IRQ_CH_2) + { + mask |= ATIM_DIER_CC2IE; + } + + if (src & STM32_CAP_FLAG_IRQ_CH_3) + { + mask |= ATIM_DIER_CC3IE; + } + + if (src & STM32_CAP_FLAG_IRQ_CH_4) + { + mask |= ATIM_DIER_CC4IE; + } + + /* Not IRQ on channel overflow */ + + if (on) + { + stm32_modifyreg16(priv, STM32_BTIM_DIER_OFFSET, 0, mask); + } + else + { + stm32_modifyreg16(priv, STM32_BTIM_DIER_OFFSET, mask, 0); + } +} + +static void stm32_cap_ackflags(struct stm32_cap_dev_s *dev, int flags) +{ + const struct stm32_cap_priv_s *priv = (const struct stm32_cap_priv_s *)dev; + uint16_t mask = 0; + + if (flags & STM32_CAP_FLAG_IRQ_COUNTER) + { + mask |= ATIM_SR_UIF; + } + + if (flags & STM32_CAP_FLAG_IRQ_CH_1) + { + mask |= ATIM_SR_CC1IF; + } + + if (flags & STM32_CAP_FLAG_IRQ_CH_2) + { + mask |= ATIM_SR_CC2IF; + } + + if (flags & STM32_CAP_FLAG_IRQ_CH_3) + { + mask |= ATIM_SR_CC3IF; + } + + if (flags & STM32_CAP_FLAG_IRQ_CH_4) + { + mask |= ATIM_SR_CC4IF; + } + + if (flags & STM32_CAP_FLAG_OF_CH_1) + { + mask |= ATIM_SR_CC1OF; + } + + if (flags & STM32_CAP_FLAG_OF_CH_2) + { + mask |= ATIM_SR_CC2OF; + } + + if (flags & STM32_CAP_FLAG_OF_CH_3) + { + mask |= ATIM_SR_CC3OF; + } + + if (flags & STM32_CAP_FLAG_OF_CH_4) + { + mask |= ATIM_SR_CC4OF; + } + + stm32_putreg16(priv, STM32_BTIM_SR_OFFSET, ~mask); +} + +static stm32_cap_flags_t stm32_cap_getflags(struct stm32_cap_dev_s *dev) +{ + const struct stm32_cap_priv_s *priv = (const struct stm32_cap_priv_s *)dev; + uint16_t regval = 0; + stm32_cap_flags_t flags = 0; + + regval = stm32_getreg16(priv, STM32_BTIM_SR_OFFSET); + + if (regval & ATIM_SR_UIF) + { + flags |= STM32_CAP_FLAG_IRQ_COUNTER; + } + + if (regval & ATIM_SR_CC1IF) + { + flags |= STM32_CAP_FLAG_IRQ_CH_1; + } + + if (regval & ATIM_SR_CC2IF) + { + flags |= STM32_CAP_FLAG_IRQ_CH_2; + } + + if (regval & ATIM_SR_CC3IF) + { + flags |= STM32_CAP_FLAG_IRQ_CH_3; + } + + if (regval & ATIM_SR_CC4IF) + { + flags |= STM32_CAP_FLAG_IRQ_CH_4; + } + + if (regval & ATIM_SR_CC1OF) + { + flags |= STM32_CAP_FLAG_OF_CH_1; + } + + if (regval & ATIM_SR_CC2OF) + { + flags |= STM32_CAP_FLAG_OF_CH_2; + } + + if (regval & ATIM_SR_CC3OF) + { + flags |= STM32_CAP_FLAG_OF_CH_3; + } + + if (regval & ATIM_SR_CC4OF) + { + flags |= STM32_CAP_FLAG_OF_CH_4; + } + + return flags; +} + +/**************************************************************************** + * General Functions + ****************************************************************************/ + +static int stm32_cap_setchannel(struct stm32_cap_dev_s *dev, + uint8_t channel, + stm32_cap_ch_cfg_t cfg) +{ + const struct stm32_cap_priv_s *priv = (const struct stm32_cap_priv_s *)dev; + uint32_t gpio = 0; + uint16_t mask; + uint16_t regval; + uint16_t ccer_en_bit; + + DEBUGASSERT(dev != NULL); + + if ((cfg & STM32_CAP_MAPPED_MASK) == 0) + { + return ERROR; /* MAPPED not selected */ + } + + /* Only a channel mapped to its own input needs a pin. A channel mapped + * to the input of its paired channel (as the second channel in PWM input + * mode) shares the pin of that channel. + */ + + if ((cfg & STM32_CAP_MAPPED_MASK) == STM32_CAP_MAPPED_TI1) + { + gpio = stm32_cap_gpio(priv, channel); + + if (gpio == 0 && + (cfg & STM32_CAP_EDGE_MASK) != STM32_CAP_EDGE_DISABLED) + { + return ERROR; + } + } + + /* Change to zero base index */ + + channel--; + + /* Set ccer : + * + * GTIM_CCER_CCxE Is written latter to allow writing CCxS bits. + * + */ + + switch (cfg & STM32_CAP_EDGE_MASK) + { + case STM32_CAP_EDGE_DISABLED: + regval = 0; + ccer_en_bit = 0; + break; + + case STM32_CAP_EDGE_RISING: + ccer_en_bit = GTIM_CCER_CC1E; + regval = 0; + break; + + case STM32_CAP_EDGE_FALLING: + ccer_en_bit = GTIM_CCER_CC1E; + regval = GTIM_CCER_CC1P; + break; + + case STM32_CAP_EDGE_BOTH: + ccer_en_bit = GTIM_CCER_CC1E; + regval = GTIM_CCER_CC1P | GTIM_CCER_CC1NP; + break; + + default: + return ERROR; + } + + /* Shift all CCER bits to corresponding channel */ + + mask = (GTIM_CCER_CC1E | GTIM_CCER_CC1P | GTIM_CCER_CC1NP); + mask <<= GTIM_CCER_CCXBASE(channel); + regval <<= GTIM_CCER_CCXBASE(channel); + ccer_en_bit <<= GTIM_CCER_CCXBASE(channel); + + stm32_modifyreg16(priv, STM32_GTIM_CCER_OFFSET, mask, regval); + + /* Set ccmr */ + + regval = cfg; + mask = (GTIM_CCMR1_IC1F_MASK | + GTIM_CCMR1_IC1PSC_MASK | + GTIM_CCMR1_CC1S_MASK); + regval &= mask; + + if (channel & 1) + { + regval <<= 8; + mask <<= 8; + } + + if (channel < 2) + { + stm32_modifyreg16(priv, STM32_GTIM_CCMR1_OFFSET, mask, regval); + } + else + { + stm32_modifyreg16(priv, STM32_GTIM_CCMR2_OFFSET, mask, regval); + } + + /* Set GPIO */ + + if (gpio != 0) + { + if ((cfg & STM32_CAP_EDGE_MASK) == STM32_CAP_EDGE_DISABLED) + { + stm32_unconfiggpio(gpio); + } + else + { + stm32_configgpio(gpio); + } + } + + /* Enable this channel timer */ + + stm32_modifyreg16(priv, STM32_GTIM_CCER_OFFSET, 0, ccer_en_bit); + return OK; +} + +static uint32_t stm32_cap_getcapture(struct stm32_cap_dev_s *dev, + uint8_t channel) +{ + const struct stm32_cap_priv_s *priv = (const struct stm32_cap_priv_s *)dev; + uint32_t offset; + + DEBUGASSERT(dev != NULL); + + switch (channel) + { + case STM32_CAP_CHANNEL_COUNTER: + offset = STM32_GTIM_CNT_OFFSET; + break; +#ifdef HAVE_CH1IN + case 1: + offset = STM32_GTIM_CCR1_OFFSET; + break; +#endif +#ifdef HAVE_CH2IN + case 2: + offset = STM32_GTIM_CCR2_OFFSET; + break; +#endif +#ifdef HAVE_CH3IN + case 3: + offset = STM32_GTIM_CCR3_OFFSET; + break; +#endif +#ifdef HAVE_CH4IN + case 4: + offset = STM32_GTIM_CCR4_OFFSET; + break; +#endif + default: + return ERROR; + } + + if (priv->base == STM32_TIM2_BASE || priv->base == STM32_TIM5_BASE) + { + return stm32_getreg32(priv, offset); + } + + return stm32_getreg16(priv, offset); +} + +/**************************************************************************** + * Advanced Functions + ****************************************************************************/ + +/* TODO: Advanced functions for the STM32_ATIM */ + +/**************************************************************************** + * Device Structures, Instantiation + ****************************************************************************/ + +struct stm32_cap_ops_s stm32_cap_ops = +{ + .setsmc = &stm32_cap_setsmc, + .setclock = &stm32_cap_setclock, + .setchannel = &stm32_cap_setchannel, + .getcapture = &stm32_cap_getcapture, + .setisr = &stm32_cap_setisr, + .enableint = &stm32_cap_enableint, + .ackflags = &stm32_cap_ackflags, + .getflags = &stm32_cap_getflags +}; + +#ifdef CONFIG_STM32_TIM1_CAP +const struct stm32_cap_priv_s stm32_tim1_priv = +{ + .ops = &stm32_cap_ops, + .base = STM32_TIM1_BASE, + .irq = STM32_IRQ_TIM1CC, +#ifdef USE_ADVANCED_TIM + .irq_of = STM32_IRQ_TIM1UP, +#endif +}; +#endif + +#ifdef CONFIG_STM32_TIM2_CAP +const struct stm32_cap_priv_s stm32_tim2_priv = +{ + .ops = &stm32_cap_ops, + .base = STM32_TIM2_BASE, + .irq = STM32_IRQ_TIM2, +#ifdef USE_ADVANCED_TIM + .irq_of = 0, +#endif +}; +#endif + +#ifdef CONFIG_STM32_TIM3_CAP +const struct stm32_cap_priv_s stm32_tim3_priv = +{ + .ops = &stm32_cap_ops, + .base = STM32_TIM3_BASE, + .irq = STM32_IRQ_TIM3, +#ifdef USE_ADVANCED_TIM + .irq_of = 0, +#endif +}; +#endif + +#ifdef CONFIG_STM32_TIM4_CAP +const struct stm32_cap_priv_s stm32_tim4_priv = +{ + .ops = &stm32_cap_ops, + .base = STM32_TIM4_BASE, + .irq = STM32_IRQ_TIM4, +#ifdef USE_ADVANCED_TIM + .irq_of = 0, +#endif +}; +#endif + +#ifdef CONFIG_STM32_TIM5_CAP +const struct stm32_cap_priv_s stm32_tim5_priv = +{ + .ops = &stm32_cap_ops, + .base = STM32_TIM5_BASE, + .irq = STM32_IRQ_TIM5, +#ifdef USE_ADVANCED_TIM + .irq_of = 0, +#endif +}; +#endif + +/* TIM6 and TIM7 cannot be used in capture */ + +#ifdef CONFIG_STM32_TIM8_CAP +const struct stm32_cap_priv_s stm32_tim8_priv = +{ + .ops = &stm32_cap_ops, + .base = STM32_TIM8_BASE, + .irq = STM32_IRQ_TIM8CC, +#ifdef USE_ADVANCED_TIM + .irq_of = STM32_IRQ_TIM8UP, +#endif +}; +#endif + +#ifdef CONFIG_STM32_TIM12_CAP +const struct stm32_cap_priv_s stm32_tim12_priv = +{ + .ops = &stm32_cap_ops, + .base = STM32_TIM12_BASE, + .irq = STM32_IRQ_TIM12, +#ifdef USE_ADVANCED_TIM + .irq_of = 0, +#endif +}; +#endif + +#ifdef CONFIG_STM32_TIM15_CAP +static const struct stm32_cap_priv_s stm32_tim15_priv = +{ + .ops = &stm32_cap_ops, + .base = STM32_TIM15_BASE, + .irq = STM32_IRQ_TIM15, +#ifdef USE_ADVANCED_TIM + .irq_of = 0, +#endif +}; +#endif + +static inline const struct stm32_cap_priv_s * stm32_cap_get_priv(int timer) +{ + switch (timer) + { +#ifdef CONFIG_STM32_TIM1_CAP + case 1: + return &stm32_tim1_priv; +#endif +#ifdef CONFIG_STM32_TIM2_CAP + case 2: + return &stm32_tim2_priv; +#endif +#ifdef CONFIG_STM32_TIM3_CAP + case 3: + return &stm32_tim3_priv; +#endif +#ifdef CONFIG_STM32_TIM4_CAP + case 4: + return &stm32_tim4_priv; +#endif +#ifdef CONFIG_STM32_TIM5_CAP + case 5: + return &stm32_tim5_priv; +#endif + + /* TIM6 and TIM7 cannot be used in capture */ + +#ifdef CONFIG_STM32_TIM8_CAP + case 8: + return &stm32_tim8_priv; +#endif +#ifdef CONFIG_STM32_TIM12_CAP + case 12: + return &stm32_tim12_priv; +#endif +#ifdef CONFIG_STM32_TIM15_CAP + case 15: + return &stm32_tim15_priv; +#endif + } + + return NULL; +} + +/**************************************************************************** + * Public Function - Initialization + ****************************************************************************/ + +struct stm32_cap_dev_s *stm32_cap_init(int timer) +{ + const struct stm32_cap_priv_s *priv = stm32_cap_get_priv(timer); + uint32_t gpio; + + if (priv) + { + stm32_cap_set_rcc(priv, true); + + gpio = stm32_cap_gpio(priv, -1); + if (gpio) + { + stm32_configgpio(gpio); + } + + /* Disable timer while is not configured */ + + stm32_modifyreg16(priv, STM32_BTIM_CR1_OFFSET, ATIM_CR1_CEN, 0); + } + + return (struct stm32_cap_dev_s *)priv; +} + +int stm32_cap_deinit(struct stm32_cap_dev_s * dev) +{ + const struct stm32_cap_priv_s *priv = (struct stm32_cap_priv_s *)dev; + uint32_t gpio; + + DEBUGASSERT(dev != NULL); + + /* Disable timer while is not configured */ + + stm32_modifyreg16(priv, STM32_BTIM_CR1_OFFSET, ATIM_CR1_CEN, 0); + + gpio = stm32_cap_gpio(priv, -1); + if (gpio) + { + stm32_unconfiggpio(gpio); + } + + stm32_cap_set_rcc(priv, false); + return OK; +} + +#endif /* CONFIG_STM32_TIMX_CAP */ diff --git a/arch/arm/src/stm32h5/stm32_capture.h b/arch/arm/src/stm32h5/stm32_capture.h new file mode 100644 index 00000000000..750a8091c8c --- /dev/null +++ b/arch/arm/src/stm32h5/stm32_capture.h @@ -0,0 +1,240 @@ +/**************************************************************************** + * arch/arm/src/stm32h5/stm32_capture.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32H5_STM32_CAPTURE_H +#define __ARCH_ARM_SRC_STM32H5_STM32_CAPTURE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include "chip.h" +#include <arch/board/board.h> +#include "hardware/stm32_tim.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Helpers ******************************************************************/ + +#define STM32_CAP_SETSMC(d,cfg) ((d)->ops->setsmc(d,cfg)) +#define STM32_CAP_SETCLOCK(d,clk,max) ((d)->ops->setclock(d,clk,max)) +#define STM32_CAP_SETCHANNEL(d,ch,cfg) ((d)->ops->setchannel(d,ch,cfg)) +#define STM32_CAP_GETCAPTURE(d,ch) ((d)->ops->getcapture(d,ch)) +#define STM32_CAP_SETISR(d,hnd,arg) ((d)->ops->setisr(d,hnd,arg)) +#define STM32_CAP_ENABLEINT(d,s,on) ((d)->ops->enableint(d,s,on)) +#define STM32_CAP_ACKFLAGS(d,f) ((d)->ops->ackflags(d,f)) +#define STM32_CAP_GETFLAGS(d) ((d)->ops->getflags(d)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* Capture Device Structure */ + +struct stm32_cap_dev_s +{ + struct stm32_cap_ops_s *ops; +}; + +/* Capture input EDGE sources */ + +typedef enum +{ + /* Mapped */ + + STM32_CAP_MAPPED_MASK = (GTIM_CCMR1_CC1S_MASK), + STM32_CAP_MAPPED_TI1 = (GTIM_CCMR_CCS_CCIN1), + STM32_CAP_MAPPED_TI2 = (GTIM_CCMR_CCS_CCIN2), + +/* TODO STM32_CAP_MAPPED_TRC = (GTIM_CCMR_CCS_CCINTRC), */ + + /* Event prescaler */ + + STM32_CAP_INPSC_MASK = (GTIM_CCMR1_IC1PSC_MASK), + STM32_CAP_INPSC_NO = (0 << GTIM_CCMR1_IC1PSC_SHIFT), + STM32_CAP_INPSC_2EVENTS = (1 << GTIM_CCMR1_IC1PSC_SHIFT), + STM32_CAP_INPSC_4EVENTS = (2 << GTIM_CCMR1_IC1PSC_SHIFT), + STM32_CAP_INPSC_8EVENTS = (3 << GTIM_CCMR1_IC1PSC_SHIFT), + + /* Event prescaler */ + + STM32_CAP_FILTER_MASK = (GTIM_CCMR1_IC1F_MASK), + STM32_CAP_FILTER_NO = (0 << GTIM_CCMR1_IC1F_SHIFT), + + /* Internal clock with N time to confirm event */ + + STM32_CAP_FILTER_INT_N2 = (1 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_INT_N4 = (2 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_INT_N8 = (3 << GTIM_CCMR1_IC1F_SHIFT), + + /* DTS clock div by D with N time to confirm event */ + + STM32_CAP_FILTER_DTS_D2_N6 = (4 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_DTS_D2_N8 = (5 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_DTS_D4_N6 = (6 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_DTS_D4_N8 = (7 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_DTS_D8_N6 = (8 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_DTS_D8_N8 = (9 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_DTS_D16_N5 = (10 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_DTS_D16_N6 = (11 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_DTS_D16_N8 = (12 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_DTS_D32_N5 = (13 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_DTS_D32_N6 = (14 << GTIM_CCMR1_IC1F_SHIFT), + STM32_CAP_FILTER_DTS_D32_N8 = (15 << GTIM_CCMR1_IC1F_SHIFT), + + /* EDGE */ + + STM32_CAP_EDGE_MASK = (3 << 8), + STM32_CAP_EDGE_DISABLED = (0 << 8), + STM32_CAP_EDGE_RISING = (1 << 8), + STM32_CAP_EDGE_FALLING = (2 << 8), + STM32_CAP_EDGE_BOTH = (3 << 8), +} stm32_cap_ch_cfg_t; + +/* Slave mode control configure */ + +typedef enum +{ + /* Slave mode selection */ + + STM32_CAP_SMS_MASK = (7 << GTIM_SMCR_SMS_SHIFT), + STM32_CAP_SMS_INT = (0 << GTIM_SMCR_SMS_SHIFT), + STM32_CAP_SMS_ENC1 = (1 << GTIM_SMCR_SMS_SHIFT), + STM32_CAP_SMS_ENC2 = (2 << GTIM_SMCR_SMS_SHIFT), + STM32_CAP_SMS_ENC3 = (3 << GTIM_SMCR_SMS_SHIFT), + STM32_CAP_SMS_RST = (4 << GTIM_SMCR_SMS_SHIFT), + STM32_CAP_SMS_GAT = (5 << GTIM_SMCR_SMS_SHIFT), + STM32_CAP_SMS_TRG = (6 << GTIM_SMCR_SMS_SHIFT), + STM32_CAP_SMS_EXT = (7 << GTIM_SMCR_SMS_SHIFT), + + /* Trigger selection */ + + STM32_CAP_TS_MASK = (7 << GTIM_SMCR_TS_SHIFT), + STM32_CAP_TS_ITR0 = (0 << GTIM_SMCR_TS_SHIFT), + STM32_CAP_TS_ITR1 = (1 << GTIM_SMCR_TS_SHIFT), + STM32_CAP_TS_ITR2 = (2 << GTIM_SMCR_TS_SHIFT), + STM32_CAP_TS_ITR3 = (3 << GTIM_SMCR_TS_SHIFT), + STM32_CAP_TS_TI1FED = (4 << GTIM_SMCR_TS_SHIFT), + STM32_CAP_TS_TI1FP1 = (5 << GTIM_SMCR_TS_SHIFT), + STM32_CAP_TS_TI2FP2 = (6 << GTIM_SMCR_TS_SHIFT), + STM32_CAP_TS_ETRF = (7 << GTIM_SMCR_TS_SHIFT), + + /* Master/Slave mode setting */ + + STM32_CAP_MSM_MASK = (1 << 7) +} stm32_cap_smc_cfg_t; + +/* Capture flags */ + +typedef enum +{ + /* One of the following */ + + STM32_CAP_FLAG_IRQ_COUNTER = (GTIM_SR_UIF), + + STM32_CAP_FLAG_IRQ_CH_1 = (GTIM_SR_CC1IF), + STM32_CAP_FLAG_IRQ_CH_2 = (GTIM_SR_CC2IF), + STM32_CAP_FLAG_IRQ_CH_3 = (GTIM_SR_CC3IF), + STM32_CAP_FLAG_IRQ_CH_4 = (GTIM_SR_CC4IF), + + STM32_CAP_FLAG_OF_CH_1 = (GTIM_SR_CC1OF), + STM32_CAP_FLAG_OF_CH_2 = (GTIM_SR_CC2OF), + STM32_CAP_FLAG_OF_CH_3 = (GTIM_SR_CC3OF), + STM32_CAP_FLAG_OF_CH_4 = (GTIM_SR_CC4OF) +} stm32_cap_flags_t; + +#define STM32_CAP_FLAG_IRQ_CH(ch) (GTIM_SR_CC1IF<<((ch)-1)) +#define STM32_CAP_FLAG_OF_CH(ch) (GTIM_SR_CC1OF<<((ch)-1)) +#define STM32_CAP_CHANNEL_COUNTER 0 + +/* Capture Operations */ + +struct stm32_cap_ops_s +{ + int (*setsmc)(struct stm32_cap_dev_s *dev, stm32_cap_smc_cfg_t cfg); + int (*setclock)(struct stm32_cap_dev_s *dev, uint32_t freq, + uint32_t max); + int (*setchannel)(struct stm32_cap_dev_s *dev, uint8_t channel, + stm32_cap_ch_cfg_t cfg); + uint32_t (*getcapture)(struct stm32_cap_dev_s *dev, uint8_t channel); + int (*setisr)(struct stm32_cap_dev_s *dev, xcpt_t handler, void *arg); + void (*enableint)(struct stm32_cap_dev_s *dev, stm32_cap_flags_t src, + bool on); + void (*ackflags)(struct stm32_cap_dev_s *dev, int flags); + stm32_cap_flags_t (*getflags)(struct stm32_cap_dev_s *dev); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Power-up timer and get its structure */ + +struct stm32_cap_dev_s *stm32_cap_init(int timer); + +/* Power-down timer, mark it as unused */ + +int stm32_cap_deinit(struct stm32_cap_dev_s *dev); + +/**************************************************************************** + * Name: stm32_cap_initialize + * + * Description: + * Initialize one timer for use with the upper_level capture driver. + * + * Input Parameters: + * timer - A number identifying the timer use. The number of valid timer + * IDs varies with the STM32 MCU and MCU family but is somewhere in + * the range of {1,..,5, 8, 12, 15}. + * + * Returned Value: + * On success, a pointer to the STM32 lower half capture driver returned. + * NULL is returned on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_CAPTURE +struct cap_lowerhalf_s *stm32_cap_initialize(int timer); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32H5_STM32_CAPTURE_H */ diff --git a/arch/arm/src/stm32h5/stm32_capture_lowerhalf.c b/arch/arm/src/stm32h5/stm32_capture_lowerhalf.c new file mode 100644 index 00000000000..5b7e4a48619 --- /dev/null +++ b/arch/arm/src/stm32h5/stm32_capture_lowerhalf.c @@ -0,0 +1,529 @@ +/**************************************************************************** + * arch/arm/src/stm32h5/stm32_capture_lowerhalf.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> + +#include <stdint.h> +#include <string.h> +#include <errno.h> + +#include <nuttx/irq.h> +#include <nuttx/timers/capture.h> + +#include <arch/board/board.h> + +#include "stm32_capture.h" + +#if defined(CONFIG_CAPTURE) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* 32-Bit Timers ************************************************************/ + +#define STM32_TIM2_RES 32 +#define STM32_TIM5_RES 32 + +/* 16-Bit Timers ************************************************************/ + +/* Advanced-Control Timers */ +#define STM32_TIM1_RES 16 +#define STM32_TIM8_RES 16 + +/* General-Purpose Timers */ +#define STM32_TIM3_RES 16 +#define STM32_TIM4_RES 16 +#define STM32_TIM12_RES 16 +#define STM32_TIM15_RES 16 + +/* Basic Timers */ +#define STM32_TIM6_RES 16 +#define STM32_TIM7_RES 16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure provides the private representation of the "lower-half" + * driver state structure. This structure must be cast-compatible with the + * cap_lowerhalf_s structure. + */ + +struct stm32_lowerhalf_s +{ + const struct cap_ops_s *ops; /* Lower half operations */ + struct stm32_cap_dev_s *cap; /* stm32 capture driver */ + bool started; /* True: Timer has been started */ + const uint8_t resolution; /* Number of bits in the timer */ + uint8_t channel; /* pwm input channel */ + uint32_t clock; /* Timer clock frequency */ + uint8_t duty; /* Result pwm frequency */ + uint32_t freq; /* Result pwm frequency */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int stm32_cap_handler(int irq, void * context, void * arg); + +/* "Lower half" driver methods **********************************************/ + +static int stm32_start(struct cap_lowerhalf_s *lower); +static int stm32_stop(struct cap_lowerhalf_s *lower); +static int stm32_getduty(struct cap_lowerhalf_s *lower, uint8_t *duty); +static int stm32_getfreq(struct cap_lowerhalf_s *lower, uint32_t *freq); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* "Lower half" driver methods */ + +static const struct cap_ops_s g_cap_ops = +{ + .start = stm32_start, + .stop = stm32_stop, + .getduty = stm32_getduty, + .getfreq = stm32_getfreq, +}; + +#ifdef CONFIG_STM32_TIM1_CAP +static struct stm32_lowerhalf_s g_cap1_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM1_RES, + .channel = CONFIG_STM32_TIM1_CHANNEL, + .clock = CONFIG_STM32_TIM1_CLOCK, +}; +#endif + +#ifdef CONFIG_STM32_TIM2_CAP +static struct stm32_lowerhalf_s g_cap2_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM2_RES, + .channel = CONFIG_STM32_TIM2_CHANNEL, + .clock = CONFIG_STM32_TIM2_CLOCK, +}; +#endif + +#ifdef CONFIG_STM32_TIM3_CAP +static struct stm32_lowerhalf_s g_cap3_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM3_RES, + .channel = CONFIG_STM32_TIM3_CHANNEL, + .clock = CONFIG_STM32_TIM3_CLOCK, +}; +#endif + +#ifdef CONFIG_STM32_TIM4_CAP +static struct stm32_lowerhalf_s g_cap4_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM4_RES, + .channel = CONFIG_STM32_TIM4_CHANNEL, + .clock = CONFIG_STM32_TIM4_CLOCK, +}; +#endif + +#ifdef CONFIG_STM32_TIM5_CAP +static struct stm32_lowerhalf_s g_cap5_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM5_RES, + .channel = CONFIG_STM32_TIM5_CHANNEL, + .clock = CONFIG_STM32_TIM5_CLOCK, +}; +#endif + +#ifdef CONFIG_STM32_TIM8_CAP +static struct stm32_lowerhalf_s g_cap8_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM8_RES, + .channel = CONFIG_STM32_TIM8_CHANNEL, + .clock = CONFIG_STM32_TIM8_CLOCK, +}; +#endif + +#ifdef CONFIG_STM32_TIM12_CAP +static struct stm32_lowerhalf_s g_cap12_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM12_RES, + .channel = CONFIG_STM32_TIM12_CHANNEL, + .clock = CONFIG_STM32_TIM12_CLOCK, +}; +#endif + +#ifdef CONFIG_STM32_TIM15_CAP +static struct stm32_lowerhalf_s g_cap15_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM15_RES, + .channel = CONFIG_STM32_TIM15_CHANNEL, + .clock = CONFIG_STM32_TIM15_CLOCK, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_cap_handler + * + * Description: + * timer interrupt handler + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int stm32_cap_handler(int irq, void * context, void * arg) +{ + struct stm32_lowerhalf_s *lower = (struct stm32_lowerhalf_s *) arg; + uint8_t ch = 0x3 & lower->channel; + int period = 0; + int flags = 0; + + flags = (int)STM32_CAP_GETFLAGS(lower->cap) ; + + STM32_CAP_ACKFLAGS(lower->cap, flags); + + period = STM32_CAP_GETCAPTURE(lower->cap, ch); + + if (period != 0) + { + lower->duty = (100 * STM32_CAP_GETCAPTURE(lower->cap, 0x3 & (~ch))) / + period; + lower->freq = lower->clock / period; + } + else + { + lower->duty = 0; + lower->freq = 0; + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_start + * + * Description: + * Start the timer, resetting the time to the current timeout, + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_start(struct cap_lowerhalf_s *lower) +{ + struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower; + int flags = 0; + uint32_t maxtimeout = (1 << priv->resolution) - 1; + + if (priv->started) + { + /* Return EBUSY to indicate that the timer was already running */ + + return -EBUSY; + } + + switch (priv->channel) + { + case 1: + STM32_CAP_SETSMC(priv->cap, STM32_CAP_SMS_RST | + STM32_CAP_TS_TI1FP1 | + STM32_CAP_MSM_MASK); + + STM32_CAP_SETCLOCK(priv->cap, priv->clock, maxtimeout); + + STM32_CAP_SETCHANNEL(priv->cap, 1, + STM32_CAP_EDGE_RISING | + STM32_CAP_MAPPED_TI1); + STM32_CAP_SETCHANNEL(priv->cap, 2, + STM32_CAP_EDGE_FALLING | + STM32_CAP_MAPPED_TI2); + + flags = (int)STM32_CAP_GETFLAGS(priv->cap); + STM32_CAP_ACKFLAGS(priv->cap, flags); + + STM32_CAP_SETISR(priv->cap, stm32_cap_handler, priv); + STM32_CAP_ENABLEINT(priv->cap, STM32_CAP_FLAG_IRQ_CH_1, true); + + priv->started = true; + break; + + case 2: + STM32_CAP_SETSMC(priv->cap, STM32_CAP_SMS_RST | + STM32_CAP_TS_TI2FP2 | + STM32_CAP_MSM_MASK); + + STM32_CAP_SETCLOCK(priv->cap, priv->clock, maxtimeout); + + STM32_CAP_SETCHANNEL(priv->cap, 2, + STM32_CAP_EDGE_RISING | + STM32_CAP_MAPPED_TI1); + STM32_CAP_SETCHANNEL(priv->cap, 1, + STM32_CAP_EDGE_FALLING | + STM32_CAP_MAPPED_TI2); + + flags = (int)STM32_CAP_GETFLAGS(priv->cap); + STM32_CAP_ACKFLAGS(priv->cap, flags); + + STM32_CAP_SETISR(priv->cap, stm32_cap_handler, priv); + STM32_CAP_ENABLEINT(priv->cap, STM32_CAP_FLAG_IRQ_CH_2, true); + + priv->started = true; + break; + + default: + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_stop + * + * Description: + * Stop the capture + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_stop(struct cap_lowerhalf_s *lower) +{ + struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower; + + if (priv->started) + { + switch (priv->channel) + { + case 1: + STM32_CAP_ENABLEINT(priv->cap, STM32_CAP_FLAG_IRQ_CH_1, false); + STM32_CAP_SETCHANNEL(priv->cap, 1, + STM32_CAP_EDGE_DISABLED | + STM32_CAP_MAPPED_TI1); + STM32_CAP_SETCHANNEL(priv->cap, 2, + STM32_CAP_EDGE_DISABLED | + STM32_CAP_MAPPED_TI2); + break; + + case 2: + STM32_CAP_ENABLEINT(priv->cap, STM32_CAP_FLAG_IRQ_CH_2, false); + STM32_CAP_SETCHANNEL(priv->cap, 2, + STM32_CAP_EDGE_DISABLED | + STM32_CAP_MAPPED_TI1); + STM32_CAP_SETCHANNEL(priv->cap, 1, + STM32_CAP_EDGE_DISABLED | + STM32_CAP_MAPPED_TI2); + break; + + default: + return ERROR; + } + + STM32_CAP_SETISR(priv->cap, NULL, NULL); + STM32_CAP_SETCLOCK(priv->cap, 0, 0); + priv->started = false; + return OK; + } + + /* Return ENODEV to indicate that the timer was not running */ + + return -ENODEV; +} + +/**************************************************************************** + * Name: stm32_getduty + * + * Description: + * get result duty + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * duty - DutyCycle * 100. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_getduty(struct cap_lowerhalf_s *lower, uint8_t *duty) +{ + struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower; + + irqstate_t flags = enter_critical_section(); + + *duty = priv->duty; + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: stm32_getfreq + * + * Description: + * get result freq + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * freq - Frequency in Hz. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_getfreq(struct cap_lowerhalf_s *lower, uint32_t *freq) +{ + struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower; + + irqstate_t flags = enter_critical_section(); + + *freq = priv->freq; + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_cap_initialize + * + * Description: + * Initialize one timer for use with the upper_level capture driver. + * + * Input Parameters: + * timer - A number identifying the timer use. The number of valid timer + * IDs varies with the STM32 MCU and MCU family but is somewhere in + * the range of {1,..,5, 8, 12, 15}. + * + * Returned Value: + * On success, a pointer to the STM32 lower half capture driver returned. + * NULL is returned on any failure. + * + ****************************************************************************/ + +struct cap_lowerhalf_s *stm32_cap_initialize(int timer) +{ + struct stm32_lowerhalf_s *lower = NULL; + + switch (timer) + { +#ifdef CONFIG_STM32_TIM1_CAP + case 1: + lower = &g_cap1_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM2_CAP + case 2: + lower = &g_cap2_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM3_CAP + case 3: + lower = &g_cap3_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM4_CAP + case 4: + lower = &g_cap4_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM5_CAP + case 5: + lower = &g_cap5_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM8_CAP + case 8: + lower = &g_cap8_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM12_CAP + case 12: + lower = &g_cap12_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM15_CAP + case 15: + lower = &g_cap15_lowerhalf; + break; +#endif + + default: + { + lower = NULL; + goto errout; + } + } + + /* Initialize the elements of lower half state structure */ + + lower->started = false; + lower->cap = stm32_cap_init(timer); + + if (lower->cap == NULL) + { + lower = NULL; + } + +errout: + return (struct cap_lowerhalf_s *)lower; +} + +#endif /* CONFIG_CAPTURE */ diff --git a/boards/arm/stm32h5/nucleo-h563zi/configs/capture/defconfig b/boards/arm/stm32h5/nucleo-h563zi/configs/capture/defconfig new file mode 100644 index 00000000000..e9ff6a7f11e --- /dev/null +++ b/boards/arm/stm32h5/nucleo-h563zi/configs/capture/defconfig @@ -0,0 +1,56 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_STANDARD_SERIAL is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nucleo-h563zi" +CONFIG_ARCH_BOARD_NUCLEO_H563ZI=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP="stm32h5" +CONFIG_ARCH_CHIP_STM32=y +CONFIG_ARCH_CHIP_STM32H563ZI=y +CONFIG_ARCH_CHIP_STM32H5=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV8M_STACKCHECK=y +CONFIG_BOARD_LOOPSPERMSEC=9251 +CONFIG_BUILTIN=y +CONFIG_CAPTURE=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_EXAMPLES_CAPTURE=y +CONFIG_EXAMPLES_CAPTURE_DEVPATH="/dev/cap0" +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_LINE_MAX=64 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=655360 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_STM32_TIM4=y +CONFIG_STM32_TIM4_CAP=y +CONFIG_STM32_TIM4_CLOCK=25000000 +CONFIG_STM32_USART3=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_TIMER=y +CONFIG_USART3_SERIAL_CONSOLE=y diff --git a/boards/arm/stm32h5/nucleo-h563zi/include/board.h b/boards/arm/stm32h5/nucleo-h563zi/include/board.h index 80e1eddf29a..304ff31f2d1 100644 --- a/boards/arm/stm32h5/nucleo-h563zi/include/board.h +++ b/boards/arm/stm32h5/nucleo-h563zi/include/board.h @@ -364,6 +364,13 @@ #define GPIO_TIM1_CH1OUT GPIO_TIM1_CH1OUT_2 /* PE9 */ +/* TIM4 capture (PWM input). The capture driver measures the signal on the + * pin of the selected channel (CONFIG_STM32_TIM4_CHANNEL, 1 by default). + */ + +#define GPIO_TIM4_CH1IN GPIO_TIM4_CH1IN_1 /* PB6 */ +#define GPIO_TIM4_CH2IN GPIO_TIM4_CH2IN_1 /* PB7 */ + /* USART3 GPIOs *************************************************************/ /* USART3 (Nucleo Virtual Console): Default board solder bridge configuration diff --git a/boards/arm/stm32h5/nucleo-h563zi/src/stm32_bringup.c b/boards/arm/stm32h5/nucleo-h563zi/src/stm32_bringup.c index 335dfd2cd22..0b67b2d6ff1 100644 --- a/boards/arm/stm32h5/nucleo-h563zi/src/stm32_bringup.c +++ b/boards/arm/stm32h5/nucleo-h563zi/src/stm32_bringup.c @@ -39,10 +39,83 @@ #include "board_common.h" +#if defined(CONFIG_CAPTURE) && defined(CONFIG_STM32_TIMX_CAP) +# include <errno.h> +# include <nuttx/timers/capture.h> +# include "stm32_capture.h" +# define HAVE_CAPTURE 1 +#endif + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_capture_setup + * + * Description: + * Initialize and register the capture drivers of the timers that are + * configured for capture. They are registered as /dev/cap0, /dev/cap1, + * etc. in the order of the timer numbers. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef HAVE_CAPTURE +static int stm32_capture_setup(void) +{ + struct cap_lowerhalf_s *lower[] = + { +#ifdef CONFIG_STM32_TIM1_CAP + stm32_cap_initialize(1), +#endif +#ifdef CONFIG_STM32_TIM2_CAP + stm32_cap_initialize(2), +#endif +#ifdef CONFIG_STM32_TIM3_CAP + stm32_cap_initialize(3), +#endif +#ifdef CONFIG_STM32_TIM4_CAP + stm32_cap_initialize(4), +#endif +#ifdef CONFIG_STM32_TIM5_CAP + stm32_cap_initialize(5), +#endif +#ifdef CONFIG_STM32_TIM8_CAP + stm32_cap_initialize(8), +#endif +#ifdef CONFIG_STM32_TIM12_CAP + stm32_cap_initialize(12), +#endif +#ifdef CONFIG_STM32_TIM15_CAP + stm32_cap_initialize(15), +#endif + }; + + size_t count = sizeof(lower) / sizeof(lower[0]); + size_t i; + + for (i = 0; i < count; i++) + { + if (lower[i] == NULL) + { + syslog(LOG_ERR, "ERROR: Failed to initialize a capture timer\n"); + return -ENODEV; + } + } + + /* This will register "/dev/cap0" ... "/dev/cap<count-1>" */ + + return cap_register_multiple("/dev/cap", lower, count); +} +#endif /* HAVE_CAPTURE */ + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -147,6 +220,16 @@ int stm32_bringup(void) } #endif +#ifdef HAVE_CAPTURE + /* Initialize the capture drivers and register them as /dev/capN */ + + ret = stm32_capture_setup(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_capture_setup() failed: %d\n", ret); + } +#endif + #ifdef CONFIG_USBHOST ret = stm32_usbhost_initialize(); if (ret < 0)
