aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormelvdl <[email protected]>2025-06-27 01:08:28 +0200
committermelvdl <[email protected]>2025-06-27 01:08:28 +0200
commit6f88c2c73caa63a6e534130f4a064cb95d3e9d7d (patch)
treefdddad93e4f48f32ff15a3b8ad6cd0ae12095fd4
parentcbd24bf2eece65a787fc085c255e9b2932ea73e3 (diff)
stm32: rename timer channel trait; replace impls via macro with impls generic over timer channels
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs33
-rw-r--r--embassy-stm32/src/timer/input_capture.rs41
-rw-r--r--embassy-stm32/src/timer/low_level.rs38
-rw-r--r--embassy-stm32/src/timer/mod.rs48
-rw-r--r--embassy-stm32/src/timer/one_pulse.rs44
-rw-r--r--embassy-stm32/src/timer/pwm_input.rs28
-rw-r--r--embassy-stm32/src/timer/qei.rs4
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs279
8 files changed, 241 insertions, 274 deletions
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 4600dd1a3..a450705a2 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -6,11 +6,11 @@ use stm32_metapac::timer::vals::Ckd;
6 6
7use super::low_level::{CountingMode, OutputPolarity, Timer}; 7use super::low_level::{CountingMode, OutputPolarity, Timer};
8use super::simple_pwm::PwmPin; 8use super::simple_pwm::PwmPin;
9use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, TimerChannel, TimerComplementaryPin}; 9use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, Channel, TimerComplementaryPin};
10use crate::gpio::{AnyPin, OutputType}; 10use crate::gpio::{AnyPin, OutputType};
11use crate::time::Hertz; 11use crate::time::Hertz;
12use crate::timer::low_level::OutputCompareMode; 12use crate::timer::low_level::OutputCompareMode;
13use crate::timer::Channel; 13use crate::timer::TimerChannel;
14use crate::Peri; 14use crate::Peri;
15 15
16/// Complementary PWM pin wrapper. 16/// Complementary PWM pin wrapper.
@@ -21,7 +21,7 @@ pub struct ComplementaryPwmPin<'d, T, C> {
21 phantom: PhantomData<(T, C)>, 21 phantom: PhantomData<(T, C)>,
22} 22}
23 23
24impl<'d, T: AdvancedInstance4Channel, C: Channel> ComplementaryPwmPin<'d, T, C> { 24impl<'d, T: AdvancedInstance4Channel, C: TimerChannel> ComplementaryPwmPin<'d, T, C> {
25 /// Create a new complementary PWM pin instance. 25 /// Create a new complementary PWM pin instance.
26 pub fn new(pin: Peri<'d, impl TimerComplementaryPin<T, C>>, output_type: OutputType) -> Self { 26 pub fn new(pin: Peri<'d, impl TimerComplementaryPin<T, C>>, output_type: OutputType) -> Self {
27 critical_section::with(|_| { 27 critical_section::with(|_| {
@@ -71,29 +71,24 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
71 71
72 this.inner.enable_outputs(); 72 this.inner.enable_outputs();
73 73
74 [ 74 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
75 TimerChannel::Ch1, 75 .iter()
76 TimerChannel::Ch2, 76 .for_each(|&channel| {
77 TimerChannel::Ch3, 77 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
78 TimerChannel::Ch4, 78 this.inner.set_output_compare_preload(channel, true);
79 ] 79 });
80 .iter()
81 .for_each(|&channel| {
82 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
83 this.inner.set_output_compare_preload(channel, true);
84 });
85 80
86 this 81 this
87 } 82 }
88 83
89 /// Enable the given channel. 84 /// Enable the given channel.
90 pub fn enable(&mut self, channel: TimerChannel) { 85 pub fn enable(&mut self, channel: Channel) {
91 self.inner.enable_channel(channel, true); 86 self.inner.enable_channel(channel, true);
92 self.inner.enable_complementary_channel(channel, true); 87 self.inner.enable_complementary_channel(channel, true);
93 } 88 }
94 89
95 /// Disable the given channel. 90 /// Disable the given channel.
96 pub fn disable(&mut self, channel: TimerChannel) { 91 pub fn disable(&mut self, channel: Channel) {
97 self.inner.enable_complementary_channel(channel, false); 92 self.inner.enable_complementary_channel(channel, false);
98 self.inner.enable_channel(channel, false); 93 self.inner.enable_channel(channel, false);
99 } 94 }
@@ -121,13 +116,13 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
121 /// Set the duty for a given channel. 116 /// Set the duty for a given channel.
122 /// 117 ///
123 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. 118 /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
124 pub fn set_duty(&mut self, channel: TimerChannel, duty: u16) { 119 pub fn set_duty(&mut self, channel: Channel, duty: u16) {
125 assert!(duty <= self.get_max_duty()); 120 assert!(duty <= self.get_max_duty());
126 self.inner.set_compare_value(channel, duty as _) 121 self.inner.set_compare_value(channel, duty as _)
127 } 122 }
128 123
129 /// Set the output polarity for a given channel. 124 /// Set the output polarity for a given channel.
130 pub fn set_polarity(&mut self, channel: TimerChannel, polarity: OutputPolarity) { 125 pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
131 self.inner.set_output_polarity(channel, polarity); 126 self.inner.set_output_polarity(channel, polarity);
132 self.inner.set_complementary_output_polarity(channel, polarity); 127 self.inner.set_complementary_output_polarity(channel, polarity);
133 } 128 }
@@ -142,7 +137,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
142} 137}
143 138
144impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { 139impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
145 type Channel = TimerChannel; 140 type Channel = Channel;
146 type Time = Hertz; 141 type Time = Hertz;
147 type Duty = u16; 142 type Duty = u16;
148 143
diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs
index da567d504..49e22b10f 100644
--- a/embassy-stm32/src/timer/input_capture.rs
+++ b/embassy-stm32/src/timer/input_capture.rs
@@ -6,12 +6,12 @@ use core::pin::Pin;
6use core::task::{Context, Poll}; 6use core::task::{Context, Poll};
7 7
8use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer}; 8use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer};
9use super::{CaptureCompareInterruptHandler, GeneralInstance4Channel, TimerChannel, TimerPin}; 9use super::{CaptureCompareInterruptHandler, GeneralInstance4Channel, Channel, TimerPin};
10pub use super::{Ch1, Ch2, Ch3, Ch4}; 10pub use super::{Ch1, Ch2, Ch3, Ch4};
11use crate::gpio::{AfType, AnyPin, Pull}; 11use crate::gpio::{AfType, AnyPin, Pull};
12use crate::interrupt::typelevel::{Binding, Interrupt}; 12use crate::interrupt::typelevel::{Binding, Interrupt};
13use crate::time::Hertz; 13use crate::time::Hertz;
14use crate::timer::Channel; 14use crate::timer::TimerChannel;
15use crate::Peri; 15use crate::Peri;
16 16
17/// Capture pin wrapper. 17/// Capture pin wrapper.
@@ -21,7 +21,7 @@ pub struct CapturePin<'d, T, C> {
21 _pin: Peri<'d, AnyPin>, 21 _pin: Peri<'d, AnyPin>,
22 phantom: PhantomData<(T, C)>, 22 phantom: PhantomData<(T, C)>,
23} 23}
24impl<'d, T: GeneralInstance4Channel, C: Channel> CapturePin<'d, T, C> { 24impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> {
25 /// Create a new capture pin instance. 25 /// Create a new capture pin instance.
26 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self { 26 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self {
27 pin.set_as_af(pin.af_num(), AfType::input(pull)); 27 pin.set_as_af(pin.af_num(), AfType::input(pull));
@@ -68,46 +68,41 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
68 } 68 }
69 69
70 /// Enable the given channel. 70 /// Enable the given channel.
71 pub fn enable(&mut self, channel: TimerChannel) { 71 pub fn enable(&mut self, channel: Channel) {
72 self.inner.enable_channel(channel, true); 72 self.inner.enable_channel(channel, true);
73 } 73 }
74 74
75 /// Disable the given channel. 75 /// Disable the given channel.
76 pub fn disable(&mut self, channel: TimerChannel) { 76 pub fn disable(&mut self, channel: Channel) {
77 self.inner.enable_channel(channel, false); 77 self.inner.enable_channel(channel, false);
78 } 78 }
79 79
80 /// Check whether given channel is enabled 80 /// Check whether given channel is enabled
81 pub fn is_enabled(&self, channel: TimerChannel) -> bool { 81 pub fn is_enabled(&self, channel: Channel) -> bool {
82 self.inner.get_channel_enable_state(channel) 82 self.inner.get_channel_enable_state(channel)
83 } 83 }
84 84
85 /// Set the input capture mode for a given channel. 85 /// Set the input capture mode for a given channel.
86 pub fn set_input_capture_mode(&mut self, channel: TimerChannel, mode: InputCaptureMode) { 86 pub fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
87 self.inner.set_input_capture_mode(channel, mode); 87 self.inner.set_input_capture_mode(channel, mode);
88 } 88 }
89 89
90 /// Set input TI selection. 90 /// Set input TI selection.
91 pub fn set_input_ti_selection(&mut self, channel: TimerChannel, tisel: InputTISelection) { 91 pub fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
92 self.inner.set_input_ti_selection(channel, tisel) 92 self.inner.set_input_ti_selection(channel, tisel)
93 } 93 }
94 94
95 /// Get capture value for a channel. 95 /// Get capture value for a channel.
96 pub fn get_capture_value(&self, channel: TimerChannel) -> u32 { 96 pub fn get_capture_value(&self, channel: Channel) -> u32 {
97 self.inner.get_capture_value(channel) 97 self.inner.get_capture_value(channel)
98 } 98 }
99 99
100 /// Get input interrupt. 100 /// Get input interrupt.
101 pub fn get_input_interrupt(&self, channel: TimerChannel) -> bool { 101 pub fn get_input_interrupt(&self, channel: Channel) -> bool {
102 self.inner.get_input_interrupt(channel) 102 self.inner.get_input_interrupt(channel)
103 } 103 }
104 104
105 fn new_future( 105 fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture<T> {
106 &self,
107 channel: TimerChannel,
108 mode: InputCaptureMode,
109 tisel: InputTISelection,
110 ) -> InputCaptureFuture<T> {
111 // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.5 106 // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.5
112 // or ST RM0008 (STM32F103) chapter 15.3.5 Input capture mode 107 // or ST RM0008 (STM32F103) chapter 15.3.5 Input capture mode
113 self.inner.set_input_ti_selection(channel, tisel); 108 self.inner.set_input_ti_selection(channel, tisel);
@@ -124,37 +119,37 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
124 } 119 }
125 120
126 /// Asynchronously wait until the pin sees a rising edge. 121 /// Asynchronously wait until the pin sees a rising edge.
127 pub async fn wait_for_rising_edge(&mut self, channel: TimerChannel) -> u32 { 122 pub async fn wait_for_rising_edge(&mut self, channel: Channel) -> u32 {
128 self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Normal) 123 self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Normal)
129 .await 124 .await
130 } 125 }
131 126
132 /// Asynchronously wait until the pin sees a falling edge. 127 /// Asynchronously wait until the pin sees a falling edge.
133 pub async fn wait_for_falling_edge(&mut self, channel: TimerChannel) -> u32 { 128 pub async fn wait_for_falling_edge(&mut self, channel: Channel) -> u32 {
134 self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Normal) 129 self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Normal)
135 .await 130 .await
136 } 131 }
137 132
138 /// Asynchronously wait until the pin sees any edge. 133 /// Asynchronously wait until the pin sees any edge.
139 pub async fn wait_for_any_edge(&mut self, channel: TimerChannel) -> u32 { 134 pub async fn wait_for_any_edge(&mut self, channel: Channel) -> u32 {
140 self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Normal) 135 self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Normal)
141 .await 136 .await
142 } 137 }
143 138
144 /// Asynchronously wait until the (alternate) pin sees a rising edge. 139 /// Asynchronously wait until the (alternate) pin sees a rising edge.
145 pub async fn wait_for_rising_edge_alternate(&mut self, channel: TimerChannel) -> u32 { 140 pub async fn wait_for_rising_edge_alternate(&mut self, channel: Channel) -> u32 {
146 self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Alternate) 141 self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Alternate)
147 .await 142 .await
148 } 143 }
149 144
150 /// Asynchronously wait until the (alternate) pin sees a falling edge. 145 /// Asynchronously wait until the (alternate) pin sees a falling edge.
151 pub async fn wait_for_falling_edge_alternate(&mut self, channel: TimerChannel) -> u32 { 146 pub async fn wait_for_falling_edge_alternate(&mut self, channel: Channel) -> u32 {
152 self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Alternate) 147 self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Alternate)
153 .await 148 .await
154 } 149 }
155 150
156 /// Asynchronously wait until the (alternate) pin sees any edge. 151 /// Asynchronously wait until the (alternate) pin sees any edge.
157 pub async fn wait_for_any_edge_alternate(&mut self, channel: TimerChannel) -> u32 { 152 pub async fn wait_for_any_edge_alternate(&mut self, channel: Channel) -> u32 {
158 self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Alternate) 153 self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Alternate)
159 .await 154 .await
160 } 155 }
@@ -162,7 +157,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> {
162 157
163#[must_use = "futures do nothing unless you `.await` or poll them"] 158#[must_use = "futures do nothing unless you `.await` or poll them"]
164struct InputCaptureFuture<T: GeneralInstance4Channel> { 159struct InputCaptureFuture<T: GeneralInstance4Channel> {
165 channel: TimerChannel, 160 channel: Channel,
166 phantom: PhantomData<T>, 161 phantom: PhantomData<T>,
167} 162}
168 163
diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs
index bfdbcf968..dc8ceb725 100644
--- a/embassy-stm32/src/timer/low_level.rs
+++ b/embassy-stm32/src/timer/low_level.rs
@@ -503,7 +503,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
503 } 503 }
504 504
505 /// Set input capture filter. 505 /// Set input capture filter.
506 pub fn set_input_capture_filter(&self, channel: TimerChannel, icf: vals::FilterValue) { 506 pub fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) {
507 let raw_channel = channel.index(); 507 let raw_channel = channel.index();
508 self.regs_gp16() 508 self.regs_gp16()
509 .ccmr_input(raw_channel / 2) 509 .ccmr_input(raw_channel / 2)
@@ -511,22 +511,22 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
511 } 511 }
512 512
513 /// Clear input interrupt. 513 /// Clear input interrupt.
514 pub fn clear_input_interrupt(&self, channel: TimerChannel) { 514 pub fn clear_input_interrupt(&self, channel: Channel) {
515 self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false)); 515 self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
516 } 516 }
517 517
518 /// Get input interrupt. 518 /// Get input interrupt.
519 pub fn get_input_interrupt(&self, channel: TimerChannel) -> bool { 519 pub fn get_input_interrupt(&self, channel: Channel) -> bool {
520 self.regs_gp16().sr().read().ccif(channel.index()) 520 self.regs_gp16().sr().read().ccif(channel.index())
521 } 521 }
522 522
523 /// Enable input interrupt. 523 /// Enable input interrupt.
524 pub fn enable_input_interrupt(&self, channel: TimerChannel, enable: bool) { 524 pub fn enable_input_interrupt(&self, channel: Channel, enable: bool) {
525 self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable)); 525 self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
526 } 526 }
527 527
528 /// Set input capture prescaler. 528 /// Set input capture prescaler.
529 pub fn set_input_capture_prescaler(&self, channel: TimerChannel, factor: u8) { 529 pub fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) {
530 let raw_channel = channel.index(); 530 let raw_channel = channel.index();
531 self.regs_gp16() 531 self.regs_gp16()
532 .ccmr_input(raw_channel / 2) 532 .ccmr_input(raw_channel / 2)
@@ -534,7 +534,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
534 } 534 }
535 535
536 /// Set input TI selection. 536 /// Set input TI selection.
537 pub fn set_input_ti_selection(&self, channel: TimerChannel, tisel: InputTISelection) { 537 pub fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) {
538 let raw_channel = channel.index(); 538 let raw_channel = channel.index();
539 self.regs_gp16() 539 self.regs_gp16()
540 .ccmr_input(raw_channel / 2) 540 .ccmr_input(raw_channel / 2)
@@ -542,7 +542,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
542 } 542 }
543 543
544 /// Set input capture mode. 544 /// Set input capture mode.
545 pub fn set_input_capture_mode(&self, channel: TimerChannel, mode: InputCaptureMode) { 545 pub fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) {
546 self.regs_gp16().ccer().modify(|r| match mode { 546 self.regs_gp16().ccer().modify(|r| match mode {
547 InputCaptureMode::Rising => { 547 InputCaptureMode::Rising => {
548 r.set_ccnp(channel.index(), false); 548 r.set_ccnp(channel.index(), false);
@@ -560,7 +560,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
560 } 560 }
561 561
562 /// Set output compare mode. 562 /// Set output compare mode.
563 pub fn set_output_compare_mode(&self, channel: TimerChannel, mode: OutputCompareMode) { 563 pub fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) {
564 let raw_channel: usize = channel.index(); 564 let raw_channel: usize = channel.index();
565 self.regs_gp16() 565 self.regs_gp16()
566 .ccmr_output(raw_channel / 2) 566 .ccmr_output(raw_channel / 2)
@@ -568,24 +568,24 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
568 } 568 }
569 569
570 /// Set output polarity. 570 /// Set output polarity.
571 pub fn set_output_polarity(&self, channel: TimerChannel, polarity: OutputPolarity) { 571 pub fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
572 self.regs_gp16() 572 self.regs_gp16()
573 .ccer() 573 .ccer()
574 .modify(|w| w.set_ccp(channel.index(), polarity.into())); 574 .modify(|w| w.set_ccp(channel.index(), polarity.into()));
575 } 575 }
576 576
577 /// Enable/disable a channel. 577 /// Enable/disable a channel.
578 pub fn enable_channel(&self, channel: TimerChannel, enable: bool) { 578 pub fn enable_channel(&self, channel: Channel, enable: bool) {
579 self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); 579 self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
580 } 580 }
581 581
582 /// Get enable/disable state of a channel 582 /// Get enable/disable state of a channel
583 pub fn get_channel_enable_state(&self, channel: TimerChannel) -> bool { 583 pub fn get_channel_enable_state(&self, channel: Channel) -> bool {
584 self.regs_gp16().ccer().read().cce(channel.index()) 584 self.regs_gp16().ccer().read().cce(channel.index())
585 } 585 }
586 586
587 /// Set compare value for a channel. 587 /// Set compare value for a channel.
588 pub fn set_compare_value(&self, channel: TimerChannel, value: u32) { 588 pub fn set_compare_value(&self, channel: Channel, value: u32) {
589 match T::BITS { 589 match T::BITS {
590 TimerBits::Bits16 => { 590 TimerBits::Bits16 => {
591 let value = unwrap!(u16::try_from(value)); 591 let value = unwrap!(u16::try_from(value));
@@ -599,7 +599,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
599 } 599 }
600 600
601 /// Get compare value for a channel. 601 /// Get compare value for a channel.
602 pub fn get_compare_value(&self, channel: TimerChannel) -> u32 { 602 pub fn get_compare_value(&self, channel: Channel) -> u32 {
603 match T::BITS { 603 match T::BITS {
604 TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32, 604 TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32,
605 #[cfg(not(stm32l0))] 605 #[cfg(not(stm32l0))]
@@ -608,12 +608,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
608 } 608 }
609 609
610 /// Get capture value for a channel. 610 /// Get capture value for a channel.
611 pub fn get_capture_value(&self, channel: TimerChannel) -> u32 { 611 pub fn get_capture_value(&self, channel: Channel) -> u32 {
612 self.get_compare_value(channel) 612 self.get_compare_value(channel)
613 } 613 }
614 614
615 /// Set output compare preload. 615 /// Set output compare preload.
616 pub fn set_output_compare_preload(&self, channel: TimerChannel, preload: bool) { 616 pub fn set_output_compare_preload(&self, channel: Channel, preload: bool) {
617 let channel_index = channel.index(); 617 let channel_index = channel.index();
618 self.regs_gp16() 618 self.regs_gp16()
619 .ccmr_output(channel_index / 2) 619 .ccmr_output(channel_index / 2)
@@ -631,12 +631,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
631 } 631 }
632 632
633 /// Get capture compare DMA enable state 633 /// Get capture compare DMA enable state
634 pub fn get_cc_dma_enable_state(&self, channel: TimerChannel) -> bool { 634 pub fn get_cc_dma_enable_state(&self, channel: Channel) -> bool {
635 self.regs_gp16().dier().read().ccde(channel.index()) 635 self.regs_gp16().dier().read().ccde(channel.index())
636 } 636 }
637 637
638 /// Set capture compare DMA enable state 638 /// Set capture compare DMA enable state
639 pub fn set_cc_dma_enable_state(&self, channel: TimerChannel, ccde: bool) { 639 pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) {
640 self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) 640 self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde))
641 } 641 }
642 642
@@ -713,14 +713,14 @@ impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> {
713 } 713 }
714 714
715 /// Set complementary output polarity. 715 /// Set complementary output polarity.
716 pub fn set_complementary_output_polarity(&self, channel: TimerChannel, polarity: OutputPolarity) { 716 pub fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) {
717 self.regs_advanced() 717 self.regs_advanced()
718 .ccer() 718 .ccer()
719 .modify(|w| w.set_ccnp(channel.index(), polarity.into())); 719 .modify(|w| w.set_ccnp(channel.index(), polarity.into()));
720 } 720 }
721 721
722 /// Enable/disable a complementary channel. 722 /// Enable/disable a complementary channel.
723 pub fn enable_complementary_channel(&self, channel: TimerChannel, enable: bool) { 723 pub fn enable_complementary_channel(&self, channel: Channel, enable: bool) {
724 self.regs_advanced() 724 self.regs_advanced()
725 .ccer() 725 .ccer()
726 .modify(|w| w.set_ccne(channel.index(), enable)); 726 .modify(|w| w.set_ccne(channel.index(), enable));
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 362d95e25..7062f5f4c 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -19,7 +19,7 @@ use crate::rcc::RccPeripheral;
19 19
20/// Timer channel. 20/// Timer channel.
21#[derive(Clone, Copy)] 21#[derive(Clone, Copy)]
22pub enum TimerChannel { 22pub enum Channel {
23 /// Channel 1. 23 /// Channel 1.
24 Ch1, 24 Ch1,
25 /// Channel 2. 25 /// Channel 2.
@@ -30,14 +30,14 @@ pub enum TimerChannel {
30 Ch4, 30 Ch4,
31} 31}
32 32
33impl TimerChannel { 33impl Channel {
34 /// Get the channel index (0..3) 34 /// Get the channel index (0..3)
35 pub fn index(&self) -> usize { 35 pub fn index(&self) -> usize {
36 match self { 36 match self {
37 TimerChannel::Ch1 => 0, 37 Channel::Ch1 => 0,
38 TimerChannel::Ch2 => 1, 38 Channel::Ch2 => 1,
39 TimerChannel::Ch3 => 2, 39 Channel::Ch3 => 2,
40 TimerChannel::Ch4 => 3, 40 Channel::Ch4 => 3,
41 } 41 }
42 } 42 }
43} 43}
@@ -53,33 +53,33 @@ pub enum Ch4 {}
53 53
54/// Timer channel trait. 54/// Timer channel trait.
55#[allow(private_bounds)] 55#[allow(private_bounds)]
56pub trait Channel: SealedChannel { 56pub trait TimerChannel: SealedTimerChannel {
57 /// The runtime channel. 57 /// The runtime channel.
58 const CHANNEL: TimerChannel; 58 const CHANNEL: Channel;
59} 59}
60 60
61trait SealedChannel {} 61trait SealedTimerChannel {}
62 62
63impl Channel for Ch1 { 63impl TimerChannel for Ch1 {
64 const CHANNEL: TimerChannel = TimerChannel::Ch1; 64 const CHANNEL: Channel = Channel::Ch1;
65} 65}
66 66
67impl Channel for Ch2 { 67impl TimerChannel for Ch2 {
68 const CHANNEL: TimerChannel = TimerChannel::Ch2; 68 const CHANNEL: Channel = Channel::Ch2;
69} 69}
70 70
71impl Channel for Ch3 { 71impl TimerChannel for Ch3 {
72 const CHANNEL: TimerChannel = TimerChannel::Ch3; 72 const CHANNEL: Channel = Channel::Ch3;
73} 73}
74 74
75impl Channel for Ch4 { 75impl TimerChannel for Ch4 {
76 const CHANNEL: TimerChannel = TimerChannel::Ch4; 76 const CHANNEL: Channel = Channel::Ch4;
77} 77}
78 78
79impl SealedChannel for Ch1 {} 79impl SealedTimerChannel for Ch1 {}
80impl SealedChannel for Ch2 {} 80impl SealedTimerChannel for Ch2 {}
81impl SealedChannel for Ch3 {} 81impl SealedTimerChannel for Ch3 {}
82impl SealedChannel for Ch4 {} 82impl SealedTimerChannel for Ch4 {}
83 83
84/// Timer break input. 84/// Timer break input.
85#[derive(Clone, Copy)] 85#[derive(Clone, Copy)]
@@ -223,10 +223,10 @@ pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + Ad
223/// Advanced 16-bit timer with 4 channels instance. 223/// Advanced 16-bit timer with 4 channels instance.
224pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {} 224pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
225 225
226pin_trait!(TimerPin, GeneralInstance4Channel, Channel); 226pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel);
227pin_trait!(ExternalTriggerPin, GeneralInstance4Channel); 227pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
228 228
229pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, Channel); 229pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel);
230 230
231pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput); 231pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput);
232 232
@@ -236,7 +236,7 @@ pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput);
236// Update Event trigger DMA for every timer 236// Update Event trigger DMA for every timer
237dma_trait!(UpDma, BasicInstance); 237dma_trait!(UpDma, BasicInstance);
238 238
239dma_trait!(Dma, GeneralInstance4Channel, Channel); 239dma_trait!(Dma, GeneralInstance4Channel, TimerChannel);
240 240
241#[allow(unused)] 241#[allow(unused)]
242macro_rules! impl_core_timer { 242macro_rules! impl_core_timer {
diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs
index e89ad8390..c8f0cafe7 100644
--- a/embassy-stm32/src/timer/one_pulse.rs
+++ b/embassy-stm32/src/timer/one_pulse.rs
@@ -9,7 +9,7 @@ use core::task::{Context, Poll};
9use super::low_level::{ 9use super::low_level::{
10 CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts, 10 CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts,
11}; 11};
12use super::{CaptureCompareInterruptHandler, ExternalTriggerPin, GeneralInstance4Channel, TimerChannel, TimerPin}; 12use super::{CaptureCompareInterruptHandler, Channel, ExternalTriggerPin, GeneralInstance4Channel, TimerPin};
13pub use super::{Ch1, Ch2}; 13pub use super::{Ch1, Ch2};
14use crate::gpio::{AfType, AnyPin, Pull}; 14use crate::gpio::{AfType, AnyPin, Pull};
15use crate::interrupt::typelevel::{Binding, Interrupt}; 15use crate::interrupt::typelevel::{Binding, Interrupt};
@@ -76,7 +76,7 @@ impl<T, P, C> TimerTriggerPin<T, C> for P
76where 76where
77 T: GeneralInstance4Channel, 77 T: GeneralInstance4Channel,
78 P: TimerPin<T, C>, 78 P: TimerPin<T, C>,
79 C: super::Channel + TriggerSource, 79 C: super::TimerChannel + TriggerSource,
80{ 80{
81 fn af_num(&self) -> u8 { 81 fn af_num(&self) -> u8 {
82 TimerPin::af_num(self) 82 TimerPin::af_num(self)
@@ -97,7 +97,7 @@ impl<T, P, C> SealedTimerTriggerPin<T, C> for P
97where 97where
98 T: GeneralInstance4Channel, 98 T: GeneralInstance4Channel,
99 P: TimerPin<T, C>, 99 P: TimerPin<T, C>,
100 C: super::Channel + TriggerSource, 100 C: super::TimerChannel + TriggerSource,
101{ 101{
102} 102}
103 103
@@ -143,9 +143,9 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
143 143
144 this.inner.set_trigger_source(Ts::TI1F_ED); 144 this.inner.set_trigger_source(Ts::TI1F_ED);
145 this.inner 145 this.inner
146 .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); 146 .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
147 this.inner 147 this.inner
148 .set_input_capture_filter(TimerChannel::Ch1, FilterValue::NO_FILTER); 148 .set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER);
149 this.new_inner(freq, pulse_end, counting_mode); 149 this.new_inner(freq, pulse_end, counting_mode);
150 150
151 this 151 this
@@ -168,10 +168,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
168 168
169 this.inner.set_trigger_source(Ts::TI1FP1); 169 this.inner.set_trigger_source(Ts::TI1FP1);
170 this.inner 170 this.inner
171 .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); 171 .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
172 this.inner 172 this.inner
173 .set_input_capture_filter(TimerChannel::Ch1, FilterValue::NO_FILTER); 173 .set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER);
174 this.inner.set_input_capture_mode(TimerChannel::Ch1, capture_mode); 174 this.inner.set_input_capture_mode(Channel::Ch1, capture_mode);
175 this.new_inner(freq, pulse_end, counting_mode); 175 this.new_inner(freq, pulse_end, counting_mode);
176 176
177 this 177 this
@@ -194,10 +194,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
194 194
195 this.inner.set_trigger_source(Ts::TI2FP2); 195 this.inner.set_trigger_source(Ts::TI2FP2);
196 this.inner 196 this.inner
197 .set_input_ti_selection(TimerChannel::Ch2, InputTISelection::Normal); 197 .set_input_ti_selection(Channel::Ch2, InputTISelection::Normal);
198 this.inner 198 this.inner
199 .set_input_capture_filter(TimerChannel::Ch2, FilterValue::NO_FILTER); 199 .set_input_capture_filter(Channel::Ch2, FilterValue::NO_FILTER);
200 this.inner.set_input_capture_mode(TimerChannel::Ch2, capture_mode); 200 this.inner.set_input_capture_mode(Channel::Ch2, capture_mode);
201 this.new_inner(freq, pulse_end, counting_mode); 201 this.new_inner(freq, pulse_end, counting_mode);
202 202
203 this 203 this
@@ -269,7 +269,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
269 /// Get a single channel 269 /// Get a single channel
270 /// 270 ///
271 /// If you need to use multiple channels, use [`Self::split`]. 271 /// If you need to use multiple channels, use [`Self::split`].
272 pub fn channel(&mut self, channel: TimerChannel) -> OnePulseChannel<'_, T> { 272 pub fn channel(&mut self, channel: Channel) -> OnePulseChannel<'_, T> {
273 OnePulseChannel { 273 OnePulseChannel {
274 inner: unsafe { self.inner.clone_unchecked() }, 274 inner: unsafe { self.inner.clone_unchecked() },
275 channel, 275 channel,
@@ -282,7 +282,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
282 /// 282 ///
283 /// If you need to use multiple channels, use [`Self::split`]. 283 /// If you need to use multiple channels, use [`Self::split`].
284 pub fn ch1(&mut self) -> OnePulseChannel<'_, T> { 284 pub fn ch1(&mut self) -> OnePulseChannel<'_, T> {
285 self.channel(TimerChannel::Ch1) 285 self.channel(Channel::Ch1)
286 } 286 }
287 287
288 /// Channel 2 288 /// Channel 2
@@ -291,7 +291,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
291 /// 291 ///
292 /// If you need to use multiple channels, use [`Self::split`]. 292 /// If you need to use multiple channels, use [`Self::split`].
293 pub fn ch2(&mut self) -> OnePulseChannel<'_, T> { 293 pub fn ch2(&mut self) -> OnePulseChannel<'_, T> {
294 self.channel(TimerChannel::Ch2) 294 self.channel(Channel::Ch2)
295 } 295 }
296 296
297 /// Channel 3 297 /// Channel 3
@@ -300,7 +300,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
300 /// 300 ///
301 /// If you need to use multiple channels, use [`Self::split`]. 301 /// If you need to use multiple channels, use [`Self::split`].
302 pub fn ch3(&mut self) -> OnePulseChannel<'_, T> { 302 pub fn ch3(&mut self) -> OnePulseChannel<'_, T> {
303 self.channel(TimerChannel::Ch3) 303 self.channel(Channel::Ch3)
304 } 304 }
305 305
306 /// Channel 4 306 /// Channel 4
@@ -309,7 +309,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
309 /// 309 ///
310 /// If you need to use multiple channels, use [`Self::split`]. 310 /// If you need to use multiple channels, use [`Self::split`].
311 pub fn ch4(&mut self) -> OnePulseChannel<'_, T> { 311 pub fn ch4(&mut self) -> OnePulseChannel<'_, T> {
312 self.channel(TimerChannel::Ch4) 312 self.channel(Channel::Ch4)
313 } 313 }
314 314
315 /// Splits a [`OnePulse`] into four output channels. 315 /// Splits a [`OnePulse`] into four output channels.
@@ -328,10 +328,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
328 }; 328 };
329 329
330 OnePulseChannels { 330 OnePulseChannels {
331 ch1: ch(TimerChannel::Ch1), 331 ch1: ch(Channel::Ch1),
332 ch2: ch(TimerChannel::Ch2), 332 ch2: ch(Channel::Ch2),
333 ch3: ch(TimerChannel::Ch3), 333 ch3: ch(Channel::Ch3),
334 ch4: ch(TimerChannel::Ch4), 334 ch4: ch(Channel::Ch4),
335 } 335 }
336 } 336 }
337} 337}
@@ -355,7 +355,7 @@ pub struct OnePulseChannels<'d, T: GeneralInstance4Channel> {
355/// configuration is shared with all four channels. 355/// configuration is shared with all four channels.
356pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> { 356pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> {
357 inner: ManuallyDrop<Timer<'d, T>>, 357 inner: ManuallyDrop<Timer<'d, T>>,
358 channel: TimerChannel, 358 channel: Channel,
359} 359}
360 360
361impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { 361impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> {
@@ -402,7 +402,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> {
402 402
403#[must_use = "futures do nothing unless you `.await` or poll them"] 403#[must_use = "futures do nothing unless you `.await` or poll them"]
404struct OnePulseFuture<T: GeneralInstance4Channel> { 404struct OnePulseFuture<T: GeneralInstance4Channel> {
405 channel: TimerChannel, 405 channel: Channel,
406 phantom: PhantomData<T>, 406 phantom: PhantomData<T>,
407} 407}
408 408
diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs
index 3f9e5f651..2e05a0593 100644
--- a/embassy-stm32/src/timer/pwm_input.rs
+++ b/embassy-stm32/src/timer/pwm_input.rs
@@ -1,14 +1,14 @@
1//! PWM Input driver. 1//! PWM Input driver.
2 2
3use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource}; 3use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource};
4use super::{Ch1, Ch2, GeneralInstance4Channel, TimerChannel, TimerPin}; 4use super::{Ch1, Ch2, GeneralInstance4Channel, Channel, TimerPin};
5use crate::gpio::{AfType, Pull}; 5use crate::gpio::{AfType, Pull};
6use crate::time::Hertz; 6use crate::time::Hertz;
7use crate::Peri; 7use crate::Peri;
8 8
9/// PWM Input driver. 9/// PWM Input driver.
10pub struct PwmInput<'d, T: GeneralInstance4Channel> { 10pub struct PwmInput<'d, T: GeneralInstance4Channel> {
11 channel: TimerChannel, 11 channel: Channel,
12 inner: Timer<'d, T>, 12 inner: Timer<'d, T>,
13} 13}
14 14
@@ -17,17 +17,17 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
17 pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1>>, pull: Pull, freq: Hertz) -> Self { 17 pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1>>, pull: Pull, freq: Hertz) -> Self {
18 pin.set_as_af(pin.af_num(), AfType::input(pull)); 18 pin.set_as_af(pin.af_num(), AfType::input(pull));
19 19
20 Self::new_inner(tim, freq, TimerChannel::Ch1, TimerChannel::Ch2) 20 Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2)
21 } 21 }
22 22
23 /// Create a new PWM input driver. 23 /// Create a new PWM input driver.
24 pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull, freq: Hertz) -> Self { 24 pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull, freq: Hertz) -> Self {
25 pin.set_as_af(pin.af_num(), AfType::input(pull)); 25 pin.set_as_af(pin.af_num(), AfType::input(pull));
26 26
27 Self::new_inner(tim, freq, TimerChannel::Ch2, TimerChannel::Ch1) 27 Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1)
28 } 28 }
29 29
30 fn new_inner(tim: Peri<'d, T>, freq: Hertz, ch1: TimerChannel, ch2: TimerChannel) -> Self { 30 fn new_inner(tim: Peri<'d, T>, freq: Hertz, ch1: Channel, ch2: Channel) -> Self {
31 let mut inner = Timer::new(tim); 31 let mut inner = Timer::new(tim);
32 32
33 inner.set_counting_mode(CountingMode::EdgeAlignedUp); 33 inner.set_counting_mode(CountingMode::EdgeAlignedUp);
@@ -44,8 +44,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
44 inner.set_input_capture_mode(ch2, InputCaptureMode::Falling); 44 inner.set_input_capture_mode(ch2, InputCaptureMode::Falling);
45 45
46 inner.set_trigger_source(match ch1 { 46 inner.set_trigger_source(match ch1 {
47 TimerChannel::Ch1 => TriggerSource::TI1FP1, 47 Channel::Ch1 => TriggerSource::TI1FP1,
48 TimerChannel::Ch2 => TriggerSource::TI2FP2, 48 Channel::Ch2 => TriggerSource::TI2FP2,
49 _ => panic!("Invalid channel for PWM input"), 49 _ => panic!("Invalid channel for PWM input"),
50 }); 50 });
51 51
@@ -58,19 +58,19 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
58 58
59 /// Enable the given channel. 59 /// Enable the given channel.
60 pub fn enable(&mut self) { 60 pub fn enable(&mut self) {
61 self.inner.enable_channel(TimerChannel::Ch1, true); 61 self.inner.enable_channel(Channel::Ch1, true);
62 self.inner.enable_channel(TimerChannel::Ch2, true); 62 self.inner.enable_channel(Channel::Ch2, true);
63 } 63 }
64 64
65 /// Disable the given channel. 65 /// Disable the given channel.
66 pub fn disable(&mut self) { 66 pub fn disable(&mut self) {
67 self.inner.enable_channel(TimerChannel::Ch1, false); 67 self.inner.enable_channel(Channel::Ch1, false);
68 self.inner.enable_channel(TimerChannel::Ch2, false); 68 self.inner.enable_channel(Channel::Ch2, false);
69 } 69 }
70 70
71 /// Check whether given channel is enabled 71 /// Check whether given channel is enabled
72 pub fn is_enabled(&self) -> bool { 72 pub fn is_enabled(&self) -> bool {
73 self.inner.get_channel_enable_state(TimerChannel::Ch1) 73 self.inner.get_channel_enable_state(Channel::Ch1)
74 } 74 }
75 75
76 /// Get the period tick count 76 /// Get the period tick count
@@ -81,8 +81,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
81 /// Get the pulse width tick count 81 /// Get the pulse width tick count
82 pub fn get_width_ticks(&self) -> u32 { 82 pub fn get_width_ticks(&self) -> u32 {
83 self.inner.get_capture_value(match self.channel { 83 self.inner.get_capture_value(match self.channel {
84 TimerChannel::Ch1 => TimerChannel::Ch2, 84 Channel::Ch1 => Channel::Ch2,
85 TimerChannel::Ch2 => TimerChannel::Ch1, 85 Channel::Ch2 => Channel::Ch1,
86 _ => panic!("Invalid channel for PWM input"), 86 _ => panic!("Invalid channel for PWM input"),
87 }) 87 })
88 } 88 }
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index 657052cfa..eabe1b22a 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -8,7 +8,7 @@ use super::low_level::Timer;
8pub use super::{Ch1, Ch2}; 8pub use super::{Ch1, Ch2};
9use super::{GeneralInstance4Channel, TimerPin}; 9use super::{GeneralInstance4Channel, TimerPin};
10use crate::gpio::{AfType, AnyPin, Pull}; 10use crate::gpio::{AfType, AnyPin, Pull};
11use crate::timer::Channel; 11use crate::timer::TimerChannel;
12use crate::Peri; 12use crate::Peri;
13 13
14/// Counting direction 14/// Counting direction
@@ -39,7 +39,7 @@ impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> {
39 } 39 }
40} 40}
41 41
42trait SealedQeiChannel: Channel {} 42trait SealedQeiChannel: TimerChannel {}
43 43
44/// Marker trait for a timer channel eligible for use with QEI. 44/// Marker trait for a timer channel eligible for use with QEI.
45#[expect(private_bounds)] 45#[expect(private_bounds)]
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 02835c379..c04b1ab97 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -4,7 +4,7 @@ use core::marker::PhantomData;
4use core::mem::ManuallyDrop; 4use core::mem::ManuallyDrop;
5 5
6use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer}; 6use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer};
7use super::{Ch1, Ch2, Ch3, Ch4, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin}; 7use super::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin};
8#[cfg(gpio_v2)] 8#[cfg(gpio_v2)]
9use crate::gpio::Pull; 9use crate::gpio::Pull;
10use crate::gpio::{AfType, AnyPin, OutputType, Speed}; 10use crate::gpio::{AfType, AnyPin, OutputType, Speed};
@@ -34,46 +34,37 @@ pub struct PwmPinConfig {
34 pub pull: Pull, 34 pub pull: Pull,
35} 35}
36 36
37macro_rules! channel_impl { 37impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
38 ($new_chx:ident, $new_chx_with_config:ident, $channel:ident, $pin_trait:ident) => { 38 /// Create a new PWM pin instance.
39 impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> { 39 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, output_type: OutputType) -> Self {
40 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")] 40 critical_section::with(|_| {
41 pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T, $channel>>, output_type: OutputType) -> Self { 41 pin.set_low();
42 critical_section::with(|_| { 42 pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
43 pin.set_low(); 43 });
44 pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); 44 PwmPin {
45 }); 45 _pin: pin.into(),
46 PwmPin { 46 phantom: PhantomData,
47 _pin: pin.into(),
48 phantom: PhantomData,
49 }
50 }
51
52 #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance with config.")]
53 pub fn $new_chx_with_config(pin: Peri<'d, impl $pin_trait<T, $channel>>, pin_config: PwmPinConfig) -> Self {
54 critical_section::with(|_| {
55 pin.set_low();
56 pin.set_as_af(
57 pin.af_num(),
58 #[cfg(gpio_v1)]
59 AfType::output(pin_config.output_type, pin_config.speed),
60 #[cfg(gpio_v2)]
61 AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
62 );
63 });
64 PwmPin {
65 _pin: pin.into(),
66 phantom: PhantomData,
67 }
68 }
69 } 47 }
70 }; 48 }
71}
72 49
73channel_impl!(new_ch1, new_ch1_with_config, Ch1, TimerPin); 50 /// Create a new PWM pin instance with config.
74channel_impl!(new_ch2, new_ch2_with_config, Ch2, TimerPin); 51 pub fn new_with_config(pin: Peri<'d, impl TimerPin<T, C>>, pin_config: PwmPinConfig) -> Self {
75channel_impl!(new_ch3, new_ch3_with_config, Ch3, TimerPin); 52 critical_section::with(|_| {
76channel_impl!(new_ch4, new_ch4_with_config, Ch4, TimerPin); 53 pin.set_low();
54 pin.set_as_af(
55 pin.af_num(),
56 #[cfg(gpio_v1)]
57 AfType::output(pin_config.output_type, pin_config.speed),
58 #[cfg(gpio_v2)]
59 AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
60 );
61 });
62 PwmPin {
63 _pin: pin.into(),
64 phantom: PhantomData,
65 }
66 }
67}
77 68
78/// A single channel of a pwm, obtained from [`SimplePwm::split`], 69/// A single channel of a pwm, obtained from [`SimplePwm::split`],
79/// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc. 70/// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc.
@@ -82,7 +73,7 @@ channel_impl!(new_ch4, new_ch4_with_config, Ch4, TimerPin);
82/// the frequency configuration is shared with all four channels. 73/// the frequency configuration is shared with all four channels.
83pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> { 74pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> {
84 timer: ManuallyDrop<Timer<'d, T>>, 75 timer: ManuallyDrop<Timer<'d, T>>,
85 channel: TimerChannel, 76 channel: Channel,
86} 77}
87 78
88// TODO: check for RMW races 79// TODO: check for RMW races
@@ -207,18 +198,13 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
207 this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details 198 this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details
208 this.inner.start(); 199 this.inner.start();
209 200
210 [ 201 [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
211 TimerChannel::Ch1, 202 .iter()
212 TimerChannel::Ch2, 203 .for_each(|&channel| {
213 TimerChannel::Ch3, 204 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
214 TimerChannel::Ch4, 205
215 ] 206 this.inner.set_output_compare_preload(channel, true);
216 .iter() 207 });
217 .for_each(|&channel| {
218 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
219
220 this.inner.set_output_compare_preload(channel, true);
221 });
222 208
223 this 209 this
224 } 210 }
@@ -226,7 +212,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
226 /// Get a single channel 212 /// Get a single channel
227 /// 213 ///
228 /// If you need to use multiple channels, use [`Self::split`]. 214 /// If you need to use multiple channels, use [`Self::split`].
229 pub fn channel(&mut self, channel: TimerChannel) -> SimplePwmChannel<'_, T> { 215 pub fn channel(&mut self, channel: Channel) -> SimplePwmChannel<'_, T> {
230 SimplePwmChannel { 216 SimplePwmChannel {
231 timer: unsafe { self.inner.clone_unchecked() }, 217 timer: unsafe { self.inner.clone_unchecked() },
232 channel, 218 channel,
@@ -239,7 +225,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
239 /// 225 ///
240 /// If you need to use multiple channels, use [`Self::split`]. 226 /// If you need to use multiple channels, use [`Self::split`].
241 pub fn ch1(&mut self) -> SimplePwmChannel<'_, T> { 227 pub fn ch1(&mut self) -> SimplePwmChannel<'_, T> {
242 self.channel(TimerChannel::Ch1) 228 self.channel(Channel::Ch1)
243 } 229 }
244 230
245 /// Channel 2 231 /// Channel 2
@@ -248,7 +234,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
248 /// 234 ///
249 /// If you need to use multiple channels, use [`Self::split`]. 235 /// If you need to use multiple channels, use [`Self::split`].
250 pub fn ch2(&mut self) -> SimplePwmChannel<'_, T> { 236 pub fn ch2(&mut self) -> SimplePwmChannel<'_, T> {
251 self.channel(TimerChannel::Ch2) 237 self.channel(Channel::Ch2)
252 } 238 }
253 239
254 /// Channel 3 240 /// Channel 3
@@ -257,7 +243,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
257 /// 243 ///
258 /// If you need to use multiple channels, use [`Self::split`]. 244 /// If you need to use multiple channels, use [`Self::split`].
259 pub fn ch3(&mut self) -> SimplePwmChannel<'_, T> { 245 pub fn ch3(&mut self) -> SimplePwmChannel<'_, T> {
260 self.channel(TimerChannel::Ch3) 246 self.channel(Channel::Ch3)
261 } 247 }
262 248
263 /// Channel 4 249 /// Channel 4
@@ -266,7 +252,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
266 /// 252 ///
267 /// If you need to use multiple channels, use [`Self::split`]. 253 /// If you need to use multiple channels, use [`Self::split`].
268 pub fn ch4(&mut self) -> SimplePwmChannel<'_, T> { 254 pub fn ch4(&mut self) -> SimplePwmChannel<'_, T> {
269 self.channel(TimerChannel::Ch4) 255 self.channel(Channel::Ch4)
270 } 256 }
271 257
272 /// Splits a [`SimplePwm`] into four pwm channels. 258 /// Splits a [`SimplePwm`] into four pwm channels.
@@ -288,10 +274,10 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
288 }; 274 };
289 275
290 SimplePwmChannels { 276 SimplePwmChannels {
291 ch1: ch(TimerChannel::Ch1), 277 ch1: ch(Channel::Ch1),
292 ch2: ch(TimerChannel::Ch2), 278 ch2: ch(Channel::Ch2),
293 ch3: ch(TimerChannel::Ch3), 279 ch3: ch(Channel::Ch3),
294 ch4: ch(TimerChannel::Ch4), 280 ch4: ch(Channel::Ch4),
295 } 281 }
296 } 282 }
297 283
@@ -322,7 +308,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
322 /// 308 ///
323 /// Note: 309 /// Note:
324 /// you will need to provide corresponding TIMx_UP DMA channel to use this method. 310 /// you will need to provide corresponding TIMx_UP DMA channel to use this method.
325 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: TimerChannel, duty: &[u16]) { 311 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) {
326 #[allow(clippy::let_unit_value)] // eg. stm32f334 312 #[allow(clippy::let_unit_value)] // eg. stm32f334
327 let req = dma.request(); 313 let req = dma.request();
328 314
@@ -405,8 +391,8 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
405 pub async fn waveform_up_multi_channel( 391 pub async fn waveform_up_multi_channel(
406 &mut self, 392 &mut self,
407 dma: Peri<'_, impl super::UpDma<T>>, 393 dma: Peri<'_, impl super::UpDma<T>>,
408 starting_channel: TimerChannel, 394 starting_channel: Channel,
409 ending_channel: TimerChannel, 395 ending_channel: Channel,
410 duty: &[u16], 396 duty: &[u16],
411 ) { 397 ) {
412 let cr1_addr = self.inner.regs_gp16().cr1().as_ptr() as u32; 398 let cr1_addr = self.inner.regs_gp16().cr1().as_ptr() as u32;
@@ -462,106 +448,97 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
462 } 448 }
463} 449}
464 450
465macro_rules! impl_waveform_chx { 451impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
466 ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { 452 /// Generate a sequence of PWM waveform
467 impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { 453 pub async fn waveform<C: TimerChannel>(&mut self, dma: Peri<'_, impl super::Dma<T, C>>, duty: &[u16]) {
468 /// Generate a sequence of PWM waveform 454 use crate::pac::timer::vals::Ccds;
469 pub async fn $fn_name(&mut self, dma: Peri<'_, impl super::$dma_ch<T, $cc_ch>>, duty: &[u16]) {
470 use crate::pac::timer::vals::Ccds;
471 455
472 #[allow(clippy::let_unit_value)] // eg. stm32f334 456 #[allow(clippy::let_unit_value)] // eg. stm32f334
473 let req = dma.request(); 457 let req = dma.request();
474 458
475 let cc_channel = TimerChannel::$cc_ch; 459 let cc_channel = C::CHANNEL;
476 460
477 let original_duty_state = self.channel(cc_channel).current_duty_cycle(); 461 let original_duty_state = self.channel(cc_channel).current_duty_cycle();
478 let original_enable_state = self.channel(cc_channel).is_enabled(); 462 let original_enable_state = self.channel(cc_channel).is_enabled();
479 let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE; 463 let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE;
480 let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel); 464 let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel);
481 465
482 // redirect CC DMA request onto Update Event 466 // redirect CC DMA request onto Update Event
483 if !original_cc_dma_on_update { 467 if !original_cc_dma_on_update {
484 self.inner.set_cc_dma_selection(Ccds::ON_UPDATE) 468 self.inner.set_cc_dma_selection(Ccds::ON_UPDATE)
485 } 469 }
486 470
487 if !original_cc_dma_enabled { 471 if !original_cc_dma_enabled {
488 self.inner.set_cc_dma_enable_state(cc_channel, true); 472 self.inner.set_cc_dma_enable_state(cc_channel, true);
489 } 473 }
490 474
491 if !original_enable_state { 475 if !original_enable_state {
492 self.channel(cc_channel).enable(); 476 self.channel(cc_channel).enable();
493 } 477 }
494 478
495 unsafe { 479 unsafe {
480 #[cfg(not(any(bdma, gpdma)))]
481 use crate::dma::{Burst, FifoThreshold};
482 use crate::dma::{Transfer, TransferOptions};
483
484 let dma_transfer_option = TransferOptions {
485 #[cfg(not(any(bdma, gpdma)))]
486 fifo_threshold: Some(FifoThreshold::Full),
487 #[cfg(not(any(bdma, gpdma)))]
488 mburst: Burst::Incr8,
489 ..Default::default()
490 };
491
492 match self.inner.bits() {
493 TimerBits::Bits16 => {
494 Transfer::new_write(
495 dma,
496 req,
497 duty,
498 self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16,
499 dma_transfer_option,
500 )
501 .await
502 }
503 #[cfg(not(any(stm32l0)))]
504 TimerBits::Bits32 => {
496 #[cfg(not(any(bdma, gpdma)))] 505 #[cfg(not(any(bdma, gpdma)))]
497 use crate::dma::{Burst, FifoThreshold}; 506 panic!("unsupported timer bits");
498 use crate::dma::{Transfer, TransferOptions}; 507
499 508 #[cfg(any(bdma, gpdma))]
500 let dma_transfer_option = TransferOptions { 509 Transfer::new_write(
501 #[cfg(not(any(bdma, gpdma)))] 510 dma,
502 fifo_threshold: Some(FifoThreshold::Full), 511 req,
503 #[cfg(not(any(bdma, gpdma)))] 512 duty,
504 mburst: Burst::Incr8, 513 self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32,
505 ..Default::default() 514 dma_transfer_option,
506 }; 515 )
507 516 .await
508 match self.inner.bits() {
509 TimerBits::Bits16 => {
510 Transfer::new_write(
511 dma,
512 req,
513 duty,
514 self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16,
515 dma_transfer_option,
516 )
517 .await
518 }
519 #[cfg(not(any(stm32l0)))]
520 TimerBits::Bits32 => {
521 #[cfg(not(any(bdma, gpdma)))]
522 panic!("unsupported timer bits");
523
524 #[cfg(any(bdma, gpdma))]
525 Transfer::new_write(
526 dma,
527 req,
528 duty,
529 self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32,
530 dma_transfer_option,
531 )
532 .await
533 }
534 };
535 };
536
537 // restore output compare state
538 if !original_enable_state {
539 self.channel(cc_channel).disable();
540 } 517 }
518 };
519 };
541 520
542 self.channel(cc_channel).set_duty_cycle(original_duty_state); 521 // restore output compare state
522 if !original_enable_state {
523 self.channel(cc_channel).disable();
524 }
543 525
544 // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off, 526 self.channel(cc_channel).set_duty_cycle(original_duty_state);
545 // this can almost always trigger a DMA FIFO error.
546 //
547 // optional TODO:
548 // clean FEIF after disable UDE
549 if !original_cc_dma_enabled {
550 self.inner.set_cc_dma_enable_state(cc_channel, false);
551 }
552 527
553 if !original_cc_dma_on_update { 528 // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off,
554 self.inner.set_cc_dma_selection(Ccds::ON_COMPARE) 529 // this can almost always trigger a DMA FIFO error.
555 } 530 //
556 } 531 // optional TODO:
532 // clean FEIF after disable UDE
533 if !original_cc_dma_enabled {
534 self.inner.set_cc_dma_enable_state(cc_channel, false);
557 } 535 }
558 };
559}
560 536
561impl_waveform_chx!(waveform_ch1, Dma, Ch1); 537 if !original_cc_dma_on_update {
562impl_waveform_chx!(waveform_ch2, Dma, Ch2); 538 self.inner.set_cc_dma_selection(Ccds::ON_COMPARE)
563impl_waveform_chx!(waveform_ch3, Dma, Ch3); 539 }
564impl_waveform_chx!(waveform_ch4, Dma, Ch4); 540 }
541}
565 542
566impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> { 543impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> {
567 type Error = core::convert::Infallible; 544 type Error = core::convert::Infallible;
@@ -599,7 +576,7 @@ impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for Simpl
599} 576}
600 577
601impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> { 578impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> {
602 type Channel = TimerChannel; 579 type Channel = Channel;
603 type Time = Hertz; 580 type Time = Hertz;
604 type Duty = u32; 581 type Duty = u32;
605 582