aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-06-22 23:33:29 +0000
committerGitHub <[email protected]>2022-06-22 23:33:29 +0000
commitcf69f78162cb60e436789c446209fb6e51c77b48 (patch)
treedbc332ca590262e20ac1bb4ef034584542e39b27
parent4a6f69e2d9e1c18ff5999a6aa049c280a6b8dcc4 (diff)
parent88c37377228f824a09a22b2f49900dd0ec8b72bb (diff)
Merge #827
827: Fix PWM for advanced timers r=Dirbaio a=chemicstry Advanced timers have additional BDTR register, which has a global output enable bit and it is disabled by default. Also added an example for F4, but it will only work once https://github.com/embassy-rs/stm32-data/pull/149 is merged. We can also move it to some other chip, but I don't have anything else to test on atm. Co-authored-by: chemicstry <[email protected]>
-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.rs35
3 files changed, 49 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..cd20c68bb
--- /dev/null
+++ b/examples/stm32f4/src/bin/pwm.rs
@@ -0,0 +1,35 @@
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::U32Ext;
11use embassy_stm32::Peripherals;
12use {defmt_rtt as _, panic_probe as _};
13
14#[embassy::main]
15async fn main(_spawner: Spawner, p: Peripherals) {
16 info!("Hello World!");
17
18 let mut pwm = SimplePwm::new_1ch(p.TIM1, p.PE9, 10000.hz());
19 let max = pwm.get_max_duty();
20 pwm.enable(Channel::Ch1);
21
22 info!("PWM initialized");
23 info!("PWM max duty {}", max);
24
25 loop {
26 pwm.set_duty(Channel::Ch1, 0);
27 Timer::after(Duration::from_millis(300)).await;
28 pwm.set_duty(Channel::Ch1, max / 4);
29 Timer::after(Duration::from_millis(300)).await;
30 pwm.set_duty(Channel::Ch1, max / 2);
31 Timer::after(Duration::from_millis(300)).await;
32 pwm.set_duty(Channel::Ch1, max - 1);
33 Timer::after(Duration::from_millis(300)).await;
34 }
35}