Skip to content

Commit ec417c7

Browse files
authored
Merge pull request #4959 from xoviat/timer
stm32: use typelevel timer type
2 parents cf6a27d + 9701382 commit ec417c7

File tree

13 files changed

+210
-208
lines changed

13 files changed

+210
-208
lines changed

embassy-stm32/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased - ReleaseDate
99

10+
- change: stm32: use typelevel timer type to allow dma for 32 bit timers
1011
- fix: fix incorrect handling of split interrupts in timer driver
1112
- feat: allow granular stop for regular usart
1213
- feat: Add continuous waveform method to SimplePWM

embassy-stm32/src/dma/word.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ pub trait Word: SealedWord + Default + Copy + 'static {
3131
fn size() -> WordSize;
3232
/// Amount of bits of this word size.
3333
fn bits() -> usize;
34+
/// Maximum value of this type.
35+
fn max() -> usize {
36+
(1 << Self::bits()) - 1
37+
}
3438
}
3539

3640
macro_rules! impl_word {

embassy-stm32/src/fmt.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,16 @@ macro_rules! error {
206206
};
207207
}
208208

209+
#[cfg(feature = "defmt")]
210+
trait_set::trait_set! {
211+
pub trait Debuggable = Debug + defmt::Format;
212+
}
213+
214+
#[cfg(not(feature = "defmt"))]
215+
trait_set::trait_set! {
216+
pub trait Debuggable = Debug;
217+
}
218+
209219
#[cfg(feature = "defmt")]
210220
#[collapse_debuginfo(yes)]
211221
macro_rules! unwrap {

embassy-stm32/src/timer/complementary_pwm.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use super::low_level::{CountingMode, OutputPolarity, Timer};
88
use super::simple_pwm::PwmPin;
99
use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, Channel, TimerComplementaryPin};
1010
use crate::Peri;
11+
use crate::dma::word::Word;
1112
use crate::gpio::{AnyPin, OutputType};
1213
use crate::time::Hertz;
1314
use crate::timer::TimerChannel;
@@ -176,20 +177,20 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
176177
/// Get max duty value.
177178
///
178179
/// This value depends on the configured frequency and the timer's clock rate from RCC.
179-
pub fn get_max_duty(&self) -> u16 {
180+
pub fn get_max_duty(&self) -> u32 {
180181
if self.inner.get_counting_mode().is_center_aligned() {
181-
self.inner.get_max_compare_value() as u16
182+
self.inner.get_max_compare_value().into()
182183
} else {
183-
self.inner.get_max_compare_value() as u16 + 1
184+
self.inner.get_max_compare_value().into() + 1
184185
}
185186
}
186187

187188
/// Set the duty for a given channel.
188189
///
189190
/// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
190-
pub fn set_duty(&mut self, channel: Channel, duty: u16) {
191+
pub fn set_duty(&mut self, channel: Channel, duty: u32) {
191192
assert!(duty <= self.get_max_duty());
192-
self.inner.set_compare_value(channel, duty as _)
193+
self.inner.set_compare_value(channel, unwrap!(duty.try_into()))
193194
}
194195

195196
/// Set the output polarity for a given channel.
@@ -220,8 +221,14 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
220221
///
221222
/// Note:
222223
/// you will need to provide corresponding TIMx_UP DMA channel to use this method.
223-
pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) {
224+
pub async fn waveform_up<W: Word + Into<T::Word>>(
225+
&mut self,
226+
dma: Peri<'_, impl super::UpDma<T>>,
227+
channel: Channel,
228+
duty: &[W],
229+
) {
224230
self.inner.enable_channel(channel, true);
231+
self.inner.clamp_compare_value::<W>(channel);
225232
self.inner.enable_update_dma(true);
226233
self.inner.setup_update_dma(dma, channel, duty).await;
227234
self.inner.enable_update_dma(false);
@@ -256,13 +263,21 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
256263
/// Also be aware that embassy timers use one of timers internally. It is possible to
257264
/// switch this timer by using `time-driver-timX` feature.
258265
///
259-
pub async fn waveform_up_multi_channel(
266+
pub async fn waveform_up_multi_channel<W: Word + Into<T::Word>>(
260267
&mut self,
261268
dma: Peri<'_, impl super::UpDma<T>>,
262269
starting_channel: Channel,
263270
ending_channel: Channel,
264-
duty: &[u16],
271+
duty: &[W],
265272
) {
273+
[Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
274+
.iter()
275+
.filter(|ch| ch.index() >= starting_channel.index())
276+
.filter(|ch| ch.index() <= ending_channel.index())
277+
.for_each(|ch| {
278+
self.inner.enable_channel(*ch, true);
279+
self.inner.clamp_compare_value::<W>(*ch);
280+
});
266281
self.inner.enable_update_dma(true);
267282
self.inner
268283
.setup_update_dma_burst(dma, starting_channel, ending_channel, duty)
@@ -291,20 +306,20 @@ impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<
291306
}
292307

293308
fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
294-
self.inner.get_compare_value(channel) as u16
309+
unwrap!(self.inner.get_compare_value(channel).try_into())
295310
}
296311

297312
fn get_max_duty(&self) -> Self::Duty {
298313
if self.inner.get_counting_mode().is_center_aligned() {
299-
self.inner.get_max_compare_value() as u16
314+
unwrap!(self.inner.get_max_compare_value().try_into())
300315
} else {
301-
self.inner.get_max_compare_value() as u16 + 1
316+
unwrap!(self.inner.get_max_compare_value().try_into()) + 1
302317
}
303318
}
304319

305320
fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
306-
assert!(duty <= self.get_max_duty());
307-
self.inner.set_compare_value(channel, duty as u32)
321+
assert!(duty <= unwrap!(self.get_max_duty().try_into()));
322+
self.inner.set_compare_value(channel, unwrap!(duty.try_into()))
308323
}
309324

310325
fn set_period<P>(&mut self, period: P)

embassy-stm32/src/timer/input_capture.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
9797

9898
/// Get capture value for a channel.
9999
pub fn get_capture_value(&self, channel: Channel) -> u32 {
100-
self.inner.get_capture_value(channel)
100+
self.inner.get_capture_value(channel).into()
101101
}
102102

103103
/// Get input interrupt.

0 commit comments

Comments
 (0)