Skip to content

move PWM pins connecting after inialization #791

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- RTC: `ClockSource` enum instead of generic [#785]
- Bump MSRV to 1.62 [#778]
- Move PWM pins connecting after PWM inialization [#791]
- Use `stm32f4-staging` until `stm32f4` is released [#706]
- use GPIO pac fields instead of raw write [#777]
- RTIC2 monotonics fix: CC1 instead of CC3 [#771]
Expand Down Expand Up @@ -51,6 +52,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
[#778]: https://github.com/stm32-rs/stm32f4xx-hal/pull/778
[#783]: https://github.com/stm32-rs/stm32f4xx-hal/pull/783
[#785]: https://github.com/stm32-rs/stm32f4xx-hal/pull/785
[#791]: https://github.com/stm32-rs/stm32f4xx-hal/pull/791
[#796]: https://github.com/stm32-rs/stm32f4xx-hal/pull/796

## [v0.21.0] - 2024-05-30
Expand Down
25 changes: 10 additions & 15 deletions examples/pwm-dead-time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,7 @@ use panic_halt as _; // panic handler
use cortex_m_rt::entry;
use stm32f4xx_hal as hal;

use hal::{
pac,
prelude::*,
timer::Channel,
timer::{Channel1, Polarity},
};
use hal::{pac, prelude::*, timer::Polarity};

#[entry]
fn main() -> ! {
Expand All @@ -25,21 +20,21 @@ fn main() -> ! {

let gpioa = dp.GPIOA.split();

let channels = Channel1::new(gpioa.pa8).with_complementary(gpioa.pa7);
let (mut pwm_mngr, (pwm_c1, ..)) = dp.TIM1.pwm_hz(20.kHz(), &clocks);

let mut pwm = dp.TIM1.pwm_hz(channels, 20.kHz(), &clocks);
let mut pwm_c1 = pwm_c1.with(gpioa.pa8).with_complementary(gpioa.pa7);

let max_duty: u16 = pwm.get_max_duty();
let max_duty: u16 = pwm_c1.get_max_duty();

pwm.set_polarity(Channel::C1, Polarity::ActiveHigh);
pwm.set_complementary_polarity(Channel::C1, Polarity::ActiveHigh);
pwm_c1.set_polarity(Polarity::ActiveHigh);
pwm_c1.set_complementary_polarity(Polarity::ActiveHigh);

pwm.set_duty(Channel::C1, max_duty / 2);
pwm_c1.set_duty(max_duty / 2);

pwm.set_dead_time(200);
pwm_mngr.set_dead_time(200);

pwm.enable(Channel::C1);
pwm.enable_complementary(Channel::C1);
pwm_c1.enable();
pwm_c1.enable_complementary();
}

loop {
Expand Down
12 changes: 4 additions & 8 deletions examples/pwm-input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@
use panic_halt as _;

use cortex_m_rt::entry;
use stm32f4xx_hal::{
pac,
prelude::*,
timer::{Channel1, Channel2, Timer},
};
use stm32f4xx_hal::{pac, prelude::*, timer::Timer};

#[entry]
fn main() -> ! {
Expand All @@ -22,10 +18,10 @@ fn main() -> ! {
let gpioa = dp.GPIOA.split();
let gpioc = dp.GPIOC.split();

let channels = (Channel1::new(gpioa.pa8), Channel2::new(gpioa.pa9));
// configure tim1 as a PWM output of known frequency.
let pwm = Timer::new(dp.TIM1, &clocks).pwm_hz(channels, 501.Hz());
let (mut ch1, _ch2) = pwm.split();
let (_, (ch1, ch2, ..)) = Timer::new(dp.TIM1, &clocks).pwm_hz(501.Hz());
let mut ch1 = ch1.with(gpioa.pa8);
let mut _ch2 = ch2.with(gpioa.pa9);
let max_duty = ch1.get_max_duty();
ch1.set_duty(max_duty / 2);
ch1.enable();
Expand Down
30 changes: 14 additions & 16 deletions examples/pwm-sinus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ use panic_halt as _;
use core::f32::consts::FRAC_PI_2;
use cortex_m_rt::entry;
use micromath::F32Ext;
use stm32f4xx_hal::{
pac,
prelude::*,
timer::{Channel, Channel1, Channel2},
};
use stm32f4xx_hal::{pac, prelude::*};

#[entry]
fn main() -> ! {
Expand All @@ -22,11 +18,13 @@ fn main() -> ! {
let clocks = rcc.cfgr.use_hse(25.MHz()).freeze();

let gpioa = dp.GPIOA.split();
let channels = (Channel1::new(gpioa.pa8), Channel2::new(gpioa.pa9));

let mut pwm = dp.TIM1.pwm_us(channels, 100.micros(), &clocks);
let (_, (pwm_c1, pwm_c2, ..)) = dp.TIM1.pwm_us(100.micros(), &clocks);
let mut pwm_c1 = pwm_c1.with(gpioa.pa8);
let mut pwm_c2 = pwm_c2.with(gpioa.pa9);

let mut counter = dp.TIM2.counter_us(&clocks);
let max_duty = pwm.get_max_duty();
let max_duty = pwm_c1.get_max_duty();

const N: usize = 50;
let mut sin_a = [0_u16; N + 1];
Expand All @@ -38,24 +36,24 @@ fn main() -> ! {
}

counter.start(100.micros()).unwrap();
pwm.enable(Channel::C1);
pwm.enable(Channel::C2);
pwm_c1.enable();
pwm_c2.enable();
let mut i = 0;
loop {
if i == 0 {
pwm.set_duty(Channel::C2, 0);
pwm_c2.set_duty(0);
}
if i == 2 * N {
pwm.set_duty(Channel::C1, 0);
pwm_c1.set_duty(0);
}
if i < N {
pwm.set_duty(Channel::C1, sin_a[i]);
pwm_c1.set_duty(sin_a[i]);
} else if i < 2 * N {
pwm.set_duty(Channel::C1, sin_a[2 * N - i]);
pwm_c1.set_duty(sin_a[2 * N - i]);
} else if i < 3 * N {
pwm.set_duty(Channel::C2, sin_a[i - 2 * N]);
pwm_c2.set_duty(sin_a[i - 2 * N]);
} else {
pwm.set_duty(Channel::C2, sin_a[4 * N - i]);
pwm_c2.set_duty(sin_a[4 * N - i]);
}
nb::block!(counter.wait()).unwrap();
i += 1;
Expand Down
13 changes: 5 additions & 8 deletions examples/pwm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@
use panic_halt as _;

use cortex_m_rt::entry;
use stm32f4xx_hal::{
pac,
prelude::*,
timer::{Channel1, Channel2},
};
use stm32f4xx_hal::{pac, prelude::*};

#[entry]
fn main() -> ! {
Expand All @@ -20,10 +16,11 @@ fn main() -> ! {
let clocks = rcc.cfgr.freeze();

let gpioa = dp.GPIOA.split();
let channels = (Channel1::new(gpioa.pa8), Channel2::new(gpioa.pa9));

let pwm = dp.TIM1.pwm_hz(channels, 20.kHz(), &clocks).split();
let (mut ch1, _ch2) = pwm;
let (_, (ch1, ch2, ..)) = dp.TIM1.pwm_us(100.micros(), &clocks);
let mut ch1 = ch1.with(gpioa.pa8);
let mut _ch2 = ch2.with(gpioa.pa9);

let max_duty = ch1.get_max_duty();
ch1.set_duty(max_duty / 2);
ch1.enable();
Expand Down
71 changes: 58 additions & 13 deletions src/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ pub type CCR4<T> = CCR<T, 3>;
pub struct DMAR<T>(T);

mod sealed {
use super::{BitFlags, Channel, Event, Flag, IdleState, Ocm, Polarity};
use super::{BitFlags, Event, Flag, IdleState, Ocm, Polarity};
pub trait General {
type Width: Into<u32> + From<u16>;
fn max_auto_reload() -> u32;
Expand Down Expand Up @@ -364,14 +364,20 @@ mod sealed {
}

pub trait WithPwm: WithPwmCommon {
fn preload_output_channel_in_mode(&mut self, channel: Channel, mode: Ocm);
fn preload_output_channel_in_mode(&mut self, c: u8, mode: Ocm);
fn freeze_output_channel(&mut self, c: u8);
fn start_pwm(&mut self);
}

pub trait MasterTimer: General {
type Mms;
fn master_mode(&mut self, mode: Self::Mms);
}

pub trait Split {
type Channels;
fn split() -> Self::Channels;
}
}
pub(crate) use sealed::{Advanced, General, MasterTimer, WithPwm, WithPwmCommon};

Expand All @@ -380,6 +386,27 @@ pub trait Instance:
{
}

use sealed::Split;
macro_rules! split {
($TIM:ty: 1) => {
split!($TIM, C1);
};
($TIM:ty: 2) => {
split!($TIM, C1, C2);
};
($TIM:ty: 4) => {
split!($TIM, C1, C2, C3, C4);
};
($TIM:ty, $($C:ident),+) => {
impl Split for $TIM {
type Channels = ($(PwmChannelDisabled<$TIM, $C>,)+);
fn split() -> Self::Channels {
($(PwmChannelDisabled::<_, $C>::new(),)+)
}
}
};
}

macro_rules! hal {
($TIM:ty: [
$Timer:ident,
Expand All @@ -389,6 +416,11 @@ macro_rules! hal {
$(m: $timbase:ident,)?
]) => {
impl Instance for $TIM { }
impl crate::Steal for $TIM {
unsafe fn steal() -> Self {
Self::steal()
}
}
pub type $Timer = Timer<$TIM>;

impl General for $TIM {
Expand Down Expand Up @@ -577,6 +609,7 @@ macro_rules! hal {
)?

with_pwm!($TIM: $cnum $(, $aoe)?);
split!($TIM: $cnum);
unsafe impl<const C: u8> PeriAddress for CCR<$TIM, C> {
#[inline(always)]
fn address(&self) -> u32 {
Expand Down Expand Up @@ -611,13 +644,13 @@ macro_rules! with_dmar {
}

macro_rules! with_pwm {
($TIM:ty: [$($Cx:ident, $ccmrx_output:ident, $ocxpe:ident, $ocxm:ident;)+] $(, $aoe:ident)?) => {
($TIM:ty: [$($Cx:literal, $ccmrx_output:ident, $ocxpe:ident, $ocxm:ident;)+] $(, $aoe:ident)?) => {
impl WithPwm for $TIM {
#[inline(always)]
fn preload_output_channel_in_mode(&mut self, channel: Channel, mode: Ocm) {
match channel {
fn preload_output_channel_in_mode(&mut self, c: u8, mode: Ocm) {
match c {
$(
Channel::$Cx => {
$Cx => {
self.$ccmrx_output()
.modify(|_, w| w.$ocxpe().set_bit().$ocxm().set(mode as _) );
}
Expand All @@ -626,6 +659,18 @@ macro_rules! with_pwm {
_ => {},
}
}
fn freeze_output_channel(&mut self, c: u8) {
match c {
$(
$Cx => {
self.$ccmrx_output()
.modify(|_, w| w.$ocxpe().clear_bit().$ocxm().set(Ocm::Frozen as _) );
}
)+
#[allow(unreachable_patterns)]
_ => {},
}
}

#[inline(always)]
fn start_pwm(&mut self) {
Expand All @@ -636,21 +681,21 @@ macro_rules! with_pwm {
};
($TIM:ty: 1) => {
with_pwm!($TIM: [
C1, ccmr1_output, oc1pe, oc1m;
0, ccmr1_output, oc1pe, oc1m;
]);
};
($TIM:ty: 2) => {
with_pwm!($TIM: [
C1, ccmr1_output, oc1pe, oc1m;
C2, ccmr1_output, oc2pe, oc2m;
0, ccmr1_output, oc1pe, oc1m;
1, ccmr1_output, oc2pe, oc2m;
]);
};
($TIM:ty: 4 $(, $aoe:ident)?) => {
with_pwm!($TIM: [
C1, ccmr1_output, oc1pe, oc1m;
C2, ccmr1_output, oc2pe, oc2m;
C3, ccmr2_output, oc3pe, oc3m;
C4, ccmr2_output, oc4pe, oc4m;
0, ccmr1_output, oc1pe, oc1m;
1, ccmr1_output, oc2pe, oc2m;
2, ccmr2_output, oc3pe, oc3m;
3, ccmr2_output, oc4pe, oc4m;
] $(, $aoe)?);
};
}
Expand Down
Loading