diff options
| author | xoviat <[email protected]> | 2025-11-27 11:29:24 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2025-11-27 11:29:24 -0600 |
| commit | 790940a18c093fb7c7f94585be81d7d02892b4fb (patch) | |
| tree | c3f90441ca4b7581ede46240c3a8ccc2c4462a59 /embassy-stm32 | |
| parent | b8afe4ff5fd590903861e44224171f37b9ae6e62 (diff) | |
stm32: use typelevel timer type
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/CHANGELOG.md | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/fmt.rs | 10 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/complementary_pwm.rs | 18 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/input_capture.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/low_level.rs | 191 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/mod.rs | 30 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/one_pulse.rs | 12 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/pwm_input.rs | 14 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/ringbuffered.rs | 12 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/simple_pwm.rs | 16 |
10 files changed, 138 insertions, 168 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 4c38b0add..13c95b60a 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md | |||
| @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 7 | 7 | ||
| 8 | ## Unreleased - ReleaseDate | 8 | ## Unreleased - ReleaseDate |
| 9 | 9 | ||
| 10 | - change: stm32: use typelevel timer type to allow dma for 32 bit timers | ||
| 10 | - fix: fix incorrect handling of split interrupts in timer driver | 11 | - fix: fix incorrect handling of split interrupts in timer driver |
| 11 | - feat: allow granular stop for regular usart | 12 | - feat: allow granular stop for regular usart |
| 12 | - feat: Add continuous waveform method to SimplePWM | 13 | - feat: Add continuous waveform method to SimplePWM |
diff --git a/embassy-stm32/src/fmt.rs b/embassy-stm32/src/fmt.rs index b6ae24ee8..b731796f0 100644 --- a/embassy-stm32/src/fmt.rs +++ b/embassy-stm32/src/fmt.rs | |||
| @@ -207,6 +207,16 @@ macro_rules! error { | |||
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | #[cfg(feature = "defmt")] | 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 | |||
| 219 | #[cfg(feature = "defmt")] | ||
| 210 | #[collapse_debuginfo(yes)] | 220 | #[collapse_debuginfo(yes)] |
| 211 | macro_rules! unwrap { | 221 | macro_rules! unwrap { |
| 212 | ($($x:tt)*) => { | 222 | ($($x:tt)*) => { |
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 77f19a37b..d194899c6 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs | |||
| @@ -178,9 +178,9 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { | |||
| 178 | /// This value depends on the configured frequency and the timer's clock rate from RCC. | 178 | /// This value depends on the configured frequency and the timer's clock rate from RCC. |
| 179 | pub fn get_max_duty(&self) -> u16 { | 179 | pub fn get_max_duty(&self) -> u16 { |
| 180 | if self.inner.get_counting_mode().is_center_aligned() { | 180 | if self.inner.get_counting_mode().is_center_aligned() { |
| 181 | self.inner.get_max_compare_value() as u16 | 181 | unwrap!(self.inner.get_max_compare_value().try_into()) |
| 182 | } else { | 182 | } else { |
| 183 | self.inner.get_max_compare_value() as u16 + 1 | 183 | unwrap!(self.inner.get_max_compare_value().try_into()) + 1 |
| 184 | } | 184 | } |
| 185 | } | 185 | } |
| 186 | 186 | ||
| @@ -189,7 +189,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { | |||
| 189 | /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. | 189 | /// 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) { | 190 | pub fn set_duty(&mut self, channel: Channel, duty: u16) { |
| 191 | assert!(duty <= self.get_max_duty()); | 191 | assert!(duty <= self.get_max_duty()); |
| 192 | self.inner.set_compare_value(channel, duty as _) | 192 | self.inner.set_compare_value(channel, duty.into()) |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | /// Set the output polarity for a given channel. | 195 | /// Set the output polarity for a given channel. |
| @@ -220,7 +220,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { | |||
| 220 | /// | 220 | /// |
| 221 | /// Note: | 221 | /// Note: |
| 222 | /// you will need to provide corresponding TIMx_UP DMA channel to use this method. | 222 | /// 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]) { | 223 | pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[T::Word]) { |
| 224 | self.inner.enable_channel(channel, true); | 224 | self.inner.enable_channel(channel, true); |
| 225 | self.inner.enable_update_dma(true); | 225 | self.inner.enable_update_dma(true); |
| 226 | self.inner.setup_update_dma(dma, channel, duty).await; | 226 | self.inner.setup_update_dma(dma, channel, duty).await; |
| @@ -261,7 +261,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { | |||
| 261 | dma: Peri<'_, impl super::UpDma<T>>, | 261 | dma: Peri<'_, impl super::UpDma<T>>, |
| 262 | starting_channel: Channel, | 262 | starting_channel: Channel, |
| 263 | ending_channel: Channel, | 263 | ending_channel: Channel, |
| 264 | duty: &[u16], | 264 | duty: &[T::Word], |
| 265 | ) { | 265 | ) { |
| 266 | self.inner.enable_update_dma(true); | 266 | self.inner.enable_update_dma(true); |
| 267 | self.inner | 267 | self.inner |
| @@ -291,20 +291,20 @@ impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm< | |||
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | fn get_duty(&self, channel: Self::Channel) -> Self::Duty { | 293 | fn get_duty(&self, channel: Self::Channel) -> Self::Duty { |
| 294 | self.inner.get_compare_value(channel) as u16 | 294 | unwrap!(self.inner.get_compare_value(channel).try_into()) |
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | fn get_max_duty(&self) -> Self::Duty { | 297 | fn get_max_duty(&self) -> Self::Duty { |
| 298 | if self.inner.get_counting_mode().is_center_aligned() { | 298 | if self.inner.get_counting_mode().is_center_aligned() { |
| 299 | self.inner.get_max_compare_value() as u16 | 299 | unwrap!(self.inner.get_max_compare_value().try_into()) |
| 300 | } else { | 300 | } else { |
| 301 | self.inner.get_max_compare_value() as u16 + 1 | 301 | unwrap!(self.inner.get_max_compare_value().try_into()) + 1 |
| 302 | } | 302 | } |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { | 305 | fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { |
| 306 | assert!(duty <= self.get_max_duty()); | 306 | assert!(duty <= self.get_max_duty()); |
| 307 | self.inner.set_compare_value(channel, duty as u32) | 307 | self.inner.set_compare_value(channel, unwrap!(duty.try_into())) |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | fn set_period<P>(&mut self, period: P) | 310 | fn set_period<P>(&mut self, period: P) |
diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index 9cf0f8c34..3e1482b67 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs | |||
| @@ -97,7 +97,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { | |||
| 97 | 97 | ||
| 98 | /// Get capture value for a channel. | 98 | /// Get capture value for a channel. |
| 99 | pub fn get_capture_value(&self, channel: Channel) -> u32 { | 99 | pub fn get_capture_value(&self, channel: Channel) -> u32 { |
| 100 | self.inner.get_capture_value(channel) | 100 | self.inner.get_capture_value(channel).into() |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | /// Get input interrupt. | 103 | /// Get input interrupt. |
diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index aba08081f..73a81bff1 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs | |||
| @@ -268,6 +268,11 @@ impl<'d, T: CoreInstance> Timer<'d, T> { | |||
| 268 | unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } | 268 | unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | #[cfg(stm32l0)] | ||
| 272 | fn regs_gp32_unchecked(&self) -> crate::pac::timer::TimGp16 { | ||
| 273 | unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) } | ||
| 274 | } | ||
| 275 | |||
| 271 | /// Start the timer. | 276 | /// Start the timer. |
| 272 | pub fn start(&self) { | 277 | pub fn start(&self) { |
| 273 | self.regs_core().cr1().modify(|r| r.set_cen(true)); | 278 | self.regs_core().cr1().modify(|r| r.set_cen(true)); |
| @@ -296,7 +301,12 @@ impl<'d, T: CoreInstance> Timer<'d, T> { | |||
| 296 | 301 | ||
| 297 | /// get the capability of the timer | 302 | /// get the capability of the timer |
| 298 | pub fn bits(&self) -> TimerBits { | 303 | pub fn bits(&self) -> TimerBits { |
| 299 | T::BITS | 304 | match T::Word::bits() { |
| 305 | 16 => TimerBits::Bits16, | ||
| 306 | #[cfg(not(stm32l0))] | ||
| 307 | 32 => TimerBits::Bits32, | ||
| 308 | _ => unreachable!(), | ||
| 309 | } | ||
| 300 | } | 310 | } |
| 301 | 311 | ||
| 302 | /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. | 312 | /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. |
| @@ -306,18 +316,10 @@ impl<'d, T: CoreInstance> Timer<'d, T> { | |||
| 306 | /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved | 316 | /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved |
| 307 | /// because it needs to count up and down. | 317 | /// because it needs to count up and down. |
| 308 | pub fn set_frequency(&self, frequency: Hertz) { | 318 | pub fn set_frequency(&self, frequency: Hertz) { |
| 309 | match T::BITS { | 319 | self.set_frequency_internal(frequency, T::Word::bits()); |
| 310 | TimerBits::Bits16 => { | ||
| 311 | self.set_frequency_internal(frequency, 16); | ||
| 312 | } | ||
| 313 | #[cfg(not(stm32l0))] | ||
| 314 | TimerBits::Bits32 => { | ||
| 315 | self.set_frequency_internal(frequency, 32); | ||
| 316 | } | ||
| 317 | } | ||
| 318 | } | 320 | } |
| 319 | 321 | ||
| 320 | pub(crate) fn set_frequency_internal(&self, frequency: Hertz, max_divide_by_bits: u8) { | 322 | pub(crate) fn set_frequency_internal(&self, frequency: Hertz, max_divide_by_bits: usize) { |
| 321 | let f = frequency.0; | 323 | let f = frequency.0; |
| 322 | assert!(f > 0); | 324 | assert!(f > 0); |
| 323 | let timer_f = T::frequency().0; | 325 | let timer_f = T::frequency().0; |
| @@ -326,25 +328,15 @@ impl<'d, T: CoreInstance> Timer<'d, T> { | |||
| 326 | let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << max_divide_by_bits)).try_into()); | 328 | let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << max_divide_by_bits)).try_into()); |
| 327 | let divide_by = pclk_ticks_per_timer_period / (u64::from(psc) + 1); | 329 | let divide_by = pclk_ticks_per_timer_period / (u64::from(psc) + 1); |
| 328 | 330 | ||
| 329 | match T::BITS { | 331 | // the timer counts `0..=arr`, we want it to count `0..divide_by` |
| 330 | TimerBits::Bits16 => { | 332 | let arr: T::Word = unwrap!(T::Word::try_from(divide_by - 1)); |
| 331 | // the timer counts `0..=arr`, we want it to count `0..divide_by` | ||
| 332 | let arr = unwrap!(u16::try_from(divide_by - 1)); | ||
| 333 | |||
| 334 | let regs = self.regs_core(); | ||
| 335 | regs.psc().write_value(psc); | ||
| 336 | regs.arr().write(|r| r.set_arr(arr)); | ||
| 337 | } | ||
| 338 | #[cfg(not(stm32l0))] | ||
| 339 | TimerBits::Bits32 => { | ||
| 340 | // the timer counts `0..=arr`, we want it to count `0..divide_by` | ||
| 341 | let arr: u32 = unwrap!(u32::try_from(divide_by - 1)); | ||
| 342 | 333 | ||
| 343 | let regs = self.regs_gp32_unchecked(); | 334 | let regs = self.regs_gp32_unchecked(); |
| 344 | regs.psc().write_value(psc); | 335 | regs.psc().write_value(psc); |
| 345 | regs.arr().write_value(arr); | 336 | #[cfg(stm32l0)] |
| 346 | } | 337 | regs.arr().write(|r| r.set_arr(unwrap!(arr.try_into()))); |
| 347 | } | 338 | #[cfg(not(stm32l0))] |
| 339 | regs.arr().write_value(arr.into()); | ||
| 348 | } | 340 | } |
| 349 | 341 | ||
| 350 | /// Set tick frequency. | 342 | /// Set tick frequency. |
| @@ -393,23 +385,14 @@ impl<'d, T: CoreInstance> Timer<'d, T> { | |||
| 393 | pub fn get_frequency(&self) -> Hertz { | 385 | pub fn get_frequency(&self) -> Hertz { |
| 394 | let timer_f = T::frequency(); | 386 | let timer_f = T::frequency(); |
| 395 | 387 | ||
| 396 | match T::BITS { | 388 | let regs = self.regs_gp32_unchecked(); |
| 397 | TimerBits::Bits16 => { | 389 | #[cfg(not(stm32l0))] |
| 398 | let regs = self.regs_core(); | 390 | let arr = regs.arr().read(); |
| 399 | let arr = regs.arr().read().arr(); | 391 | #[cfg(stm32l0)] |
| 400 | let psc = regs.psc().read(); | 392 | let arr = regs.arr().read().arr(); |
| 393 | let psc = regs.psc().read(); | ||
| 401 | 394 | ||
| 402 | timer_f / arr / (psc + 1) | 395 | timer_f / arr / (psc + 1) |
| 403 | } | ||
| 404 | #[cfg(not(stm32l0))] | ||
| 405 | TimerBits::Bits32 => { | ||
| 406 | let regs = self.regs_gp32_unchecked(); | ||
| 407 | let arr = regs.arr().read(); | ||
| 408 | let psc = regs.psc().read(); | ||
| 409 | |||
| 410 | timer_f / arr / (psc + 1) | ||
| 411 | } | ||
| 412 | } | ||
| 413 | } | 396 | } |
| 414 | 397 | ||
| 415 | /// Get the clock frequency of the timer (before prescaler is applied). | 398 | /// Get the clock frequency of the timer (before prescaler is applied). |
| @@ -469,42 +452,29 @@ impl<'d, T: GeneralInstance1Channel> Timer<'d, T> { | |||
| 469 | } | 452 | } |
| 470 | 453 | ||
| 471 | /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. | 454 | /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. |
| 472 | pub fn get_max_compare_value(&self) -> u32 { | 455 | pub fn get_max_compare_value(&self) -> T::Word { |
| 473 | match T::BITS { | 456 | #[cfg(not(stm32l0))] |
| 474 | TimerBits::Bits16 => self.regs_1ch().arr().read().arr() as u32, | 457 | return unwrap!(self.regs_gp32_unchecked().arr().read().try_into()); |
| 475 | #[cfg(not(stm32l0))] | 458 | #[cfg(stm32l0)] |
| 476 | TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(), | 459 | return unwrap!(self.regs_gp32_unchecked().arr().read().arr().try_into()); |
| 477 | } | ||
| 478 | } | 460 | } |
| 479 | 461 | ||
| 480 | /// Set the max compare value. | 462 | /// Set the max compare value. |
| 481 | /// | 463 | /// |
| 482 | /// An update event is generated to load the new value. The update event is | 464 | /// An update event is generated to load the new value. The update event is |
| 483 | /// generated such that it will not cause an interrupt or DMA request. | 465 | /// generated such that it will not cause an interrupt or DMA request. |
| 484 | pub fn set_max_compare_value(&self, ticks: u32) { | 466 | pub fn set_max_compare_value(&self, ticks: T::Word) { |
| 485 | match T::BITS { | 467 | let arr = ticks; |
| 486 | TimerBits::Bits16 => { | ||
| 487 | let arr = unwrap!(u16::try_from(ticks)); | ||
| 488 | 468 | ||
| 489 | let regs = self.regs_1ch(); | 469 | let regs = self.regs_gp32_unchecked(); |
| 490 | regs.arr().write(|r| r.set_arr(arr)); | 470 | #[cfg(not(stm32l0))] |
| 471 | regs.arr().write_value(arr.into()); | ||
| 472 | #[cfg(stm32l0)] | ||
| 473 | regs.arr().write(|r| r.set_arr(unwrap!(arr.try_into()))); | ||
| 491 | 474 | ||
| 492 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY)); | 475 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY)); |
| 493 | regs.egr().write(|r| r.set_ug(true)); | 476 | regs.egr().write(|r| r.set_ug(true)); |
| 494 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT)); | 477 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT)); |
| 495 | } | ||
| 496 | #[cfg(not(stm32l0))] | ||
| 497 | TimerBits::Bits32 => { | ||
| 498 | let arr = ticks; | ||
| 499 | |||
| 500 | let regs = self.regs_gp32_unchecked(); | ||
| 501 | regs.arr().write_value(arr); | ||
| 502 | |||
| 503 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY)); | ||
| 504 | regs.egr().write(|r| r.set_ug(true)); | ||
| 505 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT)); | ||
| 506 | } | ||
| 507 | } | ||
| 508 | } | 478 | } |
| 509 | } | 479 | } |
| 510 | 480 | ||
| @@ -638,26 +608,23 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 638 | } | 608 | } |
| 639 | 609 | ||
| 640 | /// Set compare value for a channel. | 610 | /// Set compare value for a channel. |
| 641 | pub fn set_compare_value(&self, channel: Channel, value: u32) { | 611 | pub fn set_compare_value(&self, channel: Channel, value: T::Word) { |
| 642 | match T::BITS { | 612 | #[cfg(not(stm32l0))] |
| 643 | TimerBits::Bits16 => { | 613 | self.regs_gp32_unchecked() |
| 644 | let value = unwrap!(u16::try_from(value)); | 614 | .ccr(channel.index()) |
| 645 | self.regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); | 615 | .write_value(value.into()); |
| 646 | } | 616 | #[cfg(stm32l0)] |
| 647 | #[cfg(not(stm32l0))] | 617 | self.regs_gp16() |
| 648 | TimerBits::Bits32 => { | 618 | .ccr(channel.index()) |
| 649 | self.regs_gp32_unchecked().ccr(channel.index()).write_value(value); | 619 | .modify(|w| w.set_ccr(unwrap!(value.try_into()))); |
| 650 | } | ||
| 651 | } | ||
| 652 | } | 620 | } |
| 653 | 621 | ||
| 654 | /// Get compare value for a channel. | 622 | /// Get compare value for a channel. |
| 655 | pub fn get_compare_value(&self, channel: Channel) -> u32 { | 623 | pub fn get_compare_value(&self, channel: Channel) -> T::Word { |
| 656 | match T::BITS { | 624 | #[cfg(not(stm32l0))] |
| 657 | TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32, | 625 | return unwrap!(self.regs_gp32_unchecked().ccr(channel.index()).read().try_into()); |
| 658 | #[cfg(not(stm32l0))] | 626 | #[cfg(stm32l0)] |
| 659 | TimerBits::Bits32 => self.regs_gp32_unchecked().ccr(channel.index()).read(), | 627 | return unwrap!(self.regs_gp32_unchecked().ccr(channel.index()).read().ccr().try_into()); |
| 660 | } | ||
| 661 | } | 628 | } |
| 662 | 629 | ||
| 663 | /// Setup a ring buffer for the channel | 630 | /// Setup a ring buffer for the channel |
| @@ -665,8 +632,8 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 665 | &mut self, | 632 | &mut self, |
| 666 | dma: Peri<'a, impl super::UpDma<T>>, | 633 | dma: Peri<'a, impl super::UpDma<T>>, |
| 667 | channel: Channel, | 634 | channel: Channel, |
| 668 | dma_buf: &'a mut [u16], | 635 | dma_buf: &'a mut [T::Word], |
| 669 | ) -> WritableRingBuffer<'a, u16> { | 636 | ) -> WritableRingBuffer<'a, T::Word> { |
| 670 | #[allow(clippy::let_unit_value)] // eg. stm32f334 | 637 | #[allow(clippy::let_unit_value)] // eg. stm32f334 |
| 671 | let req = dma.request(); | 638 | let req = dma.request(); |
| 672 | 639 | ||
| @@ -686,7 +653,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 686 | WritableRingBuffer::new( | 653 | WritableRingBuffer::new( |
| 687 | dma, | 654 | dma, |
| 688 | req, | 655 | req, |
| 689 | self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, | 656 | self.regs_1ch().ccr(channel.index()).as_ptr() as *mut T::Word, |
| 690 | dma_buf, | 657 | dma_buf, |
| 691 | dma_transfer_option, | 658 | dma_transfer_option, |
| 692 | ) | 659 | ) |
| @@ -701,7 +668,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 701 | &mut self, | 668 | &mut self, |
| 702 | dma: Peri<'a, impl super::UpDma<T>>, | 669 | dma: Peri<'a, impl super::UpDma<T>>, |
| 703 | channel: Channel, | 670 | channel: Channel, |
| 704 | duty: &'a [u16], | 671 | duty: &'a [T::Word], |
| 705 | ) -> Transfer<'a> { | 672 | ) -> Transfer<'a> { |
| 706 | #[allow(clippy::let_unit_value)] // eg. stm32f334 | 673 | #[allow(clippy::let_unit_value)] // eg. stm32f334 |
| 707 | let req = dma.request(); | 674 | let req = dma.request(); |
| @@ -719,29 +686,13 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 719 | ..Default::default() | 686 | ..Default::default() |
| 720 | }; | 687 | }; |
| 721 | 688 | ||
| 722 | match self.bits() { | 689 | Transfer::new_write( |
| 723 | TimerBits::Bits16 => Transfer::new_write( | 690 | dma, |
| 724 | dma, | 691 | req, |
| 725 | req, | 692 | duty, |
| 726 | duty, | 693 | self.regs_gp16().ccr(channel.index()).as_ptr() as *mut T::Word, |
| 727 | self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, | 694 | dma_transfer_option, |
| 728 | dma_transfer_option, | 695 | ) |
| 729 | ), | ||
| 730 | #[cfg(not(any(stm32l0)))] | ||
| 731 | TimerBits::Bits32 => { | ||
| 732 | #[cfg(not(any(bdma, gpdma)))] | ||
| 733 | panic!("unsupported timer bits"); | ||
| 734 | |||
| 735 | #[cfg(any(bdma, gpdma))] | ||
| 736 | Transfer::new_write( | ||
| 737 | dma, | ||
| 738 | req, | ||
| 739 | duty, | ||
| 740 | self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u32, | ||
| 741 | dma_transfer_option, | ||
| 742 | ) | ||
| 743 | } | ||
| 744 | } | ||
| 745 | } | 696 | } |
| 746 | } | 697 | } |
| 747 | 698 | ||
| @@ -779,7 +730,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 779 | dma: Peri<'a, impl super::UpDma<T>>, | 730 | dma: Peri<'a, impl super::UpDma<T>>, |
| 780 | starting_channel: Channel, | 731 | starting_channel: Channel, |
| 781 | ending_channel: Channel, | 732 | ending_channel: Channel, |
| 782 | duty: &'a [u16], | 733 | duty: &'a [T::Word], |
| 783 | ) -> Transfer<'a> { | 734 | ) -> Transfer<'a> { |
| 784 | let cr1_addr = self.regs_gp16().cr1().as_ptr() as u32; | 735 | let cr1_addr = self.regs_gp16().cr1().as_ptr() as u32; |
| 785 | let start_ch_index = starting_channel.index(); | 736 | let start_ch_index = starting_channel.index(); |
| @@ -815,14 +766,14 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 815 | dma, | 766 | dma, |
| 816 | req, | 767 | req, |
| 817 | duty, | 768 | duty, |
| 818 | self.regs_gp16().dmar().as_ptr() as *mut u16, | 769 | self.regs_gp16().dmar().as_ptr() as *mut T::Word, |
| 819 | dma_transfer_option, | 770 | dma_transfer_option, |
| 820 | ) | 771 | ) |
| 821 | } | 772 | } |
| 822 | } | 773 | } |
| 823 | 774 | ||
| 824 | /// Get capture value for a channel. | 775 | /// Get capture value for a channel. |
| 825 | pub fn get_capture_value(&self, channel: Channel) -> u32 { | 776 | pub fn get_capture_value(&self, channel: Channel) -> T::Word { |
| 826 | self.get_compare_value(channel) | 777 | self.get_compare_value(channel) |
| 827 | } | 778 | } |
| 828 | 779 | ||
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 3fa363881..74d1c9e77 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs | |||
| @@ -15,6 +15,8 @@ pub mod qei; | |||
| 15 | pub mod ringbuffered; | 15 | pub mod ringbuffered; |
| 16 | pub mod simple_pwm; | 16 | pub mod simple_pwm; |
| 17 | 17 | ||
| 18 | use crate::dma::word::Word; | ||
| 19 | use crate::fmt::Debuggable; | ||
| 18 | use crate::interrupt; | 20 | use crate::interrupt; |
| 19 | use crate::rcc::RccPeripheral; | 21 | use crate::rcc::RccPeripheral; |
| 20 | 22 | ||
| @@ -163,7 +165,12 @@ pub trait CoreInstance: SealedInstance + 'static { | |||
| 163 | type UpdateInterrupt: interrupt::typelevel::Interrupt; | 165 | type UpdateInterrupt: interrupt::typelevel::Interrupt; |
| 164 | 166 | ||
| 165 | /// Amount of bits this timer has. | 167 | /// Amount of bits this timer has. |
| 166 | const BITS: TimerBits; | 168 | type Word: Word |
| 169 | + TryInto<u16, Error: Debuggable> | ||
| 170 | + From<u16> | ||
| 171 | + TryFrom<u32, Error: Debuggable> | ||
| 172 | + Into<u32> | ||
| 173 | + TryFrom<u64, Error: Debuggable>; | ||
| 167 | 174 | ||
| 168 | /// Registers for this timer. | 175 | /// Registers for this timer. |
| 169 | /// | 176 | /// |
| @@ -241,7 +248,7 @@ dma_trait!(Dma, GeneralInstance4Channel, TimerChannel); | |||
| 241 | 248 | ||
| 242 | #[allow(unused)] | 249 | #[allow(unused)] |
| 243 | macro_rules! impl_core_timer { | 250 | macro_rules! impl_core_timer { |
| 244 | ($inst:ident, $bits:expr) => { | 251 | ($inst:ident, $bits:ident) => { |
| 245 | impl SealedInstance for crate::peripherals::$inst { | 252 | impl SealedInstance for crate::peripherals::$inst { |
| 246 | fn state() -> &'static State { | 253 | fn state() -> &'static State { |
| 247 | static STATE: State = State::new(); | 254 | static STATE: State = State::new(); |
| @@ -251,8 +258,7 @@ macro_rules! impl_core_timer { | |||
| 251 | 258 | ||
| 252 | impl CoreInstance for crate::peripherals::$inst { | 259 | impl CoreInstance for crate::peripherals::$inst { |
| 253 | type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP; | 260 | type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP; |
| 254 | 261 | type Word = $bits; | |
| 255 | const BITS: TimerBits = $bits; | ||
| 256 | 262 | ||
| 257 | fn regs() -> *mut () { | 263 | fn regs() -> *mut () { |
| 258 | crate::pac::$inst.as_ptr() | 264 | crate::pac::$inst.as_ptr() |
| @@ -306,13 +312,13 @@ macro_rules! impl_general_4ch_blank_sealed { | |||
| 306 | 312 | ||
| 307 | foreach_interrupt! { | 313 | foreach_interrupt! { |
| 308 | ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { | 314 | ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { |
| 309 | impl_core_timer!($inst, TimerBits::Bits16); | 315 | impl_core_timer!($inst, u16); |
| 310 | impl BasicNoCr2Instance for crate::peripherals::$inst {} | 316 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 311 | impl BasicInstance for crate::peripherals::$inst {} | 317 | impl BasicInstance for crate::peripherals::$inst {} |
| 312 | }; | 318 | }; |
| 313 | 319 | ||
| 314 | ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => { | 320 | ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => { |
| 315 | impl_core_timer!($inst, TimerBits::Bits16); | 321 | impl_core_timer!($inst, u16); |
| 316 | impl BasicNoCr2Instance for crate::peripherals::$inst {} | 322 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 317 | impl BasicInstance for crate::peripherals::$inst {} | 323 | impl BasicInstance for crate::peripherals::$inst {} |
| 318 | impl_general_1ch!($inst); | 324 | impl_general_1ch!($inst); |
| @@ -322,7 +328,7 @@ foreach_interrupt! { | |||
| 322 | }; | 328 | }; |
| 323 | 329 | ||
| 324 | ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => { | 330 | ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => { |
| 325 | impl_core_timer!($inst, TimerBits::Bits16); | 331 | impl_core_timer!($inst, u16); |
| 326 | impl BasicNoCr2Instance for crate::peripherals::$inst {} | 332 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 327 | impl BasicInstance for crate::peripherals::$inst {} | 333 | impl BasicInstance for crate::peripherals::$inst {} |
| 328 | impl_general_1ch!($inst); | 334 | impl_general_1ch!($inst); |
| @@ -332,7 +338,7 @@ foreach_interrupt! { | |||
| 332 | }; | 338 | }; |
| 333 | 339 | ||
| 334 | ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { | 340 | ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { |
| 335 | impl_core_timer!($inst, TimerBits::Bits16); | 341 | impl_core_timer!($inst, u16); |
| 336 | impl BasicNoCr2Instance for crate::peripherals::$inst {} | 342 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 337 | impl BasicInstance for crate::peripherals::$inst {} | 343 | impl BasicInstance for crate::peripherals::$inst {} |
| 338 | impl_general_1ch!($inst); | 344 | impl_general_1ch!($inst); |
| @@ -342,7 +348,7 @@ foreach_interrupt! { | |||
| 342 | }; | 348 | }; |
| 343 | 349 | ||
| 344 | ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { | 350 | ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { |
| 345 | impl_core_timer!($inst, TimerBits::Bits32); | 351 | impl_core_timer!($inst, u32); |
| 346 | impl BasicNoCr2Instance for crate::peripherals::$inst {} | 352 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 347 | impl BasicInstance for crate::peripherals::$inst {} | 353 | impl BasicInstance for crate::peripherals::$inst {} |
| 348 | impl_general_1ch!($inst); | 354 | impl_general_1ch!($inst); |
| @@ -353,7 +359,7 @@ foreach_interrupt! { | |||
| 353 | }; | 359 | }; |
| 354 | 360 | ||
| 355 | ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => { | 361 | ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => { |
| 356 | impl_core_timer!($inst, TimerBits::Bits16); | 362 | impl_core_timer!($inst, u16); |
| 357 | impl BasicNoCr2Instance for crate::peripherals::$inst {} | 363 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 358 | impl BasicInstance for crate::peripherals::$inst {} | 364 | impl BasicInstance for crate::peripherals::$inst {} |
| 359 | impl_general_1ch!($inst); | 365 | impl_general_1ch!($inst); |
| @@ -366,7 +372,7 @@ foreach_interrupt! { | |||
| 366 | }; | 372 | }; |
| 367 | 373 | ||
| 368 | ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => { | 374 | ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => { |
| 369 | impl_core_timer!($inst, TimerBits::Bits16); | 375 | impl_core_timer!($inst, u16); |
| 370 | impl BasicNoCr2Instance for crate::peripherals::$inst {} | 376 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 371 | impl BasicInstance for crate::peripherals::$inst {} | 377 | impl BasicInstance for crate::peripherals::$inst {} |
| 372 | impl_general_1ch!($inst); | 378 | impl_general_1ch!($inst); |
| @@ -379,7 +385,7 @@ foreach_interrupt! { | |||
| 379 | }; | 385 | }; |
| 380 | 386 | ||
| 381 | ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { | 387 | ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { |
| 382 | impl_core_timer!($inst, TimerBits::Bits16); | 388 | impl_core_timer!($inst, u16); |
| 383 | impl BasicNoCr2Instance for crate::peripherals::$inst {} | 389 | impl BasicNoCr2Instance for crate::peripherals::$inst {} |
| 384 | impl BasicInstance for crate::peripherals::$inst {} | 390 | impl BasicInstance for crate::peripherals::$inst {} |
| 385 | impl_general_1ch!($inst); | 391 | impl_general_1ch!($inst); |
diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs index fe8681356..989e1d630 100644 --- a/embassy-stm32/src/timer/one_pulse.rs +++ b/embassy-stm32/src/timer/one_pulse.rs | |||
| @@ -199,7 +199,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { | |||
| 199 | fn new_inner(&mut self, freq: Hertz, pulse_end: u32, counting_mode: CountingMode) { | 199 | fn new_inner(&mut self, freq: Hertz, pulse_end: u32, counting_mode: CountingMode) { |
| 200 | self.inner.set_counting_mode(counting_mode); | 200 | self.inner.set_counting_mode(counting_mode); |
| 201 | self.inner.set_tick_freq(freq); | 201 | self.inner.set_tick_freq(freq); |
| 202 | self.inner.set_max_compare_value(pulse_end); | 202 | self.inner.set_max_compare_value(unwrap!(pulse_end.try_into())); |
| 203 | self.inner.regs_core().cr1().modify(|r| r.set_opm(true)); | 203 | self.inner.regs_core().cr1().modify(|r| r.set_opm(true)); |
| 204 | // Required for advanced timers, see GeneralInstance4Channel for details | 204 | // Required for advanced timers, see GeneralInstance4Channel for details |
| 205 | self.inner.enable_outputs(); | 205 | self.inner.enable_outputs(); |
| @@ -211,14 +211,14 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { | |||
| 211 | 211 | ||
| 212 | /// Get the end of the pulse in ticks from the trigger. | 212 | /// Get the end of the pulse in ticks from the trigger. |
| 213 | pub fn pulse_end(&self) -> u32 { | 213 | pub fn pulse_end(&self) -> u32 { |
| 214 | let max = self.inner.get_max_compare_value(); | 214 | let max: u32 = self.inner.get_max_compare_value().into(); |
| 215 | assert!(max < u32::MAX); | 215 | assert!(max < u32::MAX); |
| 216 | max + 1 | 216 | max + 1 |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | /// Set the end of the pulse in ticks from the trigger. | 219 | /// Set the end of the pulse in ticks from the trigger. |
| 220 | pub fn set_pulse_end(&mut self, ticks: u32) { | 220 | pub fn set_pulse_end(&mut self, ticks: u32) { |
| 221 | self.inner.set_max_compare_value(ticks) | 221 | self.inner.set_max_compare_value(unwrap!(ticks.try_into())) |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | /// Reset the timer on each trigger | 224 | /// Reset the timer on each trigger |
| @@ -327,7 +327,7 @@ pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> { | |||
| 327 | impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { | 327 | impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { |
| 328 | /// Get the end of the pulse in ticks from the trigger. | 328 | /// Get the end of the pulse in ticks from the trigger. |
| 329 | pub fn pulse_end(&self) -> u32 { | 329 | pub fn pulse_end(&self) -> u32 { |
| 330 | let max = self.inner.get_max_compare_value(); | 330 | let max: u32 = self.inner.get_max_compare_value().into(); |
| 331 | assert!(max < u32::MAX); | 331 | assert!(max < u32::MAX); |
| 332 | max + 1 | 332 | max + 1 |
| 333 | } | 333 | } |
| @@ -339,13 +339,13 @@ impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { | |||
| 339 | 339 | ||
| 340 | /// Get the start of the pulse in ticks from the trigger. | 340 | /// Get the start of the pulse in ticks from the trigger. |
| 341 | pub fn pulse_delay(&mut self) -> u32 { | 341 | pub fn pulse_delay(&mut self) -> u32 { |
| 342 | self.inner.get_compare_value(self.channel) | 342 | self.inner.get_compare_value(self.channel).into() |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | /// Set the start of the pulse in ticks from the trigger. | 345 | /// Set the start of the pulse in ticks from the trigger. |
| 346 | pub fn set_pulse_delay(&mut self, delay: u32) { | 346 | pub fn set_pulse_delay(&mut self, delay: u32) { |
| 347 | assert!(delay <= self.pulse_end()); | 347 | assert!(delay <= self.pulse_end()); |
| 348 | self.inner.set_compare_value(self.channel, delay); | 348 | self.inner.set_compare_value(self.channel, unwrap!(delay.try_into())); |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | /// Set the pulse width in ticks. | 351 | /// Set the pulse width in ticks. |
diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index 057ab011a..f2f00927d 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs | |||
| @@ -91,16 +91,18 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { | |||
| 91 | 91 | ||
| 92 | /// Get the period tick count | 92 | /// Get the period tick count |
| 93 | pub fn get_period_ticks(&self) -> u32 { | 93 | pub fn get_period_ticks(&self) -> u32 { |
| 94 | self.inner.get_capture_value(self.channel) | 94 | self.inner.get_capture_value(self.channel).into() |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | /// Get the pulse width tick count | 97 | /// Get the pulse width tick count |
| 98 | pub fn get_width_ticks(&self) -> u32 { | 98 | pub fn get_width_ticks(&self) -> u32 { |
| 99 | self.inner.get_capture_value(match self.channel { | 99 | self.inner |
| 100 | Channel::Ch1 => Channel::Ch2, | 100 | .get_capture_value(match self.channel { |
| 101 | Channel::Ch2 => Channel::Ch1, | 101 | Channel::Ch1 => Channel::Ch2, |
| 102 | _ => panic!("Invalid channel for PWM input"), | 102 | Channel::Ch2 => Channel::Ch1, |
| 103 | }) | 103 | _ => panic!("Invalid channel for PWM input"), |
| 104 | }) | ||
| 105 | .into() | ||
| 104 | } | 106 | } |
| 105 | 107 | ||
| 106 | /// Get the duty cycle in 100% | 108 | /// Get the duty cycle in 100% |
diff --git a/embassy-stm32/src/timer/ringbuffered.rs b/embassy-stm32/src/timer/ringbuffered.rs index e8f97bf59..f5a4328d1 100644 --- a/embassy-stm32/src/timer/ringbuffered.rs +++ b/embassy-stm32/src/timer/ringbuffered.rs | |||
| @@ -25,7 +25,7 @@ use crate::dma::ringbuffer::Error; | |||
| 25 | /// ``` | 25 | /// ``` |
| 26 | pub struct RingBufferedPwmChannel<'d, T: GeneralInstance4Channel> { | 26 | pub struct RingBufferedPwmChannel<'d, T: GeneralInstance4Channel> { |
| 27 | timer: ManuallyDrop<Timer<'d, T>>, | 27 | timer: ManuallyDrop<Timer<'d, T>>, |
| 28 | ring_buf: WritableRingBuffer<'d, u16>, | 28 | ring_buf: WritableRingBuffer<'d, T::Word>, |
| 29 | channel: Channel, | 29 | channel: Channel, |
| 30 | } | 30 | } |
| 31 | 31 | ||
| @@ -33,7 +33,7 @@ impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> { | |||
| 33 | pub(crate) fn new( | 33 | pub(crate) fn new( |
| 34 | timer: ManuallyDrop<Timer<'d, T>>, | 34 | timer: ManuallyDrop<Timer<'d, T>>, |
| 35 | channel: Channel, | 35 | channel: Channel, |
| 36 | ring_buf: WritableRingBuffer<'d, u16>, | 36 | ring_buf: WritableRingBuffer<'d, T::Word>, |
| 37 | ) -> Self { | 37 | ) -> Self { |
| 38 | Self { | 38 | Self { |
| 39 | timer, | 39 | timer, |
| @@ -55,18 +55,18 @@ impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> { | |||
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | /// Write elements directly to the raw buffer. This can be used to fill the buffer before starting the DMA transfer. | 57 | /// Write elements directly to the raw buffer. This can be used to fill the buffer before starting the DMA transfer. |
| 58 | pub fn write_immediate(&mut self, buf: &[u16]) -> Result<(usize, usize), Error> { | 58 | pub fn write_immediate(&mut self, buf: &[T::Word]) -> Result<(usize, usize), Error> { |
| 59 | self.ring_buf.write_immediate(buf) | 59 | self.ring_buf.write_immediate(buf) |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | /// Write elements from the ring buffer | 62 | /// Write elements from the ring buffer |
| 63 | /// Return a tuple of the length written and the length remaining in the buffer | 63 | /// Return a tuple of the length written and the length remaining in the buffer |
| 64 | pub fn write(&mut self, buf: &[u16]) -> Result<(usize, usize), Error> { | 64 | pub fn write(&mut self, buf: &[T::Word]) -> Result<(usize, usize), Error> { |
| 65 | self.ring_buf.write(buf) | 65 | self.ring_buf.write(buf) |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | /// Write an exact number of elements to the ringbuffer. | 68 | /// Write an exact number of elements to the ringbuffer. |
| 69 | pub async fn write_exact(&mut self, buffer: &[u16]) -> Result<usize, Error> { | 69 | pub async fn write_exact(&mut self, buffer: &[T::Word]) -> Result<usize, Error> { |
| 70 | self.ring_buf.write_exact(buffer).await | 70 | self.ring_buf.write_exact(buffer).await |
| 71 | } | 71 | } |
| 72 | 72 | ||
| @@ -140,7 +140,7 @@ impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> { | |||
| 140 | /// | 140 | /// |
| 141 | /// This value depends on the configured frequency and the timer's clock rate from RCC. | 141 | /// This value depends on the configured frequency and the timer's clock rate from RCC. |
| 142 | pub fn max_duty_cycle(&self) -> u16 { | 142 | pub fn max_duty_cycle(&self) -> u16 { |
| 143 | let max = self.timer.get_max_compare_value(); | 143 | let max: u32 = self.timer.get_max_compare_value().into(); |
| 144 | assert!(max < u16::MAX as u32); | 144 | assert!(max < u16::MAX as u32); |
| 145 | max as u16 + 1 | 145 | max as u16 + 1 |
| 146 | } | 146 | } |
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 484e9fd81..8dc84cdfa 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs | |||
| @@ -99,7 +99,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwmChannel<'d, T> { | |||
| 99 | /// | 99 | /// |
| 100 | /// This value depends on the configured frequency and the timer's clock rate from RCC. | 100 | /// This value depends on the configured frequency and the timer's clock rate from RCC. |
| 101 | pub fn max_duty_cycle(&self) -> u16 { | 101 | pub fn max_duty_cycle(&self) -> u16 { |
| 102 | let max = self.timer.get_max_compare_value(); | 102 | let max: u32 = self.timer.get_max_compare_value().into(); |
| 103 | assert!(max < u16::MAX as u32); | 103 | assert!(max < u16::MAX as u32); |
| 104 | max as u16 + 1 | 104 | max as u16 + 1 |
| 105 | } | 105 | } |
| @@ -174,7 +174,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwmChannel<'d, T> { | |||
| 174 | pub fn into_ring_buffered_channel( | 174 | pub fn into_ring_buffered_channel( |
| 175 | mut self, | 175 | mut self, |
| 176 | tx_dma: Peri<'d, impl super::UpDma<T>>, | 176 | tx_dma: Peri<'d, impl super::UpDma<T>>, |
| 177 | dma_buf: &'d mut [u16], | 177 | dma_buf: &'d mut [T::Word], |
| 178 | ) -> RingBufferedPwmChannel<'d, T> { | 178 | ) -> RingBufferedPwmChannel<'d, T> { |
| 179 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); | 179 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); |
| 180 | 180 | ||
| @@ -333,7 +333,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { | |||
| 333 | /// | 333 | /// |
| 334 | /// This value depends on the configured frequency and the timer's clock rate from RCC. | 334 | /// This value depends on the configured frequency and the timer's clock rate from RCC. |
| 335 | pub fn max_duty_cycle(&self) -> u16 { | 335 | pub fn max_duty_cycle(&self) -> u16 { |
| 336 | let max = self.inner.get_max_compare_value(); | 336 | let max: u32 = self.inner.get_max_compare_value().into(); |
| 337 | assert!(max < u16::MAX as u32); | 337 | assert!(max < u16::MAX as u32); |
| 338 | max as u16 + 1 | 338 | max as u16 + 1 |
| 339 | } | 339 | } |
| @@ -344,7 +344,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { | |||
| 344 | /// You will need to provide corresponding `TIMx_UP` DMA channel to use this method. | 344 | /// You will need to provide corresponding `TIMx_UP` DMA channel to use this method. |
| 345 | /// Also be aware that embassy timers use one of timers internally. It is possible to | 345 | /// Also be aware that embassy timers use one of timers internally. It is possible to |
| 346 | /// switch this timer by using `time-driver-timX` feature. | 346 | /// switch this timer by using `time-driver-timX` feature. |
| 347 | pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) { | 347 | pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[T::Word]) { |
| 348 | self.inner.enable_channel(channel, true); | 348 | self.inner.enable_channel(channel, true); |
| 349 | self.inner.enable_update_dma(true); | 349 | self.inner.enable_update_dma(true); |
| 350 | self.inner.setup_update_dma(dma, channel, duty).await; | 350 | self.inner.setup_update_dma(dma, channel, duty).await; |
| @@ -385,7 +385,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { | |||
| 385 | dma: Peri<'_, impl super::UpDma<T>>, | 385 | dma: Peri<'_, impl super::UpDma<T>>, |
| 386 | starting_channel: Channel, | 386 | starting_channel: Channel, |
| 387 | ending_channel: Channel, | 387 | ending_channel: Channel, |
| 388 | duty: &[u16], | 388 | duty: &[T::Word], |
| 389 | ) { | 389 | ) { |
| 390 | self.inner.enable_update_dma(true); | 390 | self.inner.enable_update_dma(true); |
| 391 | self.inner | 391 | self.inner |
| @@ -448,16 +448,16 @@ impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> { | |||
| 448 | } | 448 | } |
| 449 | 449 | ||
| 450 | fn get_duty(&self, channel: Self::Channel) -> Self::Duty { | 450 | fn get_duty(&self, channel: Self::Channel) -> Self::Duty { |
| 451 | self.inner.get_compare_value(channel) | 451 | self.inner.get_compare_value(channel).into() |
| 452 | } | 452 | } |
| 453 | 453 | ||
| 454 | fn get_max_duty(&self) -> Self::Duty { | 454 | fn get_max_duty(&self) -> Self::Duty { |
| 455 | self.inner.get_max_compare_value() + 1 | 455 | self.inner.get_max_compare_value().into() + 1 |
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { | 458 | fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { |
| 459 | assert!(duty <= self.max_duty_cycle() as u32); | 459 | assert!(duty <= self.max_duty_cycle() as u32); |
| 460 | self.inner.set_compare_value(channel, duty) | 460 | self.inner.set_compare_value(channel, unwrap!(duty.try_into())) |
| 461 | } | 461 | } |
| 462 | 462 | ||
| 463 | fn set_period<P>(&mut self, period: P) | 463 | fn set_period<P>(&mut self, period: P) |
