diff --git a/src/drivers/stm32/drv_led_pwm.cpp b/src/drivers/stm32/drv_led_pwm.cpp index ea3dff17b2..5a2cff8dc7 100644 --- a/src/drivers/stm32/drv_led_pwm.cpp +++ b/src/drivers/stm32/drv_led_pwm.cpp @@ -63,6 +63,15 @@ #if defined(BOARD_HAS_LED_PWM) + +/* Board can override rate */ + +#if (BOARD_LED_PWM_RATE) +# define LED_PWM_RATE BOARD_LED_PWM_RATE +#else +# define LED_PWM_RATE 50 +#endif + #define REG(_tmr, _reg) (*(volatile uint32_t *)(led_pwm_timers[_tmr].base + _reg)) #define rCR1(_tmr) REG(_tmr, STM32_GTIM_CR1_OFFSET) @@ -104,6 +113,56 @@ led_pwm_timer_get_period(unsigned timer) return (rARR(timer)); } +#if !defined(BOARD_HAS_SHARED_PWM_TIMERS) + +static void led_pwm_timer_init_timer(unsigned timer) +{ + irqstate_t flags = px4_enter_critical_section(); + + /* enable the timer clock before we try to talk to it */ + + modifyreg32(led_pwm_timers[timer].clock_register, 0, led_pwm_timers[timer].clock_bit); + + /* disable and configure the timer */ + rCR1(timer) = 0; + rCR2(timer) = 0; + rSMCR(timer) = 0; + rDIER(timer) = 0; + rCCER(timer) = 0; + rCCMR1(timer) = 0; + rCCMR2(timer) = 0; + rCCR1(timer) = 0; + rCCR2(timer) = 0; + rCCR3(timer) = 0; + rCCR4(timer) = 0; + rCCER(timer) = 0; + rDCR(timer) = 0; + + if ((led_pwm_timers[timer].base == STM32_TIM1_BASE) || (led_pwm_timers[timer].base == STM32_TIM8_BASE)) { + + /* master output enable = on */ + + rBDTR(timer) = ATIM_BDTR_MOE; + } + + /* If the timer clock source provided as clock_freq is the STM32_APBx_TIMx_CLKIN + * then configure the timer to free-run at 1MHz. + * Otherwize, other frequencies are attainable by adjusting .clock_freq accordingly. + */ + + rPSC(timer) = (led_pwm_timers[timer].clock_freq / 1000000) - 1; + + /* configure the timer to update at the desired rate */ + + rARR(timer) = 1000000 / LED_PWM_RATE; + + /* generate an update event; reloads the counter and all registers */ + rEGR(timer) = GTIM_EGR_UG; + + px4_leave_critical_section(flags); + +} +#endif static void led_pwm_channel_init(unsigned channel) @@ -233,7 +292,11 @@ led_pwm_servo_init(void) { /* do basic timer initialisation first */ for (unsigned i = 0; i < arraySize(led_pwm_timers); i++) { +#if defined(BOARD_HAS_SHARED_PWM_TIMERS) io_timer_init_timer(i); +#else + led_pwm_timer_init_timer(i); +#endif } /* now init channels */