Skip to content

Commit

Permalink
BusClock
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Nov 22, 2021
1 parent 1cbe88d commit e6286a5
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 122 deletions.
2 changes: 0 additions & 2 deletions src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ use crate::hal::blocking::i2c::{Read, Write, WriteRead};
#[cfg(any(feature = "stm32l4x1", feature = "stm32l4x2", feature = "stm32l4x6"))]
use crate::pac::I2C4;
use crate::pac::{i2c1, I2C1, I2C2, I2C3};
#[cfg(any(feature = "stm32l4x1", feature = "stm32l4x2", feature = "stm32l4x6"))]
use crate::rcc::APB1R2;

use crate::rcc::{Clocks, Enable, RccBus, Reset};
use crate::time::Hertz;
Expand Down
3 changes: 1 addition & 2 deletions src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ pub use crate::dma::DmaExt as _stm32l4_hal_DmaExt;
pub use crate::flash::FlashExt as _stm32l4_hal_FlashExt;
pub use crate::gpio::ExtiPin as _stm32l4_hal_ExtiPin;
pub use crate::gpio::GpioExt as _stm32l4_hal_GpioExt;
pub use crate::pwm::PwmExt1 as _stm32l4_hal_PwmExt1;
pub use crate::pwm::PwmExt2 as _stm32l4_hal_PwmExt2;
pub use crate::pwm::PwmExt as _stm32l4_hal_PwmExt;
pub use crate::pwr::PwrExt as _stm32l4_hal_PwrExt;
pub use crate::rcc::RccExt as _stm32l4_hal_RccExt;
pub use crate::rng::RngExt as _stm32l4_hal_RngExt;
Expand Down
76 changes: 42 additions & 34 deletions src/pwm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::stm32::{TIM1, TIM15, TIM2};
use crate::gpio::gpioa::{PA0, PA1, PA10, PA11, PA15, PA2, PA3, PA8, PA9};
use crate::gpio::gpiob::{PB10, PB11, PB14, PB3};
use crate::gpio::Alternate;
use crate::rcc::{Clocks, Enable, Reset, APB1R1, APB2};
use crate::rcc::{BusTimerClock, Clocks, Enable, RccBus, Reset};
use crate::time::Hertz;

// NB: REMAP is not implemented!
Expand Down Expand Up @@ -103,28 +103,27 @@ pins_to_channels_mapping! {
// TIM15: (PA2, PA3), (C1, C2), (14, 14);
}

pub trait PwmExt1: Sized {
fn pwm<PINS, T>(self, _: PINS, frequency: T, clocks: Clocks, apb: &mut APB2) -> PINS::Channels
where
PINS: Pins<Self>,
T: Into<Hertz>;
}

pub trait PwmExt2: Sized {
pub trait PwmExt: Sized + RccBus {
fn pwm<PINS, T>(
self,
_: PINS,
frequency: T,
clocks: Clocks,
apb: &mut APB1R1,
apb: &mut Self::Bus,
) -> PINS::Channels
where
PINS: Pins<Self>,
T: Into<Hertz>;
}

impl PwmExt1 for TIM1 {
fn pwm<PINS, T>(self, _pins: PINS, freq: T, clocks: Clocks, apb: &mut APB2) -> PINS::Channels
impl PwmExt for TIM1 {
fn pwm<PINS, T>(
self,
_pins: PINS,
freq: T,
clocks: Clocks,
apb: &mut Self::Bus,
) -> PINS::Channels
where
PINS: Pins<Self>,
T: Into<Hertz>,
Expand All @@ -133,8 +132,14 @@ impl PwmExt1 for TIM1 {
}
}

impl PwmExt1 for TIM15 {
fn pwm<PINS, T>(self, _pins: PINS, freq: T, clocks: Clocks, apb: &mut APB2) -> PINS::Channels
impl PwmExt for TIM15 {
fn pwm<PINS, T>(
self,
_pins: PINS,
freq: T,
clocks: Clocks,
apb: &mut Self::Bus,
) -> PINS::Channels
where
PINS: Pins<Self>,
T: Into<Hertz>,
Expand All @@ -143,8 +148,14 @@ impl PwmExt1 for TIM15 {
}
}

impl PwmExt2 for TIM2 {
fn pwm<PINS, T>(self, _pins: PINS, freq: T, clocks: Clocks, apb: &mut APB1R1) -> PINS::Channels
impl PwmExt for TIM2 {
fn pwm<PINS, T>(
self,
_pins: PINS,
freq: T,
clocks: Clocks,
apb: &mut Self::Bus,
) -> PINS::Channels
where
PINS: Pins<Self>,
T: Into<Hertz>,
Expand All @@ -170,14 +181,14 @@ pub struct C3;
pub struct C4;

macro_rules! advanced_timer {
($($TIMX:ident: ($timX:ident, $apb:ident, $psc_width:ident, $arr_width:ident),)+) => {
($($TIMX:ident: ($timX:ident, $psc_width:ident, $arr_width:ident),)+) => {
$(
fn $timX<PINS>(
tim: $TIMX,
_pins: PINS,
freq: Hertz,
clocks: Clocks,
apb: &mut $apb,
apb: &mut <$TIMX as RccBus>::Bus,
) -> PINS::Channels
where
PINS: Pins<$TIMX>,
Expand All @@ -201,9 +212,8 @@ macro_rules! advanced_timer {
tim.ccmr2_output().modify(|_, w| w.oc4pe().set_bit().oc4m().bits(6));
}

let clk = clocks.pclk2().0;
let freq = freq.0;
let ticks = clk / freq;
let clk = <$TIMX as BusTimerClock>::timer_clock(&clocks);
let ticks = clk.0 / freq.0;

// maybe this is all u32? also, why no `- 1` vs `timer.rs`?
let psc = ticks / (1 << 16);
Expand Down Expand Up @@ -239,14 +249,14 @@ macro_rules! advanced_timer {
}

macro_rules! standard_timer {
($($TIMX:ident: ($timX:ident, $apb:ident, $psc_width:ident, $arr_width:ident),)+) => {
($($TIMX:ident: ($timX:ident, $psc_width:ident, $arr_width:ident),)+) => {
$(
fn $timX<PINS>(
tim: $TIMX,
_pins: PINS,
freq: Hertz,
clocks: Clocks,
apb: &mut $apb,
apb: &mut <$TIMX as RccBus>::Bus,
) -> PINS::Channels
where
PINS: Pins<$TIMX>,
Expand All @@ -270,9 +280,8 @@ macro_rules! standard_timer {
tim.ccmr2_output().modify(|_, w| w.oc4pe().set_bit().oc4m().bits(6));
}

let clk = clocks.pclk1().0;
let freq = freq.0;
let ticks = clk / freq;
let clk = <$TIMX as BusTimerClock>::timer_clock(&clocks);
let ticks = clk.0 / freq.0;

// maybe this is all u32? also, why no `- 1` vs `timer.rs`?
let psc = ticks / (1 << 16);
Expand Down Expand Up @@ -304,14 +313,14 @@ macro_rules! standard_timer {
}

macro_rules! small_timer {
($($TIMX:ident: ($timX:ident, $apb:ident, $psc_width:ident, $arr_width:ident),)+) => {
($($TIMX:ident: ($timX:ident, $psc_width:ident, $arr_width:ident),)+) => {
$(
fn $timX<PINS>(
tim: $TIMX,
_pins: PINS,
freq: Hertz,
clocks: Clocks,
apb: &mut $apb,
apb: &mut <$TIMX as RccBus>::Bus,
) -> PINS::Channels
where
PINS: Pins<$TIMX>,
Expand All @@ -328,9 +337,8 @@ macro_rules! small_timer {
// tim.ccmr1_output().modify(|_, w| w.oc2pe().set_bit().oc2m().bits(6));
// }

let clk = clocks.pclk1().0;
let freq = freq.0;
let ticks = clk / freq;
let clk = <$TIMX as BusTimerClock>::timer_clock(&clocks);
let ticks = clk.0 / freq.0;

// maybe this is all u32? also, why no `- 1` vs `timer.rs`?
let psc = ticks / (1 << 16);
Expand Down Expand Up @@ -396,13 +404,13 @@ macro_rules! pwm_channels {
}

advanced_timer! {
TIM1: (tim1, APB2, u16, u16),
TIM1: (tim1, u16, u16),
}

standard_timer! {
TIM2: (tim2, APB1R1, u16, u32),
TIM2: (tim2, u16, u32),
}

small_timer! {
TIM15: (tim15, APB2, u16, u16),
TIM15: (tim15, u16, u16),
}
73 changes: 66 additions & 7 deletions src/rcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ impl BDCR {
}

macro_rules! bus_struct {
($($busX:ident => ($EN:ident, $en:ident, $SMEN:ident, $smen:ident, $RST:ident, $rst:ident, $doc:literal),)+) => {
($($busX:ident => ($EN:ident, $en:ident, $SMEN:ident, $smen:ident, $RST:ident, $rst:ident, $clk:ident, $doc:literal),)+) => {
$(
#[doc = $doc]
pub struct $busX {
Expand Down Expand Up @@ -214,17 +214,23 @@ macro_rules! bus_struct {
unsafe { &(*RCC::ptr()).$rst }
}
}

impl BusClock for $busX {
fn clock(clocks: &Clocks) -> Hertz {
clocks.$clk
}
}
)+
};
}

bus_struct! {
AHB1 => (AHB1ENR, ahb1enr, AHB1SMENR, ahb1smenr, AHB1RSTR, ahb1rstr, "Advanced High-performance Bus 1 (AHB1) registers"),
AHB2 => (AHB2ENR, ahb2enr, AHB2SMENR, ahb2smenr, AHB2RSTR, ahb2rstr, "Advanced High-performance Bus 2 (AHB2) registers"),
AHB3 => (AHB3ENR, ahb3enr, AHB3SMENR, ahb3smenr, AHB3RSTR, ahb3rstr, "Advanced High-performance Bus 3 (AHB3) registers"),
APB1R1 => (APB1ENR1, apb1enr1, APB1SMENR1, apb1smenr1, APB1RSTR1, apb1rstr1, "Advanced Peripheral Bus 1 (APB1) registers"),
APB1R2 => (APB1ENR2, apb1enr2, APB1SMENR2, apb1smenr2, APB1RSTR2, apb1rstr2, "Advanced Peripheral Bus 1 (APB1) registers"),
APB2 => (APB2ENR, apb2enr, APB2SMENR, apb2smenr, APB2RSTR, apb2rstr, "Advanced Peripheral Bus 2 (APB2) registers"),
AHB1 => (AHB1ENR, ahb1enr, AHB1SMENR, ahb1smenr, AHB1RSTR, ahb1rstr, hclk, "Advanced High-performance Bus 1 (AHB1) registers"),
AHB2 => (AHB2ENR, ahb2enr, AHB2SMENR, ahb2smenr, AHB2RSTR, ahb2rstr, hclk, "Advanced High-performance Bus 2 (AHB2) registers"),
AHB3 => (AHB3ENR, ahb3enr, AHB3SMENR, ahb3smenr, AHB3RSTR, ahb3rstr, hclk, "Advanced High-performance Bus 3 (AHB3) registers"),
APB1R1 => (APB1ENR1, apb1enr1, APB1SMENR1, apb1smenr1, APB1RSTR1, apb1rstr1, pclk1, "Advanced Peripheral Bus 1 (APB1) registers"),
APB1R2 => (APB1ENR2, apb1enr2, APB1SMENR2, apb1smenr2, APB1RSTR2, apb1rstr2, pclk1, "Advanced Peripheral Bus 1 (APB1) registers"),
APB2 => (APB2ENR, apb2enr, APB2SMENR, apb2smenr, APB2RSTR, apb2rstr, pclk2, "Advanced Peripheral Bus 2 (APB2) registers"),
}

/// Bus associated to peripheral
Expand Down Expand Up @@ -294,6 +300,59 @@ pub trait Reset: RccBus {
unsafe fn reset_unchecked();
}

/// Frequency on bus that peripheral is connected in
pub trait BusClock {
/// Calculates frequency depending on `Clock` state
fn clock(clocks: &Clocks) -> Hertz;
}

impl<T> BusClock for T
where
T: RccBus,
T::Bus: BusClock,
{
fn clock(clocks: &Clocks) -> Hertz {
T::Bus::clock(clocks)
}
}

/// Frequency on bus that timer is connected in
pub trait BusTimerClock {
/// Calculates base frequency of timer depending on `Clock` state
fn timer_clock(clocks: &Clocks) -> Hertz;
}

impl<T> BusTimerClock for T
where
T: RccBus,
T::Bus: BusTimerClock,
{
fn timer_clock(clocks: &Clocks) -> Hertz {
T::Bus::timer_clock(clocks)
}
}

impl BusTimerClock for APB1R1 {
fn timer_clock(clocks: &Clocks) -> Hertz {
let pclk_mul = if clocks.ppre1 > 1 { 2 } else { 1 };
Hertz(clocks.pclk1.0 * pclk_mul)
}
}

impl BusTimerClock for APB1R2 {
fn timer_clock(clocks: &Clocks) -> Hertz {
let pclk_mul = if clocks.ppre1 > 1 { 2 } else { 1 };
Hertz(clocks.pclk1.0 * pclk_mul)
}
}

impl BusTimerClock for APB2 {
fn timer_clock(clocks: &Clocks) -> Hertz {
let pclk_mul = if clocks.ppre2 > 1 { 2 } else { 1 };
Hertz(clocks.pclk2.0 * pclk_mul)
}
}

#[derive(Debug, PartialEq)]
/// HSE Configuration
struct HseConfig {
Expand Down
Loading

0 comments on commit e6286a5

Please sign in to comment.