diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig index 28d17d3b78..df1e139865 100644 --- a/arch/arm/src/stm32/Kconfig +++ b/arch/arm/src/stm32/Kconfig @@ -3413,6 +3413,10 @@ config STM32_PWM bool default n +config STM32_CAP + bool + default n + config STM32_COMP bool default n @@ -6765,122 +6769,350 @@ config STM32_TIM1_CAP bool "TIM1 Capture" default n depends on STM32_TIM1 + select STM32_CAP ---help--- Reserve timer 1 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM1_CAP + +config STM32_TIM1_CHANNEL + int "TIM1 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM1 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM1_CLOCK + int "TIM1 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM1_CAP + config STM32_TIM2_CAP bool "TIM2 Capture" default n depends on STM32_TIM2 + select STM32_CAP ---help--- Reserve timer 2 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM2_CAP + +config STM32_TIM2_CHANNEL + int "TIM2 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM2 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM2_CLOCK + int "TIM2 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM2_CAP + config STM32_TIM3_CAP bool "TIM3 Capture" default n depends on STM32_TIM3 + select STM32_CAP ---help--- Reserve timer 3 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM3_CAP + +config STM32_TIM3_CHANNEL + int "TIM3 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM3 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM3_CLOCK + int "TIM3 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM3_CAP + config STM32_TIM4_CAP bool "TIM4 Capture" default n depends on STM32_TIM4 + select STM32_CAP ---help--- Reserve timer 4 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM4_CAP + +config STM32_TIM4_CHANNEL + int "TIM4 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM4 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM4_CLOCK + int "TIM4 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM4_CAP + config STM32_TIM5_CAP bool "TIM5 Capture" default n depends on STM32_TIM5 + select STM32_CAP ---help--- Reserve timer 5 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM5_CAP + +config STM32_TIM5_CHANNEL + int "TIM5 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM5 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM5_CLOCK + int "TIM5 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM5_CAP + config STM32_TIM8_CAP bool "TIM8 Capture" default n depends on STM32_TIM8 + select STM32_CAP ---help--- Reserve timer 8 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM8_CAP + +config STM32_TIM8_CHANNEL + int "TIM8 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM8 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM8_CLOCK + int "TIM8 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM8_CAP + config STM32_TIM9_CAP bool "TIM9 Capture" default n depends on STM32_TIM9 + select STM32_CAP ---help--- Reserve timer 9 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM9_CAP + +config STM32_TIM9_CHANNEL + int "TIM9 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM9 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM9_CLOCK + int "TIM9 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM9_CAP + config STM32_TIM10_CAP bool "TIM10 Capture" default n depends on STM32_TIM10 + select STM32_CAP ---help--- Reserve timer 10 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM10_CAP + +config STM32_TIM10_CHANNEL + int "TIM10 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM10 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM10_CLOCK + int "TIM10 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM10_CAP + config STM32_TIM11_CAP bool "TIM11 Capture" default n depends on STM32_TIM11 + select STM32_CAP ---help--- Reserve timer 11 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM11_CAP + +config STM32_TIM11_CHANNEL + int "TIM11 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM11 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM11_CLOCK + int "TIM11 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM11_CAP + config STM32_TIM12_CAP bool "TIM12 Capture" default n depends on STM32_TIM12 + select STM32_CAP ---help--- Reserve timer 12 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM12_CAP + +config STM32_TIM12_CHANNEL + int "TIM12 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM12 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM12_CLOCK + int "TIM12 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM12_CAP + config STM32_TIM13_CAP bool "TIM13 Capture" default n depends on STM32_TIM13 + select STM32_CAP ---help--- Reserve timer 13 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM13_CAP + +config STM32_TIM13_CHANNEL + int "TIM13 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM13 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM13_CLOCK + int "TIM13 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM13_CAP + config STM32_TIM14_CAP bool "TIM14 Capture" default n depends on STM32_TIM14 + select STM32_CAP ---help--- Reserve timer 14 for use by Capture Timer devices may be used for different purposes. One special purpose is to capture input. +if STM32_TIM14_CAP + +config STM32_TIM14_CHANNEL + int "TIM14 Capture Input Channel" + default 1 + range 1 4 + ---help--- + If TIM14 is enabled for capture usage, you also need specifies the timer input + channel {1,..,4} + +config STM32_TIM14_CLOCK + int "TIM14 work frequence for capture" + default 1000000 + ---help--- + This clock frequence limiting the count rate at the expense of resolution. + +endif # STM32_TIM14_CAP + menu "STM32 TIMx Outputs Configuration" config STM32_TIM1_CH1POL diff --git a/arch/arm/src/stm32/Make.defs b/arch/arm/src/stm32/Make.defs index 2413ecb014..4f7bf86e04 100644 --- a/arch/arm/src/stm32/Make.defs +++ b/arch/arm/src/stm32/Make.defs @@ -175,6 +175,10 @@ ifeq ($(CONFIG_STM32_PWM),y) CHIP_CSRCS += stm32_pwm.c endif +ifeq ($(CONFIG_STM32_CAP),y) +CHIP_CSRCS += stm32_capture_lowerhalf.c +endif + ifeq ($(CONFIG_SENSORS_QENCODER),y) CHIP_CSRCS += stm32_qencoder.c endif diff --git a/arch/arm/src/stm32/stm32_capture.c b/arch/arm/src/stm32/stm32_capture.c index 57050a83ed..20ed6a109f 100644 --- a/arch/arm/src/stm32/stm32_capture.c +++ b/arch/arm/src/stm32/stm32_capture.c @@ -617,13 +617,15 @@ static inline int stm32_cap_set_rcc(const struct stm32_cap_priv_s *priv, ****************************************************************************/ static int stm32_cap_setclock(struct stm32_cap_dev_s *dev, - stm32_cap_clk_t clk, - uint32_t prescaler, uint32_t max) + uint32_t freq, uint32_t max) { const struct stm32_cap_priv_s *priv = (const struct stm32_cap_priv_s *)dev; - uint16_t regval = 0; + uint32_t freqin; + int prescaler; - if (prescaler == 0) + /* Disable Timer? */ + + if (freq == 0) { /* Disable Timer */ @@ -631,6 +633,85 @@ static int stm32_cap_setclock(struct stm32_cap_dev_s *dev, 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_APB2_TIM1_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM2 + case STM32_TIM2_BASE: + freqin = STM32_APB1_TIM2_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM3 + case STM32_TIM3_BASE: + freqin = STM32_APB1_TIM3_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM4 + case STM32_TIM4_BASE: + freqin = STM32_APB1_TIM4_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM5 + case STM32_TIM5_BASE: + freqin = STM32_APB1_TIM5_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM8 + case STM32_TIM8_BASE: + freqin = STM32_APB2_TIM8_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM9 + case STM32_TIM9_BASE: + freqin = STM32_APB2_TIM9_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM10 + case STM32_TIM10_BASE: + freqin = STM32_APB2_TIM10_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM11 + case STM32_TIM11_BASE: + freqin = STM32_APB2_TIM11_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM12 + case STM32_TIM12_BASE: + freqin = STM32_APB1_TIM12_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM13 + case STM32_TIM13_BASE: + freqin = STM32_APB1_TIM13_CLKIN; + break; +#endif +#ifdef CONFIG_STM32_TIM14 + case STM32_TIM14_BASE: + freqin = STM32_APB1_TIM14_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. */ @@ -645,47 +726,6 @@ static int stm32_cap_setclock(struct stm32_cap_dev_s *dev, prescaler = 0xffff; } - switch (clk) - { - case STM32_CAP_CLK_INT: - regval = GTIM_SMCR_DISAB; - break; - - case STM32_CAP_CLK_ENC1: - regval = GTIM_SMCR_ENCMD1; - break; - - case STM32_CAP_CLK_ENC2: - regval = GTIM_SMCR_ENCMD2; - break; - - case STM32_CAP_CLK_ENC3: - regval = GTIM_SMCR_ENCMD3; - break; - - case STM32_CAP_CLK_RST: - regval = GTIM_SMCR_RESET; - break; - - case STM32_CAP_CLK_GAT: - regval = GTIM_SMCR_GATED; - break; - - case STM32_CAP_CLK_TRG: - regval = GTIM_SMCR_TRIGGER; - break; - - case STM32_CAP_CLK_EXT: - regval = GTIM_SMCR_EXTCLK1; - break; - - default: - return ERROR; - } - - stm32_modifyreg16(priv, STM32_GTIM_SMCR_OFFSET, - GTIM_SMCR_SMS_MASK, regval); - /* Set Maximum */ stm32_putreg32(priv, STM32_BTIM_ARR_OFFSET, max); @@ -714,6 +754,115 @@ static int stm32_cap_setclock(struct stm32_cap_dev_s *dev, 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) { @@ -1088,6 +1237,7 @@ static uint32_t stm32_cap_getcapture(struct stm32_cap_dev_s *dev, struct stm32_cap_ops_s stm32_cap_ops = { + .setsmc = &stm32_cap_setsmc, .setclock = &stm32_cap_setclock, .setchannel = &stm32_cap_setchannel, .getcapture = &stm32_cap_getcapture, diff --git a/arch/arm/src/stm32/stm32_capture.h b/arch/arm/src/stm32/stm32_capture.h index 347545fc31..ae73cb1989 100644 --- a/arch/arm/src/stm32/stm32_capture.h +++ b/arch/arm/src/stm32/stm32_capture.h @@ -37,7 +37,8 @@ /* Helpers ******************************************************************/ -#define STM32_CAP_SETCLOCK(d,clk_src,psc,max) ((d)->ops->setclock(d,clk_src,psc,max)) +#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)) @@ -122,19 +123,38 @@ typedef enum STM32_CAP_EDGE_BOTH = (3 << 8), } stm32_cap_ch_cfg_t; -/* Capture clock sources */ +/* Slave mode control configure */ typedef enum { - STM32_CAP_CLK_INT = 0, - STM32_CAP_CLK_ENC1, - STM32_CAP_CLK_ENC2, - STM32_CAP_CLK_ENC3, - STM32_CAP_CLK_RST, - STM32_CAP_CLK_GAT, - STM32_CAP_CLK_TRG, - STM32_CAP_CLK_EXT, -} stm32_cap_clk_t; + /* 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 seting */ + + STM32_CAP_MSM_MASK = (1 << 7) +} stm32_cap_smc_cfg_t; /* Capture flags */ @@ -163,8 +183,9 @@ typedef enum struct stm32_cap_ops_s { - int (*setclock)(struct stm32_cap_dev_s *dev, stm32_cap_clk_t clk, - uint32_t prescaler, uint32_t max); + 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); @@ -187,6 +208,27 @@ struct stm32_cap_dev_s *stm32_cap_init(int timer); 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,...,14}. + * + * 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) } diff --git a/arch/arm/src/stm32/stm32_capture_lowerhalf.c b/arch/arm/src/stm32/stm32_capture_lowerhalf.c new file mode 100644 index 0000000000..bc27927818 --- /dev/null +++ b/arch/arm/src/stm32/stm32_capture_lowerhalf.c @@ -0,0 +1,575 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_capture_lowerhalf.c + * + * 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 + +#include + +#include +#include +#include + +#include +#include + +#include + +#include "stm32_capture.h" + +#if defined(CONFIG_STM32_CAP) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define STM32_TIM1_RES 16 +#if defined(CONFIG_STM32_STM32L15XX) || defined(CONFIG_STM32_STM32F10XX) +# define STM32_TIM2_RES 16 +#else +# define STM32_TIM2_RES 32 +#endif +#define STM32_TIM3_RES 16 +#define STM32_TIM4_RES 16 +#if defined(CONFIG_STM32_STM32F10XX) || defined(CONFIG_STM32_STM32F30XX) +# define STM32_TIM5_RES 16 +#else +# define STM32_TIM5_RES 32 +#endif +#define STM32_TIM8_RES 16 +#define STM32_TIM9_RES 16 +#define STM32_TIM10_RES 16 +#define STM32_TIM11_RES 16 +#define STM32_TIM12_RES 16 +#define STM32_TIM13_RES 16 +#define STM32_TIM14_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 frequence */ + uint8_t duty; /* Result pwm frequence */ + uint32_t freq; /* Result pwm frequence */ +}; + +/**************************************************************************** + * 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_TIM9_CAP +static struct stm32_lowerhalf_s g_cap9_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM9_RES, + .channel = CONFIG_STM32_TIM9_CHANNEL, + .clock = CONFIG_STM32_TIM9_CLOCK, +}; +#endif + +#ifdef CONFIG_STM32_TIM10_CAP +static struct stm32_lowerhalf_s g_cap10_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM10_RES, + .channel = CONFIG_STM32_TIM10_CHANNEL, + .clock = CONFIG_STM32_TIM10_CLOCK, +}; +#endif + +#ifdef CONFIG_STM32_TIM11_CAP +static struct stm32_lowerhalf_s g_cap11_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM11_RES, + .channel = CONFIG_STM32_TIM11_CHANNEL, + .clock = CONFIG_STM32_TIM11_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_TIM13_CAP +static struct stm32_lowerhalf_s g_cap13_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM13_RES, + .channel = CONFIG_STM32_TIM13_CHANNEL, + .clock = CONFIG_STM32_TIM13_CLOCK, +}; +#endif + +#ifdef CONFIG_STM32_TIM14_CAP +static struct stm32_lowerhalf_s g_cap14_lowerhalf = +{ + .ops = &g_cap_ops, + .resolution = STM32_TIM14_RES, + .channel = CONFIG_STM32_TIM14_CHANNEL, + .clock = CONFIG_STM32_TIM14_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; + } + else + { + lower->duty = 0; + } + + lower->freq = lower->clock / period; + + 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) + { + STM32_CAP_SETCHANNEL(priv->cap, STM32_CAP_FLAG_IRQ_COUNTER, + STM32_CAP_EDGE_DISABLED); + switch (priv->channel) + { + case 1: + STM32_CAP_ENABLEINT(priv->cap, STM32_CAP_FLAG_IRQ_CH_1, false); + break; + + case 2: + STM32_CAP_ENABLEINT(priv->cap, STM32_CAP_FLAG_IRQ_CH_2, false); + break; + + default: + return ERROR; + } + + STM32_CAP_SETISR(priv->cap, NULL, NULL); + 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 - Frequence 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,...,14}. + * + * 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_TIM6_CAP + case 6: + lower = &g_cap6_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM9_CAP + case 9: + lower = &g_cap9_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM10_CAP + case 10: + lower = &g_cap10_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM11_CAP + case 11: + lower = &g_cap11_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM12_CAP + case 12: + lower = &g_cap12_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM13_CAP + case 13: + lower = &g_cap13_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32_TIM14_CAP + case 14: + lower = &g_cap14_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_STM32_CAP */ diff --git a/arch/arm/src/stm32/stm32_tim.c b/arch/arm/src/stm32/stm32_tim.c index 7046e1f212..0367f6015e 100644 --- a/arch/arm/src/stm32/stm32_tim.c +++ b/arch/arm/src/stm32/stm32_tim.c @@ -71,23 +71,28 @@ */ #if defined(CONFIG_STM32_TIM1_PWM) || defined (CONFIG_STM32_TIM1_ADC) || \ - defined(CONFIG_STM32_TIM1_DAC) || defined(CONFIG_STM32_TIM1_QE) + defined(CONFIG_STM32_TIM1_DAC) || defined(CONFIG_STM32_TIM1_QE) || \ + defined(CONFIG_STM32_TIM1_CAP) # undef CONFIG_STM32_TIM1 #endif #if defined(CONFIG_STM32_TIM2_PWM) || defined (CONFIG_STM32_TIM2_ADC) || \ - defined(CONFIG_STM32_TIM2_DAC) || defined(CONFIG_STM32_TIM2_QE) + defined(CONFIG_STM32_TIM2_DAC) || defined(CONFIG_STM32_TIM2_QE) || \ + defined(CONFIG_STM32_TIM2_CAP) # undef CONFIG_STM32_TIM2 #endif #if defined(CONFIG_STM32_TIM3_PWM) || defined (CONFIG_STM32_TIM3_ADC) || \ - defined(CONFIG_STM32_TIM3_DAC) || defined(CONFIG_STM32_TIM3_QE) + defined(CONFIG_STM32_TIM3_DAC) || defined(CONFIG_STM32_TIM3_QE) || \ + defined(CONFIG_STM32_TIM3_CAP) # undef CONFIG_STM32_TIM3 #endif #if defined(CONFIG_STM32_TIM4_PWM) || defined (CONFIG_STM32_TIM4_ADC) || \ - defined(CONFIG_STM32_TIM4_DAC) || defined(CONFIG_STM32_TIM4_QE) + defined(CONFIG_STM32_TIM4_DAC) || defined(CONFIG_STM32_TIM4_QE) || \ + defined(CONFIG_STM32_TIM4_CAP) # undef CONFIG_STM32_TIM4 #endif #if defined(CONFIG_STM32_TIM5_PWM) || defined (CONFIG_STM32_TIM5_ADC) || \ - defined(CONFIG_STM32_TIM5_DAC) || defined(CONFIG_STM32_TIM5_QE) + defined(CONFIG_STM32_TIM5_DAC) || defined(CONFIG_STM32_TIM5_QE) || \ + defined(CONFIG_STM32_TIM5_CAP) # undef CONFIG_STM32_TIM5 #endif #if defined(CONFIG_STM32_TIM6_PWM) || defined (CONFIG_STM32_TIM6_ADC) || \ @@ -99,31 +104,38 @@ # undef CONFIG_STM32_TIM7 #endif #if defined(CONFIG_STM32_TIM8_PWM) || defined (CONFIG_STM32_TIM8_ADC) || \ - defined(CONFIG_STM32_TIM8_DAC) || defined(CONFIG_STM32_TIM8_QE) + defined(CONFIG_STM32_TIM8_DAC) || defined(CONFIG_STM32_TIM8_QE) || \ + defined(CONFIG_STM32_TIM8_CAP) # undef CONFIG_STM32_TIM8 #endif #if defined(CONFIG_STM32_TIM9_PWM) || defined (CONFIG_STM32_TIM9_ADC) || \ - defined(CONFIG_STM32_TIM9_DAC) || defined(CONFIG_STM32_TIM9_QE) + defined(CONFIG_STM32_TIM9_DAC) || defined(CONFIG_STM32_TIM9_QE) || \ + defined(CONFIG_STM32_TIM9_CAP) # undef CONFIG_STM32_TIM9 #endif #if defined(CONFIG_STM32_TIM10_PWM) || defined (CONFIG_STM32_TIM10_ADC) || \ - defined(CONFIG_STM32_TIM10_DAC) || defined(CONFIG_STM32_TIM10_QE) + defined(CONFIG_STM32_TIM10_DAC) || defined(CONFIG_STM32_TIM10_QE) || \ + defined(CONFIG_STM32_TIM10_CAP) # undef CONFIG_STM32_TIM10 #endif #if defined(CONFIG_STM32_TIM11_PWM) || defined (CONFIG_STM32_TIM11_ADC) || \ - defined(CONFIG_STM32_TIM11_DAC) || defined(CONFIG_STM32_TIM11_QE) + defined(CONFIG_STM32_TIM11_DAC) || defined(CONFIG_STM32_TIM11_QE) || \ + defined(CONFIG_STM32_TIM11_CAP) # undef CONFIG_STM32_TIM11 #endif #if defined(CONFIG_STM32_TIM12_PWM) || defined (CONFIG_STM32_TIM12_ADC) || \ - defined(CONFIG_STM32_TIM12_DAC) || defined(CONFIG_STM32_TIM12_QE) + defined(CONFIG_STM32_TIM12_DAC) || defined(CONFIG_STM32_TIM12_QE) || \ + defined(CONFIG_STM32_TIM12_CAP) # undef CONFIG_STM32_TIM12 #endif #if defined(CONFIG_STM32_TIM13_PWM) || defined (CONFIG_STM32_TIM13_ADC) || \ - defined(CONFIG_STM32_TIM13_DAC) || defined(CONFIG_STM32_TIM13_QE) + defined(CONFIG_STM32_TIM13_DAC) || defined(CONFIG_STM32_TIM13_QE) || \ + defined(CONFIG_STM32_TIM13_CAP) # undef CONFIG_STM32_TIM13 #endif #if defined(CONFIG_STM32_TIM14_PWM) || defined (CONFIG_STM32_TIM14_ADC) || \ - defined(CONFIG_STM32_TIM14_DAC) || defined(CONFIG_STM32_TIM14_QE) + defined(CONFIG_STM32_TIM14_DAC) || defined(CONFIG_STM32_TIM14_QE) || \ + defined(CONFIG_STM32_TIM14_CAP) # undef CONFIG_STM32_TIM14 #endif #if defined(CONFIG_STM32_TIM15_PWM) || defined (CONFIG_STM32_TIM15_ADC) || \