Skip to content

Commit

Permalink
BusClock & macro cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Nov 19, 2021
1 parent ae12718 commit d3af40e
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 289 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Added

- `BusClock` and `BusTimerClock` traits ([#302])
- `RccBus`, `Enable`, `Reset` traits and implementations for peripherals ([#299])
- Support cortex-m-rt `v0.7.0` but still allow `v0.6.13` ([#283])

### Fixed
Expand Down Expand Up @@ -500,6 +502,8 @@ let clocks = rcc
[defmt]: https://github.com/knurling-rs/defmt
[filter]: https://defmt.ferrous-systems.com/filtering.html

[#302]: https://github.com/stm32-rs/stm32f3xx-hal/pull/302
[#299]: https://github.com/stm32-rs/stm32f3xx-hal/pull/299
[#291]: https://github.com/stm32-rs/stm32f3xx-hal/pull/291
[#283]: https://github.com/stm32-rs/stm32f3xx-hal/pull/283
[#282]: https://github.com/stm32-rs/stm32f3xx-hal/pull/282
Expand Down
61 changes: 61 additions & 0 deletions src/rcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,67 @@ 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)
}
}

impl BusClock for AHB {
fn clock(clocks: &Clocks) -> Hertz {
clocks.hclk
}
}
impl BusClock for APB1 {
fn clock(clocks: &Clocks) -> Hertz {
clocks.pclk1
}
}
impl BusClock for APB2 {
fn clock(clocks: &Clocks) -> Hertz {
clocks.pclk2
}
}

/// 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 APB1 {
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)
}
}

/// Frequency of interal hardware RC oscillator (HSI OSC)
pub const HSI: Hertz = Hertz(8_000_000);
/// Frequency of external 32.768 kHz oscillator (LSE OSC)
Expand Down
102 changes: 37 additions & 65 deletions src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1195,13 +1195,7 @@ pub trait Instance:
macro_rules! usart {
(
$(
$USARTX:ident: (
$usartXen:ident,
$INTERRUPT:path,
$pclkX:ident,
$usartXsw:ident,
$usartXclock:ident
),
$USARTX:ident: ($INTERRUPT:path),
)+
) => {
$(
Expand All @@ -1210,16 +1204,6 @@ macro_rules! usart {
const INTERRUPT: Interrupt = $INTERRUPT;
}

impl Instance for $USARTX {
fn clock(clocks: &Clocks) -> Hertz {
// Use the function created via another macro outside of this one,
// because the implementation is dependend on the type $USARTX.
// But macros can not differentiate between types.
$usartXclock(clocks)
}
}


impl<Tx, Rx> Serial<$USARTX, (Tx, Rx)>
where Tx: TxPin<$USARTX>, Rx: RxPin<$USARTX> {
/// Splits the [`Serial`] abstraction into a transmitter and a receiver half.
Expand Down Expand Up @@ -1275,17 +1259,11 @@ macro_rules! usart {
)+
};

([ $(($X:literal, $APB:literal, $INTERRUPT:path)),+ ]) => {
([ $(($X:literal, $INTERRUPT:path)),+ ]) => {
paste::paste! {
usart!(
$(
[<USART $X>]: (
[<usart $X en>],
$INTERRUPT,
[<pclk $APB>],
[<usart $X sw>],
[<usart $X clock>]
),
[<USART $X>]: ($INTERRUPT),
)+
);
}
Expand All @@ -1296,19 +1274,19 @@ macro_rules! usart {
/// the only clock source can be the peripheral clock
#[allow(unused_macros)]
macro_rules! usart_static_clock {
($($usartXclock:ident, $pclkX:ident),+) => {
($($USARTX:ident),+) => {
$(
/// Return the currently set source frequency the UART peripheral
/// depending on the clock source.
fn $usartXclock(clocks: &Clocks) -> Hertz {
clocks.$pclkX()
impl Instance for $USARTX {
fn clock(clocks: &Clocks) -> Hertz {
<$USARTX as rcc::BusClock>::clock(clocks)
}
}
)+
};
([ $(($X:literal, $APB:literal)),+ ]) => {
($($X:literal),+) => {
paste::paste! {
usart_static_clock!(
$([<usart $X clock>], [<pclk $APB>]),+
$([<USART $X>]),+
);
}
};
Expand All @@ -1317,25 +1295,25 @@ macro_rules! usart_static_clock {
/// Generates a clock function for UART Peripherals, where
/// the clock source can vary.
macro_rules! usart_var_clock {
($($usartXclock:ident, $usartXsw:ident, $pclkX:ident),+) => {
($($USARTX:ident, $usartXsw:ident),+) => {
$(
/// Return the currently set source frequency for the UART peripheral
/// depending on the clock source.
fn $usartXclock(clocks: &Clocks) -> Hertz {
// NOTE(unsafe): atomic read with no side effects
match unsafe {(*RCC::ptr()).cfgr3.read().$usartXsw().variant()} {
USART1SW_A::PCLK => clocks.$pclkX(),
USART1SW_A::HSI => crate::rcc::HSI,
USART1SW_A::SYSCLK => clocks.sysclk(),
USART1SW_A::LSE => crate::rcc::LSE,
impl Instance for $USARTX {
fn clock(clocks: &Clocks) -> Hertz {
// NOTE(unsafe): atomic read with no side effects
match unsafe {(*RCC::ptr()).cfgr3.read().$usartXsw().variant()} {
USART1SW_A::PCLK => <$USARTX as rcc::BusClock>::clock(clocks),
USART1SW_A::HSI => crate::rcc::HSI,
USART1SW_A::SYSCLK => clocks.sysclk(),
USART1SW_A::LSE => crate::rcc::LSE,
}
}
}
)+
};
([ $(($X:literal, $APB:literal)),+ ]) => {
($($X:literal),+) => {
paste::paste! {
usart_var_clock!(
$([<usart $X clock>], [<usart $X sw>], [<pclk $APB>]),+
$([<USART $X>], [<usart $X sw>]),+
);
}
};
Expand All @@ -1357,62 +1335,56 @@ cfg_if::cfg_if! {
))] {
// USART1 is accessed through APB2,
// but USART1SW_A::PCLK will connect its phy to PCLK1.
usart_var_clock!([(1,1)]);
usart_var_clock!(1);
// These are uart peripherals, where the only clock source
// is the PCLK (peripheral clock).
usart_static_clock!([(2,1), (3,1)]);
usart_static_clock!(2, 3);
} else {
usart_var_clock!([(1, 2), (2, 1), (3, 1)]);
usart_var_clock!(1, 2, 3);
}
}

#[cfg(not(feature = "svd-f373"))]
usart!([
(1, 2, Interrupt::USART1_EXTI25),
(2, 1, Interrupt::USART2_EXTI26),
(3, 1, Interrupt::USART3_EXTI28)
(1, Interrupt::USART1_EXTI25),
(2, Interrupt::USART2_EXTI26),
(3, Interrupt::USART3_EXTI28)
]);
#[cfg(feature = "svd-f373")]
usart!([
(1, 2, Interrupt::USART1),
(2, 1, Interrupt::USART2),
(3, 1, Interrupt::USART3)
(1, Interrupt::USART1),
(2, Interrupt::USART2),
(3, Interrupt::USART3)
]);

cfg_if::cfg_if! {
// See table 29.4 RM0316
if #[cfg(any(feature = "gpio-f303", feature = "gpio-f303e"))] {

macro_rules! uart {
([ $(($X:literal, $APB:literal, $INTERRUPT:path)),+ ]) => {
([ $(($X:literal, $INTERRUPT:path)),+ ]) => {
paste::paste! {
usart!(
$(
[<UART $X>]: (
[<uart $X en>],
$INTERRUPT,
[<pclk $APB>],
[<uart $X sw>],
[<usart $X clock>]
),
[<UART $X>]: ($INTERRUPT),
)+
);
}
};
}

macro_rules! uart_var_clock {
([ $(($X:literal, $APB:literal)),+ ]) => {
($($X:literal),+) => {
paste::paste! {
usart_var_clock!(
$([<usart $X clock>], [<uart $X sw>], [<pclk $APB>]),+
$([<UART $X>], [<uart $X sw>]),+
);
}
};
}

uart_var_clock!([(4,1), (5,1)]);
uart!([(4,1, Interrupt::UART4_EXTI34), (5,1, Interrupt::UART5_EXTI35)]);
uart_var_clock!(4, 5);
uart!([(4, Interrupt::UART4_EXTI34), (5, Interrupt::UART5_EXTI35)]);

impl Dma for UART4 {}

Expand Down
11 changes: 3 additions & 8 deletions src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::pac::{
use crate::{
gpio::{self, PushPull, AF5, AF6},
rcc::{self, Clocks},
time::rate::{self, Hertz},
time::rate,
};

/// SPI error
Expand Down Expand Up @@ -401,9 +401,8 @@ pub trait Instance:
+ crate::private::Sealed
+ rcc::Enable
+ rcc::Reset
+ rcc::BusClock
{
#[doc(hidden)]
fn clock(clocks: &Clocks) -> Hertz;
}

macro_rules! spi {
Expand All @@ -414,11 +413,7 @@ macro_rules! spi {
const INTERRUPT: Self::Interrupt = interrupts::$SPIX;
}

impl Instance for pac::$SPIX {
fn clock(clocks: &Clocks) -> Hertz {
clocks.$pclkX()
}
}
impl Instance for pac::$SPIX { }

#[cfg(feature = "defmt")]
impl<Pins> defmt::Format for Spi<pac::$SPIX, Pins> {
Expand Down
Loading

0 comments on commit d3af40e

Please sign in to comment.