stm32-rs / stm32f3xx-hal

A Rust embedded-hal HAL for all MCUs in the STM32 F3 family
https://crates.io/crates/stm32f3xx-hal
Apache License 2.0
164 stars 67 forks source link

[Bug] Incorrect pwm frequency #205

Open mstumbra opened 3 years ago

mstumbra commented 3 years ago

tim1(dp.TIM1, 144, 1.mhz().into(), &clocks) leads to actual timer frequency of 0.5 MHz, as code doesn't set/takes into account tim1sw bit in RCC CFGR3 register Same thing with other timers and possibly peripherals most likely. (Occurs only when MCU is running with max frequency)

David-OConnor commented 3 years ago

Note that center align modes will also cause incorrect freqs.

Sh3Rm4n commented 3 years ago

I have not had the time to dig into the PWM issues / PRs yet, but can this possible resolved or improved by https://github.com/stm32-rs/stm32f3xx-hal/pull/196?

Piroro-hs commented 3 years ago

Looks like current PWM and Timer implementation is wrong at source clock calculation. https://github.com/stm32-rs/stm32f3xx-hal/blob/f8eb2926a38c9a40c41ba53de60839ac25d78f6e/src/pwm.rs#L283-L284

David-OConnor commented 3 years ago

As in, some timers use apb1 while others use apb2? Here's how I solved it, where paste is a macro crate that lets you build identifiers from parts, $apb is apb1 or apb2, and the apb1_timer() and apb2_timer() are traits the clocks struct implements. (Ie that calculation line is moved to the clock functionality; the timer module determines which to use, apb1 or apb2.)

paste! {
    let mut timer = Timer { clock_speed: clocks.[<$apb _timer>](), tim };
    // ...
}

Example trait implementation:

    fn apb2_timer(&self) -> u32 {
        if let ApbPrescaler::Div1 = self.apb2_prescaler {
            self.apb2()
        } else {
            self.apb2() * 2
        }
    }