Skip to content
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

BusClock #302

Merged
merged 1 commit into from
Nov 19, 2021
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
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