Skip to content
Snippets Groups Projects
Commit c6f2d53f authored by Johannes Sjölund's avatar Johannes Sjölund
Browse files

Set individual pwm channels

parent ad53b3f7
No related branches found
No related tags found
No related merge requests found
...@@ -16,6 +16,7 @@ use f4::prelude::*; ...@@ -16,6 +16,7 @@ use f4::prelude::*;
use rtfm::{app, Threshold}; use rtfm::{app, Threshold};
const RESOLUTION: Milliseconds = Milliseconds(1); const RESOLUTION: Milliseconds = Milliseconds(1);
const CHANNELS: [Channel; 2] = [Channel::_1, Channel::_2];
app! { app! {
device: f4::stm32f40x, device: f4::stm32f40x,
...@@ -25,21 +26,19 @@ app! { ...@@ -25,21 +26,19 @@ app! {
}, },
} }
fn init(p: init::Peripherals) { fn init(p: init::Peripherals) {
let capture = Capture(p.TIM4); 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) -> ! { 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); let capture = Capture(&*r.TIM4);
for c in &CHANNELS {
capture.enable(*c);
}
loop { loop {
for c in &CHANNELS { for c in &CHANNELS {
match capture.capture(*c) { match capture.capture(*c) {
......
...@@ -41,8 +41,16 @@ fn init(p: init::Peripherals) { ...@@ -41,8 +41,16 @@ fn init(p: init::Peripherals) {
serial.init(BAUD_RATE.invert(), None, p.GPIOA, p.RCC); serial.init(BAUD_RATE.invert(), None, p.GPIOA, p.RCC);
serial.listen(Event::Rxne); serial.listen(Event::Rxne);
pwm.init(FREQUENCY.invert(), None, p.GPIOA, p.GPIOB, p.GPIOC, p.RCC); pwm.init(
pwm.set_duty(Channel::_1, 0); FREQUENCY.invert(),
Channel::_1,
None,
p.GPIOA,
p.GPIOB,
p.GPIOC,
p.RCC,
);
pwm.set_duty(Channel::_1, 1000);
pwm.enable(Channel::_1); pwm.enable(Channel::_1);
} }
......
//! 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(unsafe_code)]
#![deny(warnings)] #![deny(warnings)]
#![feature(proc_macro)] #![feature(proc_macro)]
...@@ -21,20 +18,23 @@ app! { ...@@ -21,20 +18,23 @@ app! {
} }
fn init(p: init::Peripherals) { fn init(p: init::Peripherals) {
let pwm = Pwm(p.TIM1); let pwm = Pwm(p.TIM4);
pwm.init(FREQUENCY.invert(), None, p.GPIOA, p.GPIOB, p.GPIOC, p.RCC);
let duty = pwm.get_max_duty() / 16;
const CHANNELS: [Channel; 4] = [Channel::_1, Channel::_2, Channel::_3, Channel::_4]; const CHANNELS: [Channel; 4] = [Channel::_1, Channel::_2, Channel::_3, Channel::_4];
for c in &CHANNELS { for c in &CHANNELS {
pwm.set_duty(*c, duty); pwm.init(
} FREQUENCY.invert(),
*c,
for c in &CHANNELS { None,
p.GPIOA,
p.GPIOB,
p.GPIOC,
p.RCC,
);
pwm.set_duty(*c, pwm.get_max_duty() / 16);
pwm.enable(*c); pwm.enable(*c);
rtfm::bkpt(); // rtfm::bkpt();
} }
} }
......
...@@ -76,8 +76,6 @@ impl<'a, T> Clone for Capture<'a, T> { ...@@ -76,8 +76,6 @@ impl<'a, T> Clone for Capture<'a, T> {
impl<'a, T> Copy 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 { macro_rules! impl_Capture {
($TIM:ident, $APB:ident) => { ($TIM:ident, $APB:ident) => {
impl<'a> Capture<'a, $TIM> impl<'a> Capture<'a, $TIM>
...@@ -88,6 +86,7 @@ macro_rules! impl_Capture { ...@@ -88,6 +86,7 @@ macro_rules! impl_Capture {
pub fn init<R>( pub fn init<R>(
&self, &self,
resolution: R, resolution: R,
channel: Channel,
gpioa: &GPIOA, // TODO: Make these optional/implement custom init for each TIM gpioa: &GPIOA, // TODO: Make these optional/implement custom init for each TIM
gpiob: &GPIOB, gpiob: &GPIOB,
gpioc: &GPIOC, gpioc: &GPIOC,
...@@ -95,19 +94,22 @@ macro_rules! impl_Capture { ...@@ -95,19 +94,22 @@ macro_rules! impl_Capture {
where where
R: Into<::$APB::Ticks>, R: Into<::$APB::Ticks>,
{ {
self._init(resolution.into(), gpioa, gpiob, gpioc, rcc) self._init(resolution.into(), channel, gpioa, gpiob, gpioc, rcc)
} }
fn _init( fn _init(
&self, &self,
resolution: ::$APB::Ticks, resolution: ::$APB::Ticks,
channel: Channel,
gpioa: &GPIOA, gpioa: &GPIOA,
gpiob: &GPIOB, gpiob: &GPIOB,
gpioc: &GPIOC, gpioc: &GPIOC,
rcc: &RCC) { rcc: &RCC) {
let tim = self.0; 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()); rcc.apb1enr.modify(|_, w| w.tim2en().set_bit());
} else if tim.get_type_id() == TypeId::of::<TIM3>() { } else if tim.get_type_id() == TypeId::of::<TIM3>() {
rcc.apb1enr.modify(|_, w| w.tim3en().set_bit()); rcc.apb1enr.modify(|_, w| w.tim3en().set_bit());
...@@ -115,12 +117,23 @@ macro_rules! impl_Capture { ...@@ -115,12 +117,23 @@ macro_rules! impl_Capture {
rcc.apb1enr.modify(|_, w| w.tim4en().set_bit()); rcc.apb1enr.modify(|_, w| w.tim4en().set_bit());
} }
// enable AFIO, GPIOx and TIMx
rcc.ahb1enr.modify(|_, w| { rcc.ahb1enr.modify(|_, w| {
if tim.get_type_id() == TypeId::of::<TIM2>() { if tim.get_type_id() == TypeId::of::<TIM1>() {
w.gpioaen().set_bit().gpioben().set_bit() 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>() { } 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>() { } else if tim.get_type_id() == TypeId::of::<TIM4>() {
w.gpioben().set_bit() w.gpioben().set_bit()
} else { } else {
...@@ -128,85 +141,101 @@ macro_rules! impl_Capture { ...@@ -128,85 +141,101 @@ macro_rules! impl_Capture {
} }
}); });
// don't remap TIM pins // See datasheet DM00115249 Table 9. Alternate function mapping
if tim.get_type_id() == TypeId::of::<TIM2>() { if tim.get_type_id() == TypeId::of::<TIM1>() {
// CH1 = PA0 = floating input // CH1 = PA8 = alternate push-pull
// CH2 = PA1 = floating input // CH2 = PA9 = alternate push-pull
// CH3 = PB10 = floating input // CH3 = PA10 = alternate push-pull
// CH4 = PA3 = floating input (Unimplemented: conflicts with USB USART2_RX) // 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 // See datasheet DM00115249 Table 9. Alternate function mapping
gpioa.afrl.modify(|_, w| { match channel {
w.afrl0().bits(1) Channel::_1 => {
.afrl1().bits(1) gpioa.afrl.modify(|_, w| w.afrl0().bits(1));
}); gpioa.moder.modify(|_, w| w.moder0().bits(2));
gpioa.moder.modify(|_, w| { }
w.moder0().bits(2) Channel::_2 => {
.moder1().bits(2) gpioa.afrl.modify(|_, w| w.afrl1().bits(1));
}); gpioa.moder.modify(|_, w| w.moder1().bits(2));
gpiob.afrh.modify(|_, w| { unsafe { }
w.afrh10().bits(1) Channel::_3 => {
}}); gpiob.afrh.modify(|_, w| unsafe {w.afrh10().bits(1)});
gpiob.moder.modify(|_, w| { unsafe { gpiob.moder.modify(|_, w| unsafe {w.moder10().bits(2)});
w.moder10().bits(2) }
}}); Channel::_4 => {
panic!("Not implemented: conflicts with USB USART2_RX");
}
}
} else if tim.get_type_id() == TypeId::of::<TIM3>() { } else if tim.get_type_id() == TypeId::of::<TIM3>() {
// CH1 = PA6 = floating input // CH1 = PA6 = alternate push-pull
// CH2 = PC7 = floating input // CH2 = PC7 = alternate push-pull
// CH3 = PB0 = floating input // CH3 = PB0 = alternate push-pull
// CH4 = PB1 = floating input // CH4 = PB1 = alternate push-pull
gpioa.afrl.modify(|_, w| { match channel {
w.afrl6().bits(2) Channel::_1 => {
}); gpioa.afrl.modify(|_, w| w.afrl6().bits(2));
gpioa.moder.modify(|_, w| { gpioa.moder.modify(|_, w| w.moder6().bits(2));
w.moder6().bits(2) }
}); Channel::_2 => {
gpiob.afrl.modify(|_, w| { unsafe { gpioc.afrl.modify(|_, w| unsafe {w.afrl7().bits(2)});
w.afrl0().bits(2) gpioc.moder.modify(|_, w| unsafe {w.moder7().bits(2)});
.afrl1().bits(2) }
}}); Channel::_3 => {
gpiob.moder.modify(|_, w| { unsafe { gpiob.afrl.modify(|_, w| unsafe {w.afrl0().bits(2)});
w.moder0().bits(2) gpiob.moder.modify(|_, w| unsafe {w.moder0().bits(2)});
.moder1().bits(2) }
}}); Channel::_4 => {
gpioc.afrl.modify(|_, w| { unsafe { gpiob.afrl.modify(|_, w| unsafe {w.afrl1().bits(2)});
w.afrl7().bits(2) gpiob.moder.modify(|_, w| unsafe {w.moder1().bits(2)});
}}); }
gpioc.moder.modify(|_, w| { unsafe { }
w.moder7().bits(2)
}});
} else if tim.get_type_id() == TypeId::of::<TIM4>() { } else if tim.get_type_id() == TypeId::of::<TIM4>() {
// CH1 = PB6 = alternate push-pull // CH1 = PB6 = alternate push-pull
// CH2 = PB7 = alternate push-pull // CH2 = PB7 = alternate push-pull
// CH3 = PB8 = alternate push-pull // CH3 = PB8 = alternate push-pull
// CH4 = PB9 = alternate push-pull // CH4 = PB9 = alternate push-pull
gpiob.afrl.modify(|_, w| { unsafe { match channel {
w.afrl6().bits(2) Channel::_1 => {
.afrl7().bits(2) gpiob.afrl.modify(|_, w| unsafe {w.afrl6().bits(2)});
gpiob.moder.modify(|_, w| unsafe {w.moder6().bits(2)});
} }
}); Channel::_2 => {
gpiob.moder.modify(|_, w| { unsafe { gpiob.afrl.modify(|_, w| unsafe {w.afrl7().bits(2)});
w.moder6().bits(2) gpiob.moder.modify(|_, w| unsafe {w.moder7().bits(2)});
.moder7().bits(2)
} }
}); Channel::_3 => {
gpiob.afrh.modify(|_, w| { unsafe { gpiob.afrh.modify(|_, w| unsafe {w.afrh8().bits(2)});
w.afrh8().bits(2) gpiob.moder.modify(|_, w| unsafe {w.moder8().bits(2)});
.afrh9().bits(2)
} }
}); Channel::_4 => {
gpiob.moder.modify(|_, w| { unsafe { gpiob.afrh.modify(|_, w| unsafe {w.afrh9().bits(2)});
w.moder8().bits(2) gpiob.moder.modify(|_, w| unsafe {w.moder9().bits(2)});
.moder9().bits(2)
} }
});
gpiob.pupdr.modify(|_, w| { unsafe {
w.pupdr6().bits(2)
.pupdr7().bits(2)
.pupdr8().bits(2)
.pupdr9().bits(2)
} }
});
} }
tim.smcr.write(|w| unsafe { tim.smcr.write(|w| unsafe {
...@@ -375,6 +404,7 @@ macro_rules! impl_Capture { ...@@ -375,6 +404,7 @@ macro_rules! impl_Capture {
} }
} }
impl_Capture!(TIM1, apb2);
impl_Capture!(TIM2, apb1); impl_Capture!(TIM2, apb1);
impl_Capture!(TIM3, apb1); impl_Capture!(TIM3, apb1);
impl_Capture!(TIM4, apb1); impl_Capture!(TIM4, apb1);
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment