aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchemicstry <[email protected]>2022-06-23 02:27:39 +0300
committerchemicstry <[email protected]>2022-06-23 02:27:39 +0300
commit3cdd8c1aebaebd7464fa3477ce63525a101dcf72 (patch)
treeb2884853b64b9790e8d5613f2c2193260eee6972
parent4a6f69e2d9e1c18ff5999a6aa049c280a6b8dcc4 (diff)
Fix PWM for advanced timers
-rw-r--r--embassy-stm32/src/pwm/mod.rs44
-rw-r--r--embassy-stm32/src/pwm/simple_pwm.rs2
-rw-r--r--examples/stm32f4/src/bin/pwm.rs42
3 files changed, 56 insertions, 32 deletions
diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs
index bd8358563..674740cc5 100644
--- a/embassy-stm32/src/pwm/mod.rs
+++ b/embassy-stm32/src/pwm/mod.rs
@@ -55,6 +55,9 @@ pub(crate) mod sealed {
55 use super::*; 55 use super::*;
56 56
57 pub trait CaptureCompare16bitInstance: crate::timer::sealed::Basic16bitInstance { 57 pub trait CaptureCompare16bitInstance: crate::timer::sealed::Basic16bitInstance {
58 /// Global output enable. Does not do anything on non-advanced timers.
59 unsafe fn enable_outputs(&mut self, enable: bool);
60
58 unsafe fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); 61 unsafe fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
59 62
60 unsafe fn enable_channel(&mut self, channel: Channel, enable: bool); 63 unsafe fn enable_channel(&mut self, channel: Channel, enable: bool);
@@ -88,6 +91,8 @@ pub trait CaptureCompare32bitInstance:
88macro_rules! impl_compare_capable_16bit { 91macro_rules! impl_compare_capable_16bit {
89 ($inst:ident) => { 92 ($inst:ident) => {
90 impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { 93 impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
94 unsafe fn enable_outputs(&mut self, _enable: bool) {}
95
91 unsafe fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) { 96 unsafe fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) {
92 use crate::timer::sealed::GeneralPurpose16bitInstance; 97 use crate::timer::sealed::GeneralPurpose16bitInstance;
93 let r = Self::regs_gp16(); 98 let r = Self::regs_gp16();
@@ -118,38 +123,7 @@ macro_rules! impl_compare_capable_16bit {
118 123
119foreach_interrupt! { 124foreach_interrupt! {
120 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { 125 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
121 impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { 126 impl_compare_capable_16bit!($inst);
122 unsafe fn set_output_compare_mode(
123 &mut self,
124 channel: crate::pwm::Channel,
125 mode: OutputCompareMode,
126 ) {
127 use crate::timer::sealed::GeneralPurpose16bitInstance;
128 let r = Self::regs_gp16();
129 let raw_channel: usize = channel.raw();
130 r.ccmr_output(raw_channel / 2)
131 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
132 }
133
134 unsafe fn enable_channel(&mut self, channel: Channel, enable: bool) {
135 use crate::timer::sealed::GeneralPurpose16bitInstance;
136 Self::regs_gp16()
137 .ccer()
138 .modify(|w| w.set_cce(channel.raw(), enable));
139 }
140
141 unsafe fn set_compare_value(&mut self, channel: Channel, value: u16) {
142 use crate::timer::sealed::GeneralPurpose16bitInstance;
143 Self::regs_gp16()
144 .ccr(channel.raw())
145 .modify(|w| w.set_ccr(value));
146 }
147
148 unsafe fn get_max_compare_value(&self) -> u16 {
149 use crate::timer::sealed::GeneralPurpose16bitInstance;
150 Self::regs_gp16().arr().read().arr()
151 }
152 }
153 127
154 impl CaptureCompare16bitInstance for crate::peripherals::$inst { 128 impl CaptureCompare16bitInstance for crate::peripherals::$inst {
155 129
@@ -194,6 +168,12 @@ foreach_interrupt! {
194 168
195 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { 169 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
196 impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { 170 impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
171 unsafe fn enable_outputs(&mut self, enable: bool) {
172 use crate::timer::sealed::AdvancedControlInstance;
173 let r = Self::regs_advanced();
174 r.bdtr().modify(|w| w.set_moe(enable));
175 }
176
197 unsafe fn set_output_compare_mode( 177 unsafe fn set_output_compare_mode(
198 &mut self, 178 &mut self,
199 channel: crate::pwm::Channel, 179 channel: crate::pwm::Channel,
diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/pwm/simple_pwm.rs
index a475f3f70..049a64027 100644
--- a/embassy-stm32/src/pwm/simple_pwm.rs
+++ b/embassy-stm32/src/pwm/simple_pwm.rs
@@ -92,6 +92,8 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
92 this.inner.start(); 92 this.inner.start();
93 93
94 unsafe { 94 unsafe {
95 this.inner.enable_outputs(true);
96
95 this.inner 97 this.inner
96 .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); 98 .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1);
97 this.inner 99 this.inner
diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs
new file mode 100644
index 000000000..4073f5385
--- /dev/null
+++ b/examples/stm32f4/src/bin/pwm.rs
@@ -0,0 +1,42 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy::executor::Spawner;
7use embassy::time::{Duration, Timer};
8use embassy_stm32::pwm::simple_pwm::SimplePwm;
9use embassy_stm32::pwm::Channel;
10use embassy_stm32::time::{Hertz, U32Ext};
11use embassy_stm32::{Config, Peripherals};
12use {defmt_rtt as _, panic_probe as _};
13
14fn config() -> Config {
15 let mut config = Config::default();
16 config.rcc.hse = Some(Hertz(8_000_000));
17 config.rcc.sys_ck = Some(Hertz(84_000_000));
18 config
19}
20
21#[embassy::main(config = "config()")]
22async fn main(_spawner: Spawner, p: Peripherals) {
23 info!("Hello World!");
24
25 let mut pwm = SimplePwm::new_1ch(p.TIM1, p.PE9, 10000.hz());
26 let max = pwm.get_max_duty();
27 pwm.enable(Channel::Ch1);
28
29 info!("PWM initialized");
30 info!("PWM max duty {}", max);
31
32 loop {
33 pwm.set_duty(Channel::Ch1, 0);
34 Timer::after(Duration::from_millis(300)).await;
35 pwm.set_duty(Channel::Ch1, max / 4);
36 Timer::after(Duration::from_millis(300)).await;
37 pwm.set_duty(Channel::Ch1, max / 2);
38 Timer::after(Duration::from_millis(300)).await;
39 pwm.set_duty(Channel::Ch1, max - 1);
40 Timer::after(Duration::from_millis(300)).await;
41 }
42}