From 62210303abf6ea324abe1cb53048860e8ae89bed Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Wed, 10 May 2023 08:31:42 +0200 Subject: [PATCH] cpu/stm32/periph_pwm: allow to use complementary timer channels To use a complementary output of an advanced timer as PWM channel, the output is defined with an offset of 4, i.e. normal outputs are in the range of 0 to 3 (CH1...CH4) and complementary outputs are in the range of 4 to 6 (CH1N...CH3N). If the defined output is less than 4, the normal output is enabled, otherwise the complementary output is enabled. --- cpu/stm32/periph/pwm.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/cpu/stm32/periph/pwm.c b/cpu/stm32/periph/pwm.c index 72a89eef99..09df6d210c 100644 --- a/cpu/stm32/periph/pwm.c +++ b/cpu/stm32/periph/pwm.c @@ -68,9 +68,23 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res) /* configure the used pins */ unsigned i = 0; + uint32_t ccer = 0; + while ((i < TIMER_CHANNEL_NUMOF) && (pwm_config[pwm].chan[i].pin != GPIO_UNDEF)) { gpio_init(pwm_config[pwm].chan[i].pin, GPIO_OUT); gpio_init_af(pwm_config[pwm].chan[i].pin, pwm_config[pwm].af); + if (pwm_config[pwm].chan[i].cc_chan < 4) { + /* OCx output channel used */ + ccer |= TIM_CCER_CC1E << ((pwm_config[pwm].chan[i].cc_chan) << 2); + } + else { +#ifdef TIM_CCER_CC1NE + /* OCxN complementary output channel used */ + ccer |= TIM_CCER_CC1NE << ((pwm_config[pwm].chan[i].cc_chan & 0x03) << 2); +#else + assert(false); +#endif + } i++; } @@ -102,8 +116,7 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res) #ifdef TIM_BDTR_MOE dev(pwm)->BDTR = TIM_BDTR_MOE; #endif - dev(pwm)->CCER = (TIM_CCER_CC1E | TIM_CCER_CC2E | - TIM_CCER_CC3E | TIM_CCER_CC4E); + dev(pwm)->CCER = ccer; dev(pwm)->CR1 |= TIM_CR1_CEN; /* return the actual used PWM frequency */ @@ -138,7 +151,7 @@ void pwm_set(pwm_t pwm, uint8_t channel, uint16_t value) } /* set new value */ - TIM_CHAN(pwm, pwm_config[pwm].chan[channel].cc_chan) = value; + TIM_CHAN(pwm, (pwm_config[pwm].chan[channel].cc_chan & 0x3)) = value; } void pwm_poweron(pwm_t pwm)