mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge #19572
19572: cpu/stm32/periph_pwm: support of complementary timer outputs r=maribu a=gschorcht ### Contribution description This PR provides the support of complementary timer outputs as PWM channels for advanced timers (TIM1/TIM8). 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. This change is required to support PWM on boards that have connected the complementary outputs of advanced timers to the PWM connector pins, for example the STM32L496-DISCO board. ### Testing procedure - Green CI - Use any STM32 board which supports the `periph_pwm` feature. `tests/periph_pwm` should still work. - Change the configuration for this board so that either timer TIM1 or TIM8 and a complementary channel is used for any exposed GPIO. `tests/periph_pwm` should also work with such a configuration. ### Issues/PRs references Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
This commit is contained in:
commit
f47003c1db
@ -33,10 +33,21 @@ extern "C" {
|
||||
|
||||
/**
|
||||
* @brief PWM channel
|
||||
*
|
||||
* When using a general-purpose timer for a PWM device, the outputs OC<n> of
|
||||
* each of the four capture/compare channels can be used as PWM channel.
|
||||
* The respective capture/compare channel is then specified with 0...3 in
|
||||
* `cc_chan` for the outputs OC1...OC4.
|
||||
*
|
||||
* Advanced timers like TIM1 and TIM8 have additionally three complementary
|
||||
* outputs OC<n>N of the capture/compare channels, which can also be used
|
||||
* as PWM channels. These complementary outputs are defined with an offset
|
||||
* of 4, i.e. they are specified in `cc_chan` with 4...6 for OC1N...OC3N.
|
||||
*/
|
||||
typedef struct {
|
||||
gpio_t pin; /**< GPIO pin mapped to this channel */
|
||||
uint8_t cc_chan; /**< capture compare channel used */
|
||||
uint8_t cc_chan; /**< Capture/compare channel used: 0..3 for OC1..OC4
|
||||
or 4..6 for OC1N..OC3N for advanced timers */
|
||||
} pwm_chan_t;
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user