diff options
Diffstat (limited to 'nuttx/arch/arm/src/stm32/stm32_pwm.c')
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_pwm.c | 617 |
1 files changed, 548 insertions, 69 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_pwm.c b/nuttx/arch/arm/src/stm32/stm32_pwm.c index 8646bfcd7..141b7bb43 100644 --- a/nuttx/arch/arm/src/stm32/stm32_pwm.c +++ b/nuttx/arch/arm/src/stm32/stm32_pwm.c @@ -42,9 +42,11 @@ #include <stdint.h> #include <stdio.h> #include <assert.h> +#include <errno.h> #include <debug.h> #include <nuttx/pwm.h> +#include <arch/board/board.h> #include "up_internal.h" #include "up_arch.h" @@ -59,8 +61,7 @@ #if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM2_PWM) || \ defined(CONFIG_STM32_TIM3_PWM) || defined(CONFIG_STM32_TIM4_PWM) || \ - defined(CONFIG_STM32_TIM5_PWM) || defined(CONFIG_STM32_TIM6_PWM) || \ - defined(CONFIG_STM32_TIM7_PWM) || defined(CONFIG_STM32_TIM8_PWM) || \ + defined(CONFIG_STM32_TIM5_PWM) || defined(CONFIG_STM32_TIM8_PWM) || \ defined(CONFIG_STM32_TIM9_PWM) || defined(CONFIG_STM32_TIM10_PWM) || \ defined(CONFIG_STM32_TIM11_PWM) || defined(CONFIG_STM32_TIM12_PWM) || \ defined(CONFIG_STM32_TIM13_PWM) || defined(CONFIG_STM32_TIM14_PWM) @@ -68,6 +69,19 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* Debug ********************************************************************/ + +#ifdef CONFIG_DEBUG_PWM +# define pwmdbg dbg +# define pwmvdbg vdbg +# define pwmlldbg lldbg +# define pwmllvdbg llvdbg +#else +# define pwmdbg(x...) +# define pwmvdbg(x...) +# define pwmlldbg(x...) +# define pwmllvdbg(x...) +#endif /**************************************************************************** * Private Types @@ -76,12 +90,26 @@ struct stm32_pwmtimer_s { - uint32_t base; /* The base address of the timer */ + FAR const struct pwm_ops_s *ops; /* PWM operations */ + uint8_t timid; /* Timer ID {1,...,14} */ + uint8_t channel; /* Timer output channel: {1,..4} */ + uint8_t unused2; + uint8_t unused3; + uint32_t base; /* The base address of the timer */ + uint32_t pincfg; /* Output pin configuration */ + uint32_t pclk; /* The frequency of the peripheral clock + * that drives the timer module. */ }; /**************************************************************************** * Static Function Prototypes ****************************************************************************/ +/* Register access */ + +static uint16_t pwm_getreg(struct stm32_pwmtimer_s *priv, int offset); +static void pwm_putreg(struct stm32_pwmtimer_s *priv, int offset, uint16_t value); + +/* PWM driver methods */ static int pwm_setup(FAR struct pwm_lowerhalf_s *dev); static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev); @@ -97,125 +125,155 @@ static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg static const struct pwm_ops_s g_pwmops = { - .setup = pwm_setup(FAR struct pwm_lowerhalf_s *dev); - .shutdown = pwm_shutdown(FAR struct pwm_lowerhalf_s *dev); - .start = pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info); - .stop = pwm_stop(FAR struct pwm_lowerhalf_s *dev); - .pulsecount = pwm_pulsecount(FAR struct pwm_lowerhalf_s *dev, FAR pwm_count_t *count); - .ioctl = pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, unsigned long arg); + .setup = pwm_setup, + .shutdown = pwm_shutdown, + .start = pwm_start, + .stop = pwm_stop, + .pulsecount = pwm_pulsecount, + .ioctl = pwm_ioctl, }; -/* The following represent the state of each possible PWM driver */ - #ifdef CONFIG_STM32_TIM1_PWM static struct stm32_pwmtimer_s g_pwm1dev = { - .ops = *g_pwmops; - .base = STM32_TIM1_BASE; + .ops = &g_pwmops, + .timid = 1, + .channel = CONFIG_STM32_TIM1_CHANNEL, + .base = STM32_TIM1_BASE, + .pincfg = PWM_TIM1_PINCFG, + .pclk = STM32_PCLK2_FREQUENCY, }; #endif #ifdef CONFIG_STM32_TIM2_PWM static struct stm32_pwmtimer_s g_pwm2dev = { - .ops = *g_pwmops; - .base = STM32_TIM2_BASE; + .ops = &g_pwmops, + .timid = 2, + .channel = CONFIG_STM32_TIM2_CHANNEL, + .base = STM32_TIM2_BASE, + .pincfg = PWM_TIM2_PINCFG, + .pclk = STM32_PCLK1_FREQUENCY, }; #endif #ifdef CONFIG_STM32_TIM3_PWM static struct stm32_pwmtimer_s g_pwm3dev = { - .ops = *g_pwmops; - .base = STM32_TIM3_BASE; + .ops = &g_pwmops, + .timid = 3, + .channel = CONFIG_STM32_TIM3_CHANNEL, + .base = STM32_TIM3_BASE, + .pincfg = PWM_TIM3_PINCFG, + .pclk = STM32_PCLK1_FREQUENCY, }; #endif #ifdef CONFIG_STM32_TIM4_PWM static struct stm32_pwmtimer_s g_pwm4dev = { - .ops = *g_pwmops; - .base = STM32_TIM4_BASE; + .ops = &g_pwmops, + .timid = 4, + .channel = CONFIG_STM32_TIM4_CHANNEL, + .base = STM32_TIM4_BASE, + .pincfg = PWM_TIM4_PINCFG, + .pclk = STM32_PCLK1_FREQUENCY, }; #endif #ifdef CONFIG_STM32_TIM5_PWM static struct stm32_pwmtimer_s g_pwm5dev = { - .ops = *g_pwmops; - .base = STM32_TIM5_BASE; -}; -#endif - -#ifdef CONFIG_STM32_TIM6_PWM -static struct stm32_pwmtimer_s g_pwm6dev = -{ - .ops = *g_pwmops; - .base = STM32_TIM6_BASE; -}; -#endif - -#ifdef CONFIG_STM32_TIM7_PWM -static struct stm32_pwmtimer_s g_pwm7dev = -{ - .ops = *g_pwmops; - .base = STM32_TIM7_BASE; + .ops = &g_pwmops, + .timid = 5, + .channel = CONFIG_STM32_TIM5_CHANNEL, + .base = STM32_TIM5_BASE, + .pincfg = PWM_TIM5_PINCFG, + .pclk = STM32_PCLK1_FREQUENCY, }; #endif #ifdef CONFIG_STM32_TIM8_PWM static struct stm32_pwmtimer_s g_pwm8dev = { - .ops = *g_pwmops; - .base = STM32_TIM8_BASE; + .ops = &g_pwmops, + .timid = 8, + .channel = CONFIG_STM32_TIM8_CHANNEL, + .base = STM32_TIM8_BASE, + .pincfg = PWM_TIM8_PINCFG, + .pclk = STM32_PCLK2_FREQUENCY, }; #endif #ifdef CONFIG_STM32_TIM9_PWM static struct stm32_pwmtimer_s g_pwm9dev = { - .ops = *g_pwmops; - .base = STM32_TIM9_BASE; + .ops = &g_pwmops, + .timid = 9, + .channel = CONFIG_STM32_TIM9_CHANNEL, + .base = STM32_TIM9_BASE, + .pincfg = PWM_TIM9_PINCFG, + .pclk = STM32_PCLK2_FREQUENCY, }; #endif #ifdef CONFIG_STM32_TIM10_PWM static struct stm32_pwmtimer_s g_pwm10dev = { - .ops = *g_pwmops; - .base = STM32_TIM10_BASE; + .ops = &g_pwmops, + .timid = 10, + .channel = CONFIG_STM32_TIM10_CHANNEL, + .base = STM32_TIM10_BASE, + .pincfg = PWM_TIM10_PINCFG, + .pclk = STM32_PCLK2_FREQUENCY, }; #endif #ifdef CONFIG_STM32_TIM11_PWM static struct stm32_pwmtimer_s g_pwm11dev = { - .ops = *g_pwmops; - .base = STM32_TIM11_BASE; + .ops = &g_pwmops, + .timid = 11, + .channel = CONFIG_STM32_TIM11_CHANNEL, + .base = STM32_TIM11_BASE, + .pincfg = PWM_TIM11_PINCFG, + .pclk = STM32_PCLK2_FREQUENCY, }; #endif #ifdef CONFIG_STM32_TIM12_PWM static struct stm32_pwmtimer_s g_pwm12dev = { - .ops = *g_pwmops; - .base = STM32_TIM12_BASE; + .ops = &g_pwmops, + .timid = 12, + .channel = CONFIG_STM32_TIM12_CHANNEL, + .base = STM32_TIM12_BASE, + .pincfg = PWM_TIM12_PINCFG, + .pclk = STM32_PCLK1_FREQUENCY, }; #endif #ifdef CONFIG_STM32_TIM13_PWM static struct stm32_pwmtimer_s g_pwm13dev = { - .ops = *g_pwmops; - .base = STM32_TIM13_BASE; + .ops = &g_pwmops, + .timid = 13, + .channel = CONFIG_STM32_TIM13_CHANNEL, + .base = STM32_TIM13_BASE, + .pincfg = PWM_TIM13_PINCFG, + .pclk = STM32_PCLK1_FREQUENCY, }; #endif #ifdef CONFIG_STM32_TIM14_PWM static struct stm32_pwmtimer_s g_pwm14dev = { - .ops = *g_pwmops; - .base = STM32_TIM14_BASE; + .ops = &g_pwmops, + .timid = 14, + .channel = CONFIG_STM32_TIM14_CHANNEL, + .base = STM32_TIM14_BASE, + .pincfg = PWM_TIM14_PINCFG, + .pclk = STM32_PCLK1_FREQUENCY, }; #endif @@ -224,6 +282,46 @@ static struct stm32_pwmtimer_s g_pwm14dev = ****************************************************************************/ /**************************************************************************** + * Name: pwm_getreg + * + * Description: + * Read the value of an ADC timer register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ****************************************************************************/ + +static uint16_t pwm_getreg(struct stm32_pwmtimer_s *priv, int offset) +{ + return getreg16(priv->base + offset); +} + +/**************************************************************************** + * Name: pwm_putreg + * + * Description: + * Read the value of an ADC timer register. + * + * Input Parameters: + * priv - A reference to the ADC block status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void pwm_putreg(struct stm32_pwmtimer_s *priv, int offset, uint16_t value) +{ + putreg16(value, priv->base + offset); +} + +/**************************************************************************** * Name: pwm_setup * * Description: @@ -237,12 +335,20 @@ static struct stm32_pwmtimer_s g_pwm14dev = * Returned Value: * Zero on success; a negated errno value on failure * + * Assumptions: + * AHB1 or 2 clocking for the GPIOs and timer has already been configured + * by the RCC logic at power up. + * ****************************************************************************/ static int pwm_setup(FAR struct pwm_lowerhalf_s *dev) { -#warning "Missing logic" - return -ENOSYS; + FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev; + + /* Configure the PWM output pin, but do not start the timer yet */ + + stm32_configgpio(priv->pincfg); + return OK; } /**************************************************************************** @@ -263,8 +369,27 @@ static int pwm_setup(FAR struct pwm_lowerhalf_s *dev) static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev) { -#warning "Missing logic" - return -ENOSYS; + FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev; + uint32_t pincfg; + + /* Make sure that the output has been stopped */ + + pwm_stop(dev); + + /* Then put the GPIO pin back to the default state */ + + pincfg = priv->pincfg & (GPIO_PORT_MASK|GPIO_PIN_MASK); + +#if defined(CONFIG_STM32_STM32F10XX) + pincfg |= (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT); +#elif defined(CONFIG_STM32_STM32F40XX) + pincfg |= (GPIO_INPUT|GPIO_FLOAT); +#else +# error "Unrecognized STM32 chip" +#endif + + stm32_configgpio(pincfg); + return OK; } /**************************************************************************** @@ -284,8 +409,281 @@ static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev) static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info) { -#warning "Missing logic" - return -ENOSYS; + FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev; + + /* Calculated values */ + + uint32_t prescaler; + uint32_t timclk; + uint32_t reload; + uint32_t ccr; + + /* Register contents */ + + uint16_t cr1; + uint16_t ccer; + uint16_t cr2; + uint16_t ccmr1; + uint16_t ccmr2; + + /* New timer regiser bit settings */ + + uint16_t ccenable; + uint16_t ocmode1; + uint16_t ocmode2; + + /* Caculate optimal values for the timer prescaler and for the timer reload + * register. If' frequency' is the desired frequency, then + * + * reload = timclk / frequency + * timclk = pclk / presc + * + * Or, + * + * reload = pclk / presc / frequency + * + * There are many solutions to this this, but the best solution will be the + * one that has the largest reload value and the smallest prescaler value. + * That is the solution that should give us the most accuracy in the timer + * control. Subject to: + * + * 0 <= presc <= 65536 + * 1 <= reload <= 65535 + * + * So presc = pclk / 65535 / frequency would be optimal. + * + * Example: + * + * pclk = 42 MHz + * frequency = 100 Hz + * + * prescaler = 42,000,000 / 65,535 / 100 + * = 6.4 (or 7 -- taking the ceiling always) + * timclk = 42,000,000 / 7 + * = 6,000,000 + * reload = 7,000,000 / 100 + * = 60,000 + */ + + prescaler = (priv->pclk / info->frequency + 65534) / 65535; + if (prescaler < 1) + { + prescaler = 1; + } + else if (prescaler > 65536) + { + prescaler = 65536; + } + + timclk = priv->pclk / prescaler; + + reload = timclk / info->frequency; + if (reload < 1) + { + reload = 1; + } + else if (reload > 65535) + { + reload = 65535; + } + + pwmvdbg("TIM%d PCLK: %d frequency: %d TIMCLK: %d prescaler: %d reload: %d\n", + priv->timid, priv->pclk, info->frequency, timclk, prescaler, reload); + + /* Set up the timer CR1 register: + * + * 1-8 CKD[1:0] ARPE CMS[1:0] DIR OPM URS UDIS CEN + * 2-5 CKD[1:0] ARPE CMS DIR OPM URS UDIS CEN + * 6-7 ARPE OPM URS UDIS CEN + * 9-14 CKD[1:0] ARPE URS UDIS CEN + */ + + cr1 = pwm_getreg(priv, STM32_GTIM_CR1_OFFSET); + + /* Disable the timer until we get it configured */ + + cr1 &= ~GTIM_CR1_CEN; + + /* Set the counter mode for the advanced timers (1,8) and most general + * purpose timers (2-5, but not 9-14): + */ + +#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM2_PWM) || \ + defined(CONFIG_STM32_TIM3_PWM) || defined(CONFIG_STM32_TIM4_PWM) || \ + defined(CONFIG_STM32_TIM5_PWM) || defined(CONFIG_STM32_TIM8_PWM) + + if ((priv->timid >= 1 && priv->timid <= 5) || priv->timid == 8) + { + /* Select the Counter Mode == count up: + * + * ATIM_CR1_EDGE: The counter counts up or down depending on the + * direction bit(DIR). + * ATIM_CR1_DIR: 0: count up, 1: count down + */ + + cr1 &= ~(ATIM_CR1_DIR | ATIM_CR1_CMS_MASK); + cr1 |= ATIM_CR1_EDGE; + } +#endif + + /* Set the clock division to zero for all (but the basic timers, but there + * should be no basic timers in this context + */ + + cr1 &= ~GTIM_CR1_CKD_MASK; + pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, cr1); + + /* Set the reload and prescaler values */ + + pwm_putreg(priv, STM32_GTIM_ARR_OFFSET, reload); + pwm_putreg(priv, STM32_GTIM_PSC_OFFSET, prescaler - 1); + + /* Clear the advanced timers repitition counter in all but the advanced timers */ + +#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM) + if (priv->timid == 1 || priv->timid == 8) + { + pwm_putreg(priv, STM32_ATIM_RCR_OFFSET, 0); + } +#endif + + /* Generate an update event to reload the prescaler (all timers) */ + + pwm_putreg(priv, STM32_GTIM_EGR_OFFSET, ATIM_EGR_UG); + + /* Duty cycle: + * + * duty cycle = ccr / reload (fractional value) + */ + + ccr = b16toi(info->duty * reload + b16HALF); + + /* Handle channel specific setup */ + + ocmode1 = 0; + ocmode2 = 0; + switch (priv->channel) + { + case 1: /* PWM Mode configuration: Channel 1 */ + { + ccenable = ATIM_CCER_CC1E; + ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) | + ATIM_CCMR1_OC1PE; + } + break; + + case 2: /* PWM Mode configuration: Channel 2 */ + { + ccenable = ATIM_CCER_CC2E; + ocmode1 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC2M_SHIFT) | + ATIM_CCMR1_OC2PE; + } + break; + + case 3: /* PWM Mode configuration: Channel3 */ + { + ccenable = ATIM_CCER_CC3E; + ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC3M_SHIFT) | + ATIM_CCMR2_OC3PE; + } + break; + + case 4: /* PWM1 Mode configuration: Channel4 */ + { + ccenable = ATIM_CCER_CC4E; + ocmode2 = (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) | + (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR2_OC4M_SHIFT) | + ATIM_CCMR2_OC4PE; + } + break; + + default: + return -EINVAL; + } + + /* Disable the Channel by resetting the CCxE Bit in the CCER register */ + + ccer = pwm_getreg(priv, STM32_GTIM_CCER_OFFSET); + ccer &= ~ccenable; + pwm_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer); + + /* Fetch the CR2, CCMR1, and CCMR2 register (already have cr1 and ccer) */ + + cr2 = pwm_getreg(priv, STM32_GTIM_CR2_OFFSET); + ccmr1 = pwm_getreg(priv, STM32_GTIM_CCMR1_OFFSET); + ccmr2 = pwm_getreg(priv, STM32_GTIM_CCMR1_OFFSET); + + /* Reset the Output Compare Mode Bits and set the select output compare mode */ + + ccmr1 &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | ATIM_CCMR1_OC1PE | + ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | ATIM_CCMR1_OC2PE); + ccmr2 &= ~(ATIM_CCMR2_CC3S_MASK | ATIM_CCMR2_OC3M_MASK | ATIM_CCMR2_OC3PE | + ATIM_CCMR2_CC4S_MASK | ATIM_CCMR2_OC4M_MASK | ATIM_CCMR2_OC4PE); + ccmr1 |= ocmode1; + ccmr2 |= ocmode2; + + /* Reset the output polarity level of all channels (selects high polarity)*/ + + ccer &= ~(ATIM_CCER_CC1P | ATIM_CCER_CC2P | ATIM_CCER_CC3P | ATIM_CCER_CC4P); + + /* Enable the output state of the selected channel (only) */ + + ccer &= ~(ATIM_CCER_CC1E | ATIM_CCER_CC2E | ATIM_CCER_CC3E | ATIM_CCER_CC4E); + ccer |= ccenable; + + /* Some special setup for advanced timers */ + +#if defined(CONFIG_STM32_TIM1_PWM) || defined(CONFIG_STM32_TIM8_PWM) + if (priv->timid == 1 || priv->timid == 8) + { + /* Reset output N polarity level, output N state, output compre state, + * output compare N idle state. + */ + +#ifdef CONFIG_STM32_STM32F40XX + ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | ATIM_CCER_CC2NP | + ATIM_CCER_CC3NE | ATIM_CCER_CC3NP | ATIM_CCER_CC4NP); +#else + ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | ATIM_CCER_CC2NP | + ATIM_CCER_CC3NE | ATIM_CCER_CC3NP); +#endif + + /* Reset the output compare and output compare N IDLE State */ + + cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N | ATIM_CR2_OIS2 | ATIM_CR2_OIS2N | + ATIM_CR2_OIS3 | ATIM_CR2_OIS3N | ATIM_CR2_OIS4); + } +#ifdef CONFIG_STM32_STM32F40XX + else +#endif +#endif +#ifdef CONFIG_STM32_STM32F40XX + { + ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP | GTIM_CCER_CC4NP); + } +#endif + + /* Save the modified register values */ + + pwm_putreg(priv, STM32_GTIM_CR2_OFFSET, cr2); + pwm_putreg(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1); + pwm_putreg(priv, STM32_GTIM_CCMR1_OFFSET, ccmr2); + pwm_putreg(priv, STM32_GTIM_CCER_OFFSET, ccer); + + /* Set the ARR Preload Bit */ + + cr1 = pwm_getreg(priv, STM32_GTIM_CR1_OFFSET); + cr1 |= GTIM_CR1_ARPE; + pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, ccmr2); + + /* And, finally, enable the timer */ + + cr1 |= GTIM_CR1_CEN; + pwm_putreg(priv, STM32_GTIM_CR1_OFFSET, ccmr2); + return OK; } /**************************************************************************** @@ -304,8 +702,99 @@ static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_ static int pwm_stop(FAR struct pwm_lowerhalf_s *dev) { -#warning "Missing logic" - return -ENOSYS; + FAR struct stm32_pwmtimer_s *priv = (FAR struct stm32_pwmtimer_s *)dev; + + uint32_t resetbit; + uint32_t regaddr; + uint32_t regval; + + switch (priv->timid) + { +#ifdef CONFIG_STM32_TIM1_PWM + case 1: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM1RST; + break; +#endif +#ifdef CONFIG_STM32_TIM2_PWM + case 2: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM2RST; + break; +#endif +#ifdef CONFIG_STM32_TIM3_PWM + case 3: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM3RST; + break; +#endif +#ifdef CONFIG_STM32_TIM4_PWM + case 4: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM4RST; + break; +#endif +#ifdef CONFIG_STM32_TIM5_PWM + case 5: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM5RST; + break; +#endif +#ifdef CONFIG_STM32_TIM8_PWM + case 8: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM8RST; + break; +#endif +#ifdef CONFIG_STM32_TIM9_PWM + case 9: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM9RST; + break; +#endif +#ifdef CONFIG_STM32_TIM10_PWM + case 10: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM10RST; + break; +#endif +#ifdef CONFIG_STM32_TIM11_PWM + case 11: + regaddr = STM32_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM11RST; + break; +#endif +#ifdef CONFIG_STM32_TIM12_PWM + case 12: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM12RST; + break; +#endif +#ifdef CONFIG_STM32_TIM13_PWM + case 13: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM13RST; + break; +#endif +#ifdef CONFIG_STM32_TIM14_PWM + case 14: + regaddr = STM32_RCC_APB1RSTR; + resetbit = RCC_APB1RSTR_TIM14RST; + break; +#endif + } + + /* Reset the timer - stopping the output and putting the timer back + * into a state where pwm_start() can be called. + */ + + regval = getreg32(regaddr); + regval |= resetbit; + putreg32(regval, regaddr); + + regval &= ~resetbit; + putreg32(regval, regaddr); + return OK; } /**************************************************************************** @@ -404,16 +893,6 @@ FAR struct pwm_lowerhalf_s *stm32_pwminitialize(int timer) lower = &g_pwm5dev; break; #endif -#ifdef CONFIG_STM32_TIM6_PWM - case 6: - lower = &g_pwm6dev; - break; -#endif -#ifdef CONFIG_STM32_TIM7_PWM - case 7: - lower = &g_pwm7dev; - break; -#endif #ifdef CONFIG_STM32_TIM8_PWM case 8: lower = &g_pwm8dev; |