TIM8 not working in PWM Mode 1 on STM32G474RETx
gueldenstone opened this issue · comments
Hi everyone,
Disclaimer: I'm very new to rust, so there might be an obvious thing I did wrong. Sorry in advance.
I just tried to port a project from C++ to rust using this library and the STM32G474RE on the NUCLEO Board.
In the C/C++ project I used Timer8 with PA15 in AF2 as positive output. This does not seem to work with this library.
I tested the Pin working with Timer2 and the PA15 in AF1 mode. Is this a bug, or am I getting something wrong. Below you can find a copy of my main.rs of reference:
#![no_std]
#![no_main]
use core::panic::PanicInfo;
use cortex_m::delay::Delay;
use cortex_m_rt::entry; // The runtime
use stm32_hal2::{
clocks::{ApbPrescaler, Clk48Src, Clocks, HclkPrescaler, InputSrc, PllCfg, PllSrc, Pllm, Pllr},
gpio::{Pin, PinMode, Port},
pac,
timer::{OutputCompare, TimChannel, Timer, TimerConfig},
};
use defmt_rtt as _;
// This marks the entrypoint of our application. The cortex_m_rt creates some
// startup code before this, but we don't need to worry about this
#[entry]
fn main() -> ! {
// CPU Peripherals
let cp = cortex_m::Peripherals::take().unwrap();
// MCU Peripherals
let dp = pac::Peripherals::take().unwrap();
defmt::println!("Hello, world!");
let clock_cfg = Clocks {
input_src: InputSrc::Pll(PllSrc::Hse(24_000_000)),
pll: PllCfg {
enabled: true,
divm: Pllm::Div3,
divn: 20,
divp: Pllr::Div2,
pllp_en: false,
divr: Pllr::Div2,
pllr_en: true,
divq: Pllr::Div2,
pllq_en: false,
},
hclk_prescaler: HclkPrescaler::Div1,
apb1_prescaler: ApbPrescaler::Div1,
apb2_prescaler: ApbPrescaler::Div1,
clk48_src: Clk48Src::Hsi48,
hse_bypass: false,
hsi48_on: true,
security_system: true,
};
// Write the clock configuration to the MCU. If you wish, you can modify `clocks` above
// in accordance with [its docs](https://docs.rs/stm32-hal2/0.2.0/stm32_hal2/clocks/index.html),
// and the `clock_cfg` example.
clock_cfg.setup().unwrap();
// setup timer
let _pwm_pin = Pin::new(Port::A, 15, PinMode::Alt(2));
let mut pwm = Timer::new_tim8(
dp.TIM8,
1000.,
TimerConfig {
auto_reload_preload: true,
..Default::default()
},
&clock_cfg,
);
pwm.enable_pwm_output(TimChannel::C1, OutputCompare::Pwm1, 0.5);
pwm.enable();
// Setup a delay, based on the Cortex-m systick.
let mut delay = Delay::new(cp.SYST, clock_cfg.systick());
let mut led = Pin::new(Port::A, 5, PinMode::Output);
let mut duty = 0.0;
let period = pwm.get_max_duty();
// Now, enjoy the lightshow!
loop {
defmt::debug!("Our demo is alive");
led.set_low();
delay.delay_ms(100_u32);
duty += 0.01;
pwm.set_duty(TimChannel::C1, (duty * period as f64) as u16);
if duty >= 1. {
duty = 0.;
}
led.set_high();
delay.delay_ms(100_u32);
}
}
// same panicking *behavior* as `panic-probe` but doesn't print a panic message
// this prevents the panic message being printed *twice* when `defmt::panic` is invoked
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
cortex_m::asm::udf()
}
/// Terminates the application and makes `probe-run` exit with exit-code = 0
pub fn exit() -> ! {
loop {
cortex_m::asm::bkpt();
}
}
Also: Is there a way to enable the negative Output for the timers?
Looks like a bug, but I don't know the cause yet.
To set negative output, I think you're looking for the .set_complementary_polarity()
method on the Timer
struct. This sets the ccxnp
fields on the CCER
register. Is this what you're looking for?
Does the Timer 2 / AF1 setting you use work correctly?
Just fixed a bug with Channels 2-4 PWM output. Were you using one of those (Example shows 1).
Closing due to lack of response. Possibly fixed in PWM-related fixes pushed yesterday.