From c6f2d53fa3d7243c65f00dcf7cd874ae3ac97569 Mon Sep 17 00:00:00 2001 From: jsjolund <j.sjolund@gmail.com> Date: Tue, 12 Dec 2017 07:57:47 +0100 Subject: [PATCH] Set individual pwm channels --- examples/capture4.rs | 13 +- examples/pwm-control.rs | 12 +- examples/pwm1.rs | 24 +-- src/capture.rs | 180 +++++++++------- src/pwm.rs | 464 +++++++++++++++------------------------- 5 files changed, 311 insertions(+), 382 deletions(-) diff --git a/examples/capture4.rs b/examples/capture4.rs index 108fb4f..ce67f70 100644 --- a/examples/capture4.rs +++ b/examples/capture4.rs @@ -16,6 +16,7 @@ use f4::prelude::*; use rtfm::{app, Threshold}; const RESOLUTION: Milliseconds = Milliseconds(1); +const CHANNELS: [Channel; 2] = [Channel::_1, Channel::_2]; app! { device: f4::stm32f40x, @@ -25,21 +26,19 @@ app! { }, } + fn init(p: init::Peripherals) { let capture = Capture(p.TIM4); - capture.init(RESOLUTION, p.GPIOA, p.GPIOB, p.GPIOC, p.RCC); + for c in &CHANNELS { + capture.init(RESOLUTION, *c, p.GPIOA, p.GPIOB, p.GPIOC, p.RCC); + capture.enable(*c); + } } fn idle(_t: &mut Threshold, r: idle::Resources) -> ! { - const CHANNELS: [Channel; 4] = [Channel::_1, Channel::_2, Channel::_3, Channel::_4]; - let capture = Capture(&*r.TIM4); - for c in &CHANNELS { - capture.enable(*c); - } - loop { for c in &CHANNELS { match capture.capture(*c) { diff --git a/examples/pwm-control.rs b/examples/pwm-control.rs index 391d51f..702dead 100644 --- a/examples/pwm-control.rs +++ b/examples/pwm-control.rs @@ -41,8 +41,16 @@ fn init(p: init::Peripherals) { serial.init(BAUD_RATE.invert(), None, p.GPIOA, p.RCC); serial.listen(Event::Rxne); - pwm.init(FREQUENCY.invert(), None, p.GPIOA, p.GPIOB, p.GPIOC, p.RCC); - pwm.set_duty(Channel::_1, 0); + pwm.init( + FREQUENCY.invert(), + Channel::_1, + None, + p.GPIOA, + p.GPIOB, + p.GPIOC, + p.RCC, + ); + pwm.set_duty(Channel::_1, 1000); pwm.enable(Channel::_1); } diff --git a/examples/pwm1.rs b/examples/pwm1.rs index 2b45f30..ddc7f1d 100644 --- a/examples/pwm1.rs +++ b/examples/pwm1.rs @@ -1,6 +1,3 @@ -//! Output a PWM with a duty cycle of ~6% on all the channels of TIM1 -// FIXME doesn't seem to work :-( - #![deny(unsafe_code)] #![deny(warnings)] #![feature(proc_macro)] @@ -21,20 +18,23 @@ app! { } fn init(p: init::Peripherals) { - let pwm = Pwm(p.TIM1); - - pwm.init(FREQUENCY.invert(), None, p.GPIOA, p.GPIOB, p.GPIOC, p.RCC); - let duty = pwm.get_max_duty() / 16; + let pwm = Pwm(p.TIM4); const CHANNELS: [Channel; 4] = [Channel::_1, Channel::_2, Channel::_3, Channel::_4]; for c in &CHANNELS { - pwm.set_duty(*c, duty); - } - - for c in &CHANNELS { + pwm.init( + FREQUENCY.invert(), + *c, + None, + p.GPIOA, + p.GPIOB, + p.GPIOC, + p.RCC, + ); + pwm.set_duty(*c, pwm.get_max_duty() / 16); pwm.enable(*c); - rtfm::bkpt(); + // rtfm::bkpt(); } } diff --git a/src/capture.rs b/src/capture.rs index 94cdfc2..57e7bf6 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -76,8 +76,6 @@ impl<'a, T> Clone for Capture<'a, T> { impl<'a, T> Copy for Capture<'a, T> {} -// TODO: TIM1 is a 16 bit timer, must have its own implementation - macro_rules! impl_Capture { ($TIM:ident, $APB:ident) => { impl<'a> Capture<'a, $TIM> @@ -88,6 +86,7 @@ macro_rules! impl_Capture { pub fn init<R>( &self, resolution: R, + channel: Channel, gpioa: &GPIOA, // TODO: Make these optional/implement custom init for each TIM gpiob: &GPIOB, gpioc: &GPIOC, @@ -95,19 +94,22 @@ macro_rules! impl_Capture { where R: Into<::$APB::Ticks>, { - self._init(resolution.into(), gpioa, gpiob, gpioc, rcc) + self._init(resolution.into(), channel, gpioa, gpiob, gpioc, rcc) } fn _init( &self, resolution: ::$APB::Ticks, + channel: Channel, gpioa: &GPIOA, gpiob: &GPIOB, gpioc: &GPIOC, rcc: &RCC) { let tim = self.0; - if tim.get_type_id() == TypeId::of::<TIM2>() { + if tim.get_type_id() == TypeId::of::<TIM1>() { + rcc.apb2enr.modify(|_, w| w.tim1en().set_bit()); + } else if tim.get_type_id() == TypeId::of::<TIM2>() { rcc.apb1enr.modify(|_, w| w.tim2en().set_bit()); } else if tim.get_type_id() == TypeId::of::<TIM3>() { rcc.apb1enr.modify(|_, w| w.tim3en().set_bit()); @@ -115,12 +117,23 @@ macro_rules! impl_Capture { rcc.apb1enr.modify(|_, w| w.tim4en().set_bit()); } - // enable AFIO, GPIOx and TIMx rcc.ahb1enr.modify(|_, w| { - if tim.get_type_id() == TypeId::of::<TIM2>() { - w.gpioaen().set_bit().gpioben().set_bit() + if tim.get_type_id() == TypeId::of::<TIM1>() { + w.gpioaen().set_bit() + } else if tim.get_type_id() == TypeId::of::<TIM2>() { + match channel { + Channel::_1 => w.gpioaen().set_bit(), + Channel::_2 => w.gpioaen().set_bit(), + Channel::_3 => w.gpioben().set_bit(), + Channel::_4 => panic!("Not implemented: conflicts with USB USART2_RX"), + } } else if tim.get_type_id() == TypeId::of::<TIM3>() { - w.gpioaen().set_bit().gpioben().set_bit().gpiocen().set_bit() + match channel { + Channel::_1 => w.gpioaen().set_bit(), + Channel::_2 => w.gpiocen().set_bit(), + Channel::_3 => w.gpioben().set_bit(), + Channel::_4 => w.gpioben().set_bit(), + } } else if tim.get_type_id() == TypeId::of::<TIM4>() { w.gpioben().set_bit() } else { @@ -128,85 +141,101 @@ macro_rules! impl_Capture { } }); - // don't remap TIM pins - if tim.get_type_id() == TypeId::of::<TIM2>() { - // CH1 = PA0 = floating input - // CH2 = PA1 = floating input - // CH3 = PB10 = floating input - // CH4 = PA3 = floating input (Unimplemented: conflicts with USB USART2_RX) + // See datasheet DM00115249 Table 9. Alternate function mapping + if tim.get_type_id() == TypeId::of::<TIM1>() { + // CH1 = PA8 = alternate push-pull + // CH2 = PA9 = alternate push-pull + // CH3 = PA10 = alternate push-pull + // CH4 = PA11 = alternate push-pull + match channel { + Channel::_1 => { + gpioa.afrh.modify(|_, w| w.afrh8().bits(1)); + gpioa.moder.modify(|_, w| w.moder8().bits(2)); + } + Channel::_2 => { + gpioa.afrh.modify(|_, w| w.afrh9().bits(1)); + gpioa.moder.modify(|_, w| w.moder9().bits(2)); + } + Channel::_3 => { + gpioa.afrh.modify(|_, w| w.afrh10().bits(1)); + gpioa.moder.modify(|_, w| w.moder10().bits(2)); + } + Channel::_4 => { + gpioa.afrh.modify(|_, w| w.afrh11().bits(1)); + gpioa.moder.modify(|_, w| w.moder11().bits(2)); + } + } + } else if tim.get_type_id() == TypeId::of::<TIM2>() { + // CH1 = PA0 = alternate push-pull + // CH2 = PA1 = alternate push-pull + // CH3 = PB10 = alternate push-pull + // CH4 = PA3 = alternate push-pull (Not implemented: conflicts with USB USART2_RX) // See datasheet DM00115249 Table 9. Alternate function mapping - gpioa.afrl.modify(|_, w| { - w.afrl0().bits(1) - .afrl1().bits(1) - }); - gpioa.moder.modify(|_, w| { - w.moder0().bits(2) - .moder1().bits(2) - }); - gpiob.afrh.modify(|_, w| { unsafe { - w.afrh10().bits(1) - }}); - gpiob.moder.modify(|_, w| { unsafe { - w.moder10().bits(2) - }}); + match channel { + Channel::_1 => { + gpioa.afrl.modify(|_, w| w.afrl0().bits(1)); + gpioa.moder.modify(|_, w| w.moder0().bits(2)); + } + Channel::_2 => { + gpioa.afrl.modify(|_, w| w.afrl1().bits(1)); + gpioa.moder.modify(|_, w| w.moder1().bits(2)); + } + Channel::_3 => { + gpiob.afrh.modify(|_, w| unsafe {w.afrh10().bits(1)}); + gpiob.moder.modify(|_, w| unsafe {w.moder10().bits(2)}); + } + Channel::_4 => { + panic!("Not implemented: conflicts with USB USART2_RX"); + } + } } else if tim.get_type_id() == TypeId::of::<TIM3>() { - // CH1 = PA6 = floating input - // CH2 = PC7 = floating input - // CH3 = PB0 = floating input - // CH4 = PB1 = floating input - gpioa.afrl.modify(|_, w| { - w.afrl6().bits(2) - }); - gpioa.moder.modify(|_, w| { - w.moder6().bits(2) - }); - gpiob.afrl.modify(|_, w| { unsafe { - w.afrl0().bits(2) - .afrl1().bits(2) - }}); - gpiob.moder.modify(|_, w| { unsafe { - w.moder0().bits(2) - .moder1().bits(2) - }}); - gpioc.afrl.modify(|_, w| { unsafe { - w.afrl7().bits(2) - }}); - gpioc.moder.modify(|_, w| { unsafe { - w.moder7().bits(2) - }}); + // CH1 = PA6 = alternate push-pull + // CH2 = PC7 = alternate push-pull + // CH3 = PB0 = alternate push-pull + // CH4 = PB1 = alternate push-pull + match channel { + Channel::_1 => { + gpioa.afrl.modify(|_, w| w.afrl6().bits(2)); + gpioa.moder.modify(|_, w| w.moder6().bits(2)); + } + Channel::_2 => { + gpioc.afrl.modify(|_, w| unsafe {w.afrl7().bits(2)}); + gpioc.moder.modify(|_, w| unsafe {w.moder7().bits(2)}); + } + Channel::_3 => { + gpiob.afrl.modify(|_, w| unsafe {w.afrl0().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder0().bits(2)}); + } + Channel::_4 => { + gpiob.afrl.modify(|_, w| unsafe {w.afrl1().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder1().bits(2)}); + } + } + } else if tim.get_type_id() == TypeId::of::<TIM4>() { // CH1 = PB6 = alternate push-pull // CH2 = PB7 = alternate push-pull // CH3 = PB8 = alternate push-pull // CH4 = PB9 = alternate push-pull - gpiob.afrl.modify(|_, w| { unsafe { - w.afrl6().bits(2) - .afrl7().bits(2) - } - }); - gpiob.moder.modify(|_, w| { unsafe { - w.moder6().bits(2) - .moder7().bits(2) + match channel { + Channel::_1 => { + gpiob.afrl.modify(|_, w| unsafe {w.afrl6().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder6().bits(2)}); } - }); - gpiob.afrh.modify(|_, w| { unsafe { - w.afrh8().bits(2) - .afrh9().bits(2) + Channel::_2 => { + gpiob.afrl.modify(|_, w| unsafe {w.afrl7().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder7().bits(2)}); } - }); - gpiob.moder.modify(|_, w| { unsafe { - w.moder8().bits(2) - .moder9().bits(2) + Channel::_3 => { + gpiob.afrh.modify(|_, w| unsafe {w.afrh8().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder8().bits(2)}); } - }); - gpiob.pupdr.modify(|_, w| { unsafe { - w.pupdr6().bits(2) - .pupdr7().bits(2) - .pupdr8().bits(2) - .pupdr9().bits(2) + Channel::_4 => { + gpiob.afrh.modify(|_, w| unsafe {w.afrh9().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder9().bits(2)}); } - }); + } } tim.smcr.write(|w| unsafe { @@ -375,6 +404,7 @@ macro_rules! impl_Capture { } } +impl_Capture!(TIM1, apb2); impl_Capture!(TIM2, apb1); impl_Capture!(TIM3, apb1); impl_Capture!(TIM4, apb1); diff --git a/src/pwm.rs b/src/pwm.rs index 93000a5..f68fded 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -14,7 +14,7 @@ //! - CH1 = PA0 //! - CH2 = PA1 //! - CH3 = PB10 -//! - CH4 = PA3 (Unimplemented: conflicts with USB USART2_RX) +//! - CH4 = PA3 (Not implemented: conflicts with USB USART2_RX) //! //! # TIM3 //! @@ -45,176 +45,6 @@ use timer::Channel; pub struct Pwm<'a, T>(pub &'a T) where T: 'a; -impl<'a> Pwm<'a, TIM1> { - /// Initializes the PWM module - pub fn init<P>( - &self, - period: P, - dma1: Option<&DMA1>, - gpioa: &GPIOA, // TODO: Make these optional/implement custom init for each TIM - gpiob: &GPIOB, - gpioc: &GPIOC, - rcc: &RCC, - ) where - P: Into<::apb2::Ticks>, - { - self._init(period.into(), dma1, gpioa, gpiob, gpioc, rcc) - } - - fn _init( - &self, - period: ::apb2::Ticks, - dma1: Option<&DMA1>, - gpioa: &GPIOA, - gpiob: &GPIOB, - gpioc: &GPIOC, - rcc: &RCC, - ) { - let tim1 = self.0; - - rcc.apb2enr.modify(|_, w| w.tim1en().set_bit()); - rcc.ahb1enr.modify(|_, w| w.gpioaen().set_bit()); - - // CH1 = PA8 = alternate push-pull - // CH2 = PA9 = alternate push-pull - // CH3 = PA10 = alternate push-pull - // CH4 = PA11 = alternate push-pull - gpioa.afrh.modify(|_, w| { - w.afrh8() - .bits(1) - .afrh9() - .bits(1) - .afrh10() - .bits(1) - .afrh11() - .bits(1) - }); - gpioa.moder.modify(|_, w| { - w.moder8() - .bits(2) - .moder9() - .bits(2) - .moder10() - .bits(2) - .moder11() - .bits(2) - }); - - // PWM mode 1 - tim1.ccmr1_output.modify(|_, w| unsafe { - w.oc1pe() - .set_bit() - .oc1m() - .bits(0b110) - .oc2pe() - .set_bit() - .oc2m() - .bits(0b110) - }); - tim1.ccmr2_output.modify(|_, w| unsafe { - w.oc3pe() - .set_bit() - .oc3m() - .bits(0b110) - .oc4pe() - .set_bit() - .oc4m() - .bits(0b110) - }); - tim1.ccer.modify(|_, w| { - w.cc1p() - .clear_bit() - .cc2p() - .clear_bit() - .cc3p() - .clear_bit() - .cc4p() - .clear_bit() - }); - - tim1.bdtr.modify(|_, w| w.moe().set_bit()); - - self._set_period(period); - - tim1.cr1.write(|w| unsafe { - w.cms() - .bits(0b00) - .dir() - .bit(false) - .opm() - .bit(false) - .cen() - .set_bit() - }); - } - - fn _set_period(&self, period: ::apb2::Ticks) { - let period = period.0; - - let psc = u16((period - 1) / (1 << 16)).unwrap(); - self.0.psc.write(|w| unsafe { w.psc().bits(psc) }); - - let arr = u16(period / u32(psc + 1)).unwrap(); - self.0.arr.write(|w| unsafe { w.arr().bits(arr) }); - } -} - -impl<'a> hal::Pwm for Pwm<'a, TIM1> { - type Channel = Channel; - type Time = ::apb2::Ticks; - type Duty = u16; - - fn disable(&self, channel: Channel) { - match channel { - Channel::_1 => self.0.ccer.modify(|_, w| w.cc1e().clear_bit()), - Channel::_2 => self.0.ccer.modify(|_, w| w.cc2e().clear_bit()), - Channel::_3 => self.0.ccer.modify(|_, w| w.cc3e().clear_bit()), - Channel::_4 => self.0.ccer.modify(|_, w| w.cc4e().clear_bit()), - } - } - - fn enable(&self, channel: Channel) { - match channel { - Channel::_1 => self.0.ccer.modify(|_, w| w.cc1e().set_bit()), - Channel::_2 => self.0.ccer.modify(|_, w| w.cc2e().set_bit()), - Channel::_3 => self.0.ccer.modify(|_, w| w.cc3e().set_bit()), - Channel::_4 => self.0.ccer.modify(|_, w| w.cc4e().set_bit()), - } - } - - fn get_duty(&self, channel: Channel) -> u16 { - match channel { - Channel::_1 => self.0.ccr1.read().ccr1().bits(), - Channel::_2 => self.0.ccr2.read().ccr2().bits(), - Channel::_3 => self.0.ccr3.read().ccr3().bits(), - Channel::_4 => self.0.ccr4.read().ccr4().bits(), - } - } - - fn get_max_duty(&self) -> u16 { - self.0.arr.read().arr().bits() - } - - fn get_period(&self) -> ::apb2::Ticks { - ::apb2::Ticks(u32(self.0.psc.read().bits() * self.0.arr.read().bits())) - } - - fn set_duty(&self, channel: Channel, duty: u16) { - match channel { - Channel::_1 => self.0.ccr1.write(|w| unsafe { w.ccr1().bits(duty) }), - Channel::_2 => self.0.ccr2.write(|w| unsafe { w.ccr2().bits(duty) }), - Channel::_3 => self.0.ccr3.write(|w| unsafe { w.ccr3().bits(duty) }), - Channel::_4 => self.0.ccr4.write(|w| unsafe { w.ccr4().bits(duty) }), - } - } - - fn set_period<P>(&self, period: P) - where - P: Into<::apb2::Ticks>, - { - self._set_period(period.into()) - } -} macro_rules! impl_Pwm { ($TIM:ident, $APB:ident) => { @@ -224,6 +54,7 @@ macro_rules! impl_Pwm { pub fn init<P>( &self, period: P, + channel: Channel, dma1: Option<&DMA1>, gpioa: &GPIOA, gpiob: &GPIOB, @@ -232,12 +63,13 @@ macro_rules! impl_Pwm { ) where P: Into<::$APB::Ticks>, { - self._init(period.into(), dma1, gpioa, gpiob, gpioc, rcc) + self._init(period.into(), channel, dma1, gpioa, gpiob, gpioc, rcc) } fn _init( &self, period: ::$APB::Ticks, + channel: Channel, dma1: Option<&DMA1>, gpioa: &GPIOA, gpiob: &GPIOB, @@ -251,7 +83,9 @@ macro_rules! impl_Pwm { rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit()); } - if tim.get_type_id() == TypeId::of::<TIM2>() { + if tim.get_type_id() == TypeId::of::<TIM1>() { + rcc.apb2enr.modify(|_, w| w.tim1en().set_bit()); + } else if tim.get_type_id() == TypeId::of::<TIM2>() { rcc.apb1enr.modify(|_, w| w.tim2en().set_bit()); } else if tim.get_type_id() == TypeId::of::<TIM3>() { rcc.apb1enr.modify(|_, w| w.tim3en().set_bit()); @@ -260,10 +94,22 @@ macro_rules! impl_Pwm { } rcc.ahb1enr.modify(|_, w| { - if tim.get_type_id() == TypeId::of::<TIM2>() { - w.gpioaen().set_bit().gpioben().set_bit() + if tim.get_type_id() == TypeId::of::<TIM1>() { + w.gpioaen().set_bit() + } else if tim.get_type_id() == TypeId::of::<TIM2>() { + match channel { + Channel::_1 => w.gpioaen().set_bit(), + Channel::_2 => w.gpioaen().set_bit(), + Channel::_3 => w.gpioben().set_bit(), + Channel::_4 => panic!("Not implemented: conflicts with USB USART2_RX"), + } } else if tim.get_type_id() == TypeId::of::<TIM3>() { - w.gpioaen().set_bit().gpioben().set_bit().gpiocen().set_bit() + match channel { + Channel::_1 => w.gpioaen().set_bit(), + Channel::_2 => w.gpiocen().set_bit(), + Channel::_3 => w.gpioben().set_bit(), + Channel::_4 => w.gpioben().set_bit(), + } } else if tim.get_type_id() == TypeId::of::<TIM4>() { w.gpioben().set_bit() } else { @@ -271,143 +117,124 @@ macro_rules! impl_Pwm { } }); - if tim.get_type_id() == TypeId::of::<TIM2>() { + // See datasheet DM00115249 Table 9. Alternate function mapping + if tim.get_type_id() == TypeId::of::<TIM1>() { + // CH1 = PA8 = alternate push-pull + // CH2 = PA9 = alternate push-pull + // CH3 = PA10 = alternate push-pull + // CH4 = PA11 = alternate push-pull + match channel { + Channel::_1 => { + gpioa.afrh.modify(|_, w| w.afrh8().bits(1)); + gpioa.moder.modify(|_, w| w.moder8().bits(2)); + } + Channel::_2 => { + gpioa.afrh.modify(|_, w| w.afrh9().bits(1)); + gpioa.moder.modify(|_, w| w.moder9().bits(2)); + } + Channel::_3 => { + gpioa.afrh.modify(|_, w| w.afrh10().bits(1)); + gpioa.moder.modify(|_, w| w.moder10().bits(2)); + } + Channel::_4 => { + gpioa.afrh.modify(|_, w| w.afrh11().bits(1)); + gpioa.moder.modify(|_, w| w.moder11().bits(2)); + } + } + } else if tim.get_type_id() == TypeId::of::<TIM2>() { // CH1 = PA0 = alternate push-pull // CH2 = PA1 = alternate push-pull // CH3 = PB10 = alternate push-pull - // CH4 = PA3 = alternate push-pull (Unimplemented: conflicts with USB USART2_RX) + // CH4 = PA3 = alternate push-pull (Not implemented: conflicts with USB USART2_RX) // See datasheet DM00115249 Table 9. Alternate function mapping - gpioa.afrl.modify(|_, w| { - w - .afrl0().bits(1) - .afrl1().bits(1) - }); - gpioa.moder.modify(|_, w| { - w - .moder0().bits(2) - .moder1().bits(2) - }); - gpiob.afrh.modify(|_, w| { unsafe { - w - .afrh10().bits(1)} - }); - gpiob.moder.modify(|_, w| { unsafe { - w - .moder10().bits(2) + match channel { + Channel::_1 => { + gpioa.afrl.modify(|_, w| w.afrl0().bits(1)); + gpioa.moder.modify(|_, w| w.moder0().bits(2)); + } + Channel::_2 => { + gpioa.afrl.modify(|_, w| w.afrl1().bits(1)); + gpioa.moder.modify(|_, w| w.moder1().bits(2)); + } + Channel::_3 => { + gpiob.afrh.modify(|_, w| unsafe {w.afrh10().bits(1)}); + gpiob.moder.modify(|_, w| unsafe {w.moder10().bits(2)}); + } + Channel::_4 => { + panic!("Not implemented: conflicts with USB USART2_RX"); + } } - }); } else if tim.get_type_id() == TypeId::of::<TIM3>() { // CH1 = PA6 = alternate push-pull // CH2 = PC7 = alternate push-pull // CH3 = PB0 = alternate push-pull // CH4 = PB1 = alternate push-pull - gpioa.afrl.modify(|_, w| { - w.afrl6().bits(2) - }); - gpioa.moder.modify(|_, w| { - w.moder6().bits(2) - }); - gpiob.afrl.modify(|_, w| { unsafe { - w.afrl0().bits(2) - .afrl1().bits(2) + match channel { + Channel::_1 => { + gpioa.afrl.modify(|_, w| w.afrl6().bits(2)); + gpioa.moder.modify(|_, w| w.moder6().bits(2)); } - }); - gpiob.moder.modify(|_, w| { unsafe { - w.moder0().bits(2) - .moder1().bits(2) + Channel::_2 => { + gpioc.afrl.modify(|_, w| unsafe {w.afrl7().bits(2)}); + gpioc.moder.modify(|_, w| unsafe {w.moder7().bits(2)}); } - }); - gpioc.afrl.modify(|_, w| { unsafe { - w.afrl7().bits(2) + Channel::_3 => { + gpiob.afrl.modify(|_, w| unsafe {w.afrl0().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder0().bits(2)}); } - }); - gpioc.moder.modify(|_, w| { unsafe { - w.moder7().bits(2) + Channel::_4 => { + gpiob.afrl.modify(|_, w| unsafe {w.afrl1().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder1().bits(2)}); } - }); + } } else if tim.get_type_id() == TypeId::of::<TIM4>() { // CH1 = PB6 = alternate push-pull // CH2 = PB7 = alternate push-pull // CH3 = PB8 = alternate push-pull // CH4 = PB9 = alternate push-pull - gpiob.afrl.modify(|_, w| { unsafe { - w.afrl6().bits(2) - .afrl7().bits(2) + match channel { + Channel::_1 => { + gpiob.afrl.modify(|_, w| unsafe {w.afrl6().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder6().bits(2)}); } - }); - gpiob.moder.modify(|_, w| { unsafe { - w.moder6().bits(2) - .moder7().bits(2) + Channel::_2 => { + gpiob.afrl.modify(|_, w| unsafe {w.afrl7().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder7().bits(2)}); } - }); - gpiob.afrh.modify(|_, w| { unsafe { - w.afrh8().bits(2) - .afrh9().bits(2) + Channel::_3 => { + gpiob.afrh.modify(|_, w| unsafe {w.afrh8().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder8().bits(2)}); } - }); - gpiob.moder.modify(|_, w| { unsafe { - w.moder8().bits(2) - .moder9().bits(2) + Channel::_4 => { + gpiob.afrh.modify(|_, w| unsafe {w.afrh9().bits(2)}); + gpiob.moder.modify(|_, w| unsafe {w.moder9().bits(2)}); } - }); + } } // PWM mode 1 - if tim.get_type_id() == TypeId::of::<TIM2>() { - // Ignore conflicting pin for channel 4 - tim.ccmr1_output.modify(|_, w| unsafe { - w.oc1pe() - .set_bit() - .oc1m() - .bits(0b110) - .oc2pe() - .set_bit() - .oc2m() - .bits(0b110) - }); - tim.ccmr2_output.modify(|_, w| unsafe { - w.oc3pe() - .set_bit() - .oc3m() - .bits(0b110) - }); - tim.ccer - .modify(|_, w| w.cc1p().clear_bit().cc2p().clear_bit().cc3p().clear_bit()); - } else { - tim.ccmr1_output.modify(|_, w| unsafe { - w.oc1pe() - .set_bit() - .oc1m() - .bits(0b110) - .oc2pe() - .set_bit() - .oc2m() - .bits(0b110) - }); - - tim.ccmr2_output.modify(|_, w| unsafe { - w.oc3pe() - .set_bit() - .oc3m() - .bits(0b110) - .oc4pe() - .set_bit() - .oc4m() - .bits(0b110) - }); - - tim.ccer.modify(|_, w| { - w.cc1p() - .clear_bit() - .cc2p() - .clear_bit() - .cc3p() - .clear_bit() - .cc4p() - .clear_bit() - }); + match channel { + Channel::_1 => { + tim.ccmr1_output.modify(|_, w| unsafe {w.oc1pe().set_bit().oc1m().bits(0b110)}); + tim.ccer.modify(|_, w| {w.cc1p().clear_bit()}); + } + Channel::_2 => { + tim.ccmr1_output.modify(|_, w| unsafe {w.oc2pe().set_bit().oc2m().bits(0b110)}); + tim.ccer.modify(|_, w| {w.cc2p().clear_bit()}); + } + Channel::_3 => { + tim.ccmr2_output.modify(|_, w| unsafe {w.oc3pe().set_bit().oc3m().bits(0b110)}); + tim.ccer.modify(|_, w| {w.cc3p().clear_bit()}); + } + Channel::_4 => { + if tim.get_type_id() == TypeId::of::<TIM2>() { + panic!("Not implemented: conflicts with USB USART2_RX"); + } + tim.ccmr2_output.modify(|_, w| unsafe {w.oc4pe().set_bit().oc4m().bits(0b110)}); + tim.ccer.modify(|_, w| {w.cc4p().clear_bit()}); + } } self._set_period(period); @@ -514,7 +341,10 @@ macro_rules! impl_Pwm { } } } - + } +} +macro_rules! impl_halPwm { + ($TIM:ident, $APB:ident) => { impl<'a> hal::Pwm for Pwm<'a, $TIM> { type Channel = Channel; @@ -585,6 +415,68 @@ macro_rules! impl_Pwm { } } +impl_Pwm!(TIM1, apb2); impl_Pwm!(TIM2, apb1); +impl_halPwm!(TIM2, apb1); impl_Pwm!(TIM3, apb1); +impl_halPwm!(TIM3, apb1); impl_Pwm!(TIM4, apb1); +impl_halPwm!(TIM4, apb1); + +// TIM1 is 16 bit instead of 32 +impl<'a> hal::Pwm for Pwm<'a, TIM1> { + type Channel = Channel; + type Time = ::apb2::Ticks; + type Duty = u16; + + fn disable(&self, channel: Channel) { + match channel { + Channel::_1 => self.0.ccer.modify(|_, w| w.cc1e().clear_bit()), + Channel::_2 => self.0.ccer.modify(|_, w| w.cc2e().clear_bit()), + Channel::_3 => self.0.ccer.modify(|_, w| w.cc3e().clear_bit()), + Channel::_4 => self.0.ccer.modify(|_, w| w.cc4e().clear_bit()), + } + } + + fn enable(&self, channel: Channel) { + match channel { + Channel::_1 => self.0.ccer.modify(|_, w| w.cc1e().set_bit()), + Channel::_2 => self.0.ccer.modify(|_, w| w.cc2e().set_bit()), + Channel::_3 => self.0.ccer.modify(|_, w| w.cc3e().set_bit()), + Channel::_4 => self.0.ccer.modify(|_, w| w.cc4e().set_bit()), + } + } + + fn get_duty(&self, channel: Channel) -> u16 { + match channel { + Channel::_1 => self.0.ccr1.read().ccr1().bits(), + Channel::_2 => self.0.ccr2.read().ccr2().bits(), + Channel::_3 => self.0.ccr3.read().ccr3().bits(), + Channel::_4 => self.0.ccr4.read().ccr4().bits(), + } + } + + fn get_max_duty(&self) -> u16 { + self.0.arr.read().arr().bits() + } + + fn get_period(&self) -> ::apb2::Ticks { + ::apb2::Ticks(u32(self.0.psc.read().bits() * self.0.arr.read().bits())) + } + + fn set_duty(&self, channel: Channel, duty: u16) { + match channel { + Channel::_1 => self.0.ccr1.write(|w| unsafe { w.ccr1().bits(duty) }), + Channel::_2 => self.0.ccr2.write(|w| unsafe { w.ccr2().bits(duty) }), + Channel::_3 => self.0.ccr3.write(|w| unsafe { w.ccr3().bits(duty) }), + Channel::_4 => self.0.ccr4.write(|w| unsafe { w.ccr4().bits(duty) }), + } + } + + fn set_period<P>(&self, period: P) + where + P: Into<::apb2::Ticks>, + { + self._set_period(period.into()) + } +} -- GitLab