-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
I believe this may be related to #2522 and #3704.
On an STM32H734ZIxT I've configured SimplePWM with 32-bit TIM5, a 800kHz cycle, APB1 running at 240MHz, so full duty cycle is 300.
If I use the set_duty_cycle and related methods on SimplePWM all the timing is correct on my scope.
However, one I start trying to feed it data with DMA via SimplePWM.waveform things start to go a little funny. Firstly, if I try to feed it anything in less them multiples of 2, i.e. [300], I hit the assertion from here. I understand why, but my expectation considering the waveform method takes in u16s and the PR linked above was that it would handle the data differences.
To actually get correct waveforms out of it, I need to pad them with 0's, i.e. [300, 0, 150, 0] for 1 full duty cycle, and then one half cycle:
// Configure the pin to PWM
let pwm_pin = PwmPin::new(p.PA3, OutputType::PushPull);
// Given this system frequency and pwm frequency the max duty cycle will be 300.
let mut pwm = SimplePwm::new(
TIM5,
None,
None,
None,
Some(pwm_pin),
// PWM_FREQ = 1 / data_transfer_time = 1 / 1.25us = 800kHz
Hertz::khz(800),
CountingMode::EdgeAlignedUp,
);
// Enable the channel corresponding to the PWM channel above.
let mut pwm_channel = pwm.ch4();
pwm_channel.enable();
// Make sure PWM output keep low on first start.
//
// This duty cycle is reset to after the DMA waveform has been transmitted.
pwm_channel.set_duty_cycle(0);
let mut led_dma = p.DMA2_CH4;
let duty = &[300, 0, 0, 0, 150, 0, 0, 0];
loop {
pwm.waveform::<embassy_stm32::timer::Ch4>(led_dma.reborrow(), duty)
.await;
Timer::after_millis(600).await;
}If anything is written in the second half-word, then the timing becomes really strange - a fairly consistent 30us cycle time, followed by a consistent 80us gap.