cpu/stm32_common: consider timer multiplier for PWM
This commit is contained in:
parent
09a8a83c80
commit
ebd525306a
@ -24,6 +24,28 @@
|
|||||||
#define ENABLE_DEBUG (0)
|
#define ENABLE_DEBUG (0)
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Timer specific additional bus clock prescaler
|
||||||
|
*
|
||||||
|
* This prescale factor is dependent on the actual APBx bus clock divider, if
|
||||||
|
* the APBx presacler is != 1, it is set to 2, if the APBx prescaler is == 1, it
|
||||||
|
* is set to 1.
|
||||||
|
*
|
||||||
|
* See reference manuals section 'reset and clock control'.
|
||||||
|
*/
|
||||||
|
static const uint8_t apbmul[] = {
|
||||||
|
#if (CLOCK_APB1 < CLOCK_CORECLOCK)
|
||||||
|
[APB1] = 2,
|
||||||
|
#else
|
||||||
|
[APB1] = 1,
|
||||||
|
#endif
|
||||||
|
#if (CLOCK_APB2 < CLOCK_CORECLOCK)
|
||||||
|
[APB2] = 2
|
||||||
|
#else
|
||||||
|
[APB2] = 1
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
uint32_t periph_apb_clk(uint8_t bus)
|
uint32_t periph_apb_clk(uint8_t bus)
|
||||||
{
|
{
|
||||||
if (bus == APB1) {
|
if (bus == APB1) {
|
||||||
@ -34,6 +56,11 @@ uint32_t periph_apb_clk(uint8_t bus)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t periph_timer_clk(uint8_t bus)
|
||||||
|
{
|
||||||
|
return periph_apb_clk(bus) * apbmul[bus];
|
||||||
|
}
|
||||||
|
|
||||||
void periph_clk_en(bus_t bus, uint32_t mask)
|
void periph_clk_en(bus_t bus, uint32_t mask)
|
||||||
{
|
{
|
||||||
switch (bus) {
|
switch (bus) {
|
||||||
|
|||||||
@ -297,6 +297,15 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
uint32_t periph_apb_clk(uint8_t bus);
|
uint32_t periph_apb_clk(uint8_t bus);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the actual timer clock frequency
|
||||||
|
*
|
||||||
|
* @param[in] bus corresponding APBx bus
|
||||||
|
*
|
||||||
|
* @return timer clock frequency in Hz
|
||||||
|
*/
|
||||||
|
uint32_t periph_timer_clk(uint8_t bus);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enable the given peripheral clock
|
* @brief Enable the given peripheral clock
|
||||||
*
|
*
|
||||||
|
|||||||
@ -42,10 +42,10 @@ static inline TIM_TypeDef *dev(pwm_t pwm)
|
|||||||
|
|
||||||
uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
||||||
{
|
{
|
||||||
uint32_t bus_clk = periph_apb_clk(pwm_config[pwm].bus);
|
uint32_t timer_clk = periph_timer_clk(pwm_config[pwm].bus);
|
||||||
|
|
||||||
/* verify parameters */
|
/* verify parameters */
|
||||||
assert((pwm < PWM_NUMOF) && ((freq * res) < bus_clk));
|
assert((pwm < PWM_NUMOF) && ((freq * res) < timer_clk));
|
||||||
|
|
||||||
/* power on the used timer */
|
/* power on the used timer */
|
||||||
periph_clk_en(pwm_config[pwm].bus, pwm_config[pwm].rcc_mask);
|
periph_clk_en(pwm_config[pwm].bus, pwm_config[pwm].rcc_mask);
|
||||||
@ -66,7 +66,7 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
|||||||
|
|
||||||
/* configure the PWM frequency and resolution by setting the auto-reload
|
/* configure the PWM frequency and resolution by setting the auto-reload
|
||||||
* and prescaler registers */
|
* and prescaler registers */
|
||||||
dev(pwm)->PSC = (bus_clk / (res * freq)) - 1;
|
dev(pwm)->PSC = (timer_clk / (res * freq)) - 1;
|
||||||
dev(pwm)->ARR = res - 1;
|
dev(pwm)->ARR = res - 1;
|
||||||
|
|
||||||
/* set PWM mode */
|
/* set PWM mode */
|
||||||
@ -95,7 +95,7 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
|||||||
dev(pwm)->CR1 |= TIM_CR1_CEN;
|
dev(pwm)->CR1 |= TIM_CR1_CEN;
|
||||||
|
|
||||||
/* return the actual used PWM frequency */
|
/* return the actual used PWM frequency */
|
||||||
return (bus_clk / (res * (dev(pwm)->PSC + 1)));
|
return (timer_clk / (res * (dev(pwm)->PSC + 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t pwm_channels(pwm_t pwm)
|
uint8_t pwm_channels(pwm_t pwm)
|
||||||
|
|||||||
@ -23,28 +23,6 @@
|
|||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "periph/timer.h"
|
#include "periph/timer.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Timer specific additional bus clock presacler
|
|
||||||
*
|
|
||||||
* This prescale factor is dependent on the actual APBx bus clock divider, if
|
|
||||||
* the APBx presacler is != 1, it is set to 2, if the APBx prescaler is == 1, it
|
|
||||||
* is set to 1.
|
|
||||||
*
|
|
||||||
* See reference manuals section 'reset and clock control'.
|
|
||||||
*/
|
|
||||||
static const uint8_t apbmul[] = {
|
|
||||||
#if (CLOCK_APB1 < CLOCK_CORECLOCK)
|
|
||||||
[APB1] = 2,
|
|
||||||
#else
|
|
||||||
[APB1] = 1,
|
|
||||||
#endif
|
|
||||||
#if (CLOCK_APB2 < CLOCK_CORECLOCK)
|
|
||||||
[APB2] = 2
|
|
||||||
#else
|
|
||||||
[APB2] = 1
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Interrupt context for each configured timer
|
* @brief Interrupt context for each configured timer
|
||||||
*/
|
*/
|
||||||
@ -78,8 +56,7 @@ int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg)
|
|||||||
dev(tim)->ARR = timer_config[tim].max;
|
dev(tim)->ARR = timer_config[tim].max;
|
||||||
|
|
||||||
/* set prescaler */
|
/* set prescaler */
|
||||||
dev(tim)->PSC = (((periph_apb_clk(timer_config[tim].bus) *
|
dev(tim)->PSC = ((periph_timer_clk(timer_config[tim].bus) / freq) - 1);
|
||||||
apbmul[timer_config[tim].bus]) / freq) - 1);
|
|
||||||
/* generate an update event to apply our configuration */
|
/* generate an update event to apply our configuration */
|
||||||
dev(tim)->EGR = TIM_EGR_UG;
|
dev(tim)->EGR = TIM_EGR_UG;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user