Skip to content

Commit

Permalink
Merge pull request #2021 from embassy-rs/stm32-mco
Browse files Browse the repository at this point in the history
stm32: add MCO for all chips
  • Loading branch information
Dirbaio authored Oct 6, 2023
2 parents f30fc94 + 3a8e0d4 commit 7a2b848
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 351 deletions.
4 changes: 2 additions & 2 deletions embassy-stm32/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ sdio-host = "0.5.0"
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
critical-section = "1.1"
atomic-polyfill = "1.0.1"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0f06b4c95bd9e185e4aa5f2e1d4b76ba84f1594" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a7bf7f02d1e0bc720c24dbb8881677a298890365" }
vcell = "0.1.3"
bxcan = "0.7.0"
nb = "1.0.0"
Expand All @@ -78,7 +78,7 @@ critical-section = { version = "1.1", features = ["std"] }
[build-dependencies]
proc-macro2 = "1.0.36"
quote = "1.0.15"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0f06b4c95bd9e185e4aa5f2e1d4b76ba84f1594", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a7bf7f02d1e0bc720c24dbb8881677a298890365", default-features = false, features = ["metadata"]}


[features]
Expand Down
35 changes: 10 additions & 25 deletions embassy-stm32/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ fn main() {
// We *shouldn't* have singletons for these, but the HAL currently requires
// singletons, for using with RccPeripheral to enable/disable clocks to them.
"rcc" => {
if r.version.starts_with("h5") || r.version.starts_with("h7") || r.version.starts_with("f4") {
singletons.push("MCO1".to_string());
singletons.push("MCO2".to_string());
}
if r.version.starts_with("l4") {
singletons.push("MCO".to_string());
for pin in p.pins {
if pin.signal.starts_with("MCO") {
let name = pin.signal.replace('_', "").to_string();
if !singletons.contains(&name) {
println!("cargo:rustc-cfg={}", name.to_ascii_lowercase());
singletons.push(name);
}
}
}
singletons.push(p.name.to_string());
}
Expand Down Expand Up @@ -751,25 +753,8 @@ fn main() {
let af = pin.af.unwrap_or(0);

// MCO is special
if pin.signal.starts_with("MCO_") {
// Supported in H7 only for now
if regs.version.starts_with("h5")
|| regs.version.starts_with("h7")
|| regs.version.starts_with("f4")
{
peri = format_ident!("{}", pin.signal.replace('_', ""));
} else {
continue;
}
}

if pin.signal == "MCO" {
// Supported in H7 only for now
if regs.version.starts_with("l4") {
peri = format_ident!("MCO");
} else {
continue;
}
if pin.signal.starts_with("MCO") {
peri = format_ident!("{}", pin.signal.replace('_', ""));
}

g.extend(quote! {
Expand Down
166 changes: 0 additions & 166 deletions embassy-stm32/src/rcc/f4.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
use core::marker::PhantomData;

use embassy_hal_internal::into_ref;
use stm32_metapac::rcc::vals::{Mco1, Mco2, Mcopre};

use crate::gpio::sealed::AFType;
use crate::gpio::Speed;
use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
use crate::pac::{FLASH, PWR, RCC};
use crate::rcc::bd::{BackupDomain, RtcClockSource};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
use crate::{peripherals, Peripheral};

/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
Expand Down Expand Up @@ -197,164 +189,6 @@ fn setup_pll(
}
}

pub enum McoClock {
DIV1,
DIV2,
DIV3,
DIV4,
DIV5,
}

impl McoClock {
fn into_raw(&self) -> Mcopre {
match self {
McoClock::DIV1 => Mcopre::DIV1,
McoClock::DIV2 => Mcopre::DIV2,
McoClock::DIV3 => Mcopre::DIV3,
McoClock::DIV4 => Mcopre::DIV4,
McoClock::DIV5 => Mcopre::DIV5,
}
}
}

#[derive(Copy, Clone)]
pub enum Mco1Source {
Hsi,
Lse,
Hse,
Pll,
}

impl Default for Mco1Source {
fn default() -> Self {
Self::Hsi
}
}

pub trait McoSource {
type Raw;

fn into_raw(&self) -> Self::Raw;
}

impl McoSource for Mco1Source {
type Raw = Mco1;
fn into_raw(&self) -> Self::Raw {
match self {
Mco1Source::Hsi => Mco1::HSI,
Mco1Source::Lse => Mco1::LSE,
Mco1Source::Hse => Mco1::HSE,
Mco1Source::Pll => Mco1::PLL,
}
}
}

#[derive(Copy, Clone)]
pub enum Mco2Source {
SysClk,
Plli2s,
Hse,
Pll,
}

impl Default for Mco2Source {
fn default() -> Self {
Self::SysClk
}
}

impl McoSource for Mco2Source {
type Raw = Mco2;
fn into_raw(&self) -> Self::Raw {
match self {
Mco2Source::SysClk => Mco2::SYSCLK,
Mco2Source::Plli2s => Mco2::PLLI2S,
Mco2Source::Hse => Mco2::HSE,
Mco2Source::Pll => Mco2::PLL,
}
}
}

pub(crate) mod sealed {
use stm32_metapac::rcc::vals::Mcopre;
pub trait McoInstance {
type Source;
unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre);
}
}

pub trait McoInstance: sealed::McoInstance + 'static {}

pin_trait!(McoPin, McoInstance);

impl sealed::McoInstance for peripherals::MCO1 {
type Source = Mco1;
unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) {
RCC.cfgr().modify(|w| {
w.set_mco1(source);
w.set_mco1pre(prescaler);
});
match source {
Mco1::PLL => {
RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {}
}
Mco1::HSI => {
RCC.cr().modify(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
}
_ => {}
}
}
}
impl McoInstance for peripherals::MCO1 {}

impl sealed::McoInstance for peripherals::MCO2 {
type Source = Mco2;
unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) {
RCC.cfgr().modify(|w| {
w.set_mco2(source);
w.set_mco2pre(prescaler);
});
match source {
Mco2::PLL => {
RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {}
}
#[cfg(not(stm32f410))]
Mco2::PLLI2S => {
RCC.cr().modify(|w| w.set_plli2son(true));
while !RCC.cr().read().plli2srdy() {}
}
_ => {}
}
}
}
impl McoInstance for peripherals::MCO2 {}

pub struct Mco<'d, T: McoInstance> {
phantom: PhantomData<&'d mut T>,
}

impl<'d, T: McoInstance> Mco<'d, T> {
pub fn new(
_peri: impl Peripheral<P = T> + 'd,
pin: impl Peripheral<P = impl McoPin<T>> + 'd,
source: impl McoSource<Raw = T::Source>,
prescaler: McoClock,
) -> Self {
into_ref!(pin);

critical_section::with(|_| unsafe {
T::apply_clock_settings(source.into_raw(), prescaler.into_raw());
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
pin.set_speed(Speed::VeryHigh);
});

Self { phantom: PhantomData }
}
}

fn flash_setup(sysclk: u32) {
use crate::pac::flash::vals::Latency;

Expand Down
132 changes: 0 additions & 132 deletions embassy-stm32/src/rcc/l4.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
use core::marker::PhantomData;

use embassy_hal_internal::into_ref;
use stm32_metapac::rcc::regs::Cfgr;
use stm32_metapac::rcc::vals::{Mcopre, Mcosel};

pub use super::bus::{AHBPrescaler, APBPrescaler};
use crate::gpio::sealed::AFType;
use crate::gpio::Speed;
use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
use crate::pac::{FLASH, RCC};
use crate::rcc::bd::{BackupDomain, RtcClockSource};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
use crate::{peripherals, Peripheral};

/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
Expand Down Expand Up @@ -263,131 +256,6 @@ impl Default for Config {
}
}

pub enum McoClock {
DIV1,
DIV2,
DIV4,
DIV8,
DIV16,
}

impl McoClock {
fn into_raw(&self) -> Mcopre {
match self {
McoClock::DIV1 => Mcopre::DIV1,
McoClock::DIV2 => Mcopre::DIV2,
McoClock::DIV4 => Mcopre::DIV4,
McoClock::DIV8 => Mcopre::DIV8,
McoClock::DIV16 => Mcopre::DIV16,
}
}
}

#[derive(Copy, Clone)]
pub enum Mco1Source {
Disabled,
Lse,
Lsi,
Hse,
Hsi16,
PllClk,
SysClk,
Msi,
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
Hsi48,
}

impl Default for Mco1Source {
fn default() -> Self {
Self::Hsi16
}
}

pub trait McoSource {
type Raw;

fn into_raw(&self) -> Self::Raw;
}

impl McoSource for Mco1Source {
type Raw = Mcosel;
fn into_raw(&self) -> Self::Raw {
match self {
Mco1Source::Disabled => Mcosel::NOCLOCK,
Mco1Source::Lse => Mcosel::LSE,
Mco1Source::Lsi => Mcosel::LSI,
Mco1Source::Hse => Mcosel::HSE,
Mco1Source::Hsi16 => Mcosel::HSI16,
Mco1Source::PllClk => Mcosel::PLL,
Mco1Source::SysClk => Mcosel::SYSCLK,
Mco1Source::Msi => Mcosel::MSI,
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
Mco1Source::Hsi48 => Mcosel::HSI48,
}
}
}

pub(crate) mod sealed {
use stm32_metapac::rcc::vals::Mcopre;
pub trait McoInstance {
type Source;
unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre);
}
}

pub trait McoInstance: sealed::McoInstance + 'static {}

pin_trait!(McoPin, McoInstance);

impl sealed::McoInstance for peripherals::MCO {
type Source = Mcosel;

unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) {
RCC.cfgr().modify(|w| {
w.set_mcosel(source);
w.set_mcopre(prescaler);
});

match source {
Mcosel::HSI16 => {
RCC.cr().modify(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
}
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
Mcosel::HSI48 => {
RCC.crrcr().modify(|w| w.set_hsi48on(true));
while !RCC.crrcr().read().hsi48rdy() {}
}
_ => {}
}
}
}

impl McoInstance for peripherals::MCO {}

pub struct Mco<'d, T: McoInstance> {
phantom: PhantomData<&'d mut T>,
}

impl<'d, T: McoInstance> Mco<'d, T> {
pub fn new(
_peri: impl Peripheral<P = T> + 'd,
pin: impl Peripheral<P = impl McoPin<T>> + 'd,
source: impl McoSource<Raw = T::Source>,
prescaler: McoClock,
) -> Self {
into_ref!(pin);

critical_section::with(|_| unsafe {
T::apply_clock_settings(source.into_raw(), prescaler.into_raw());
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
pin.set_speed(Speed::VeryHigh);
});

Self { phantom: PhantomData }
}
}

pub(crate) unsafe fn init(config: Config) {
// Switch to MSI to prevent problems with PLL configuration.
if !RCC.cr().read().msion() {
Expand Down
Loading

0 comments on commit 7a2b848

Please sign in to comment.