Merge pull request #2021 from embassy-rs/stm32-mco
stm32: add MCO for all chips
This commit is contained in:
commit
7a2b8481f7
10 changed files with 52 additions and 351 deletions
|
@ -59,7 +59,7 @@ sdio-host = "0.5.0"
|
||||||
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
|
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
|
||||||
critical-section = "1.1"
|
critical-section = "1.1"
|
||||||
atomic-polyfill = "1.0.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"
|
vcell = "0.1.3"
|
||||||
bxcan = "0.7.0"
|
bxcan = "0.7.0"
|
||||||
nb = "1.0.0"
|
nb = "1.0.0"
|
||||||
|
@ -78,7 +78,7 @@ critical-section = { version = "1.1", features = ["std"] }
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
proc-macro2 = "1.0.36"
|
proc-macro2 = "1.0.36"
|
||||||
quote = "1.0.15"
|
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]
|
[features]
|
||||||
|
|
|
@ -50,12 +50,14 @@ fn main() {
|
||||||
// We *shouldn't* have singletons for these, but the HAL currently requires
|
// We *shouldn't* have singletons for these, but the HAL currently requires
|
||||||
// singletons, for using with RccPeripheral to enable/disable clocks to them.
|
// singletons, for using with RccPeripheral to enable/disable clocks to them.
|
||||||
"rcc" => {
|
"rcc" => {
|
||||||
if r.version.starts_with("h5") || r.version.starts_with("h7") || r.version.starts_with("f4") {
|
for pin in p.pins {
|
||||||
singletons.push("MCO1".to_string());
|
if pin.signal.starts_with("MCO") {
|
||||||
singletons.push("MCO2".to_string());
|
let name = pin.signal.replace('_', "").to_string();
|
||||||
}
|
if !singletons.contains(&name) {
|
||||||
if r.version.starts_with("l4") {
|
println!("cargo:rustc-cfg={}", name.to_ascii_lowercase());
|
||||||
singletons.push("MCO".to_string());
|
singletons.push(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
singletons.push(p.name.to_string());
|
singletons.push(p.name.to_string());
|
||||||
}
|
}
|
||||||
|
@ -751,25 +753,8 @@ fn main() {
|
||||||
let af = pin.af.unwrap_or(0);
|
let af = pin.af.unwrap_or(0);
|
||||||
|
|
||||||
// MCO is special
|
// MCO is special
|
||||||
if pin.signal.starts_with("MCO_") {
|
if pin.signal.starts_with("MCO") {
|
||||||
// Supported in H7 only for now
|
peri = format_ident!("{}", pin.signal.replace('_', ""));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g.extend(quote! {
|
g.extend(quote! {
|
||||||
|
|
|
@ -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::rcc::vals::{Hpre, Ppre, Sw};
|
||||||
use crate::pac::{FLASH, PWR, RCC};
|
use crate::pac::{FLASH, PWR, RCC};
|
||||||
use crate::rcc::bd::{BackupDomain, RtcClockSource};
|
use crate::rcc::bd::{BackupDomain, RtcClockSource};
|
||||||
use crate::rcc::{set_freqs, Clocks};
|
use crate::rcc::{set_freqs, Clocks};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::{peripherals, Peripheral};
|
|
||||||
|
|
||||||
/// HSI speed
|
/// HSI speed
|
||||||
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
|
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
|
||||||
|
@ -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) {
|
fn flash_setup(sysclk: u32) {
|
||||||
use crate::pac::flash::vals::Latency;
|
use crate::pac::flash::vals::Latency;
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,11 @@
|
||||||
use core::marker::PhantomData;
|
|
||||||
|
|
||||||
use embassy_hal_internal::into_ref;
|
|
||||||
use stm32_metapac::rcc::regs::Cfgr;
|
use stm32_metapac::rcc::regs::Cfgr;
|
||||||
use stm32_metapac::rcc::vals::{Mcopre, Mcosel};
|
|
||||||
|
|
||||||
pub use super::bus::{AHBPrescaler, APBPrescaler};
|
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::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
|
||||||
use crate::pac::{FLASH, RCC};
|
use crate::pac::{FLASH, RCC};
|
||||||
use crate::rcc::bd::{BackupDomain, RtcClockSource};
|
use crate::rcc::bd::{BackupDomain, RtcClockSource};
|
||||||
use crate::rcc::{set_freqs, Clocks};
|
use crate::rcc::{set_freqs, Clocks};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::{peripherals, Peripheral};
|
|
||||||
|
|
||||||
/// HSI speed
|
/// HSI speed
|
||||||
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
|
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
|
||||||
|
@ -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) {
|
pub(crate) unsafe fn init(config: Config) {
|
||||||
// Switch to MSI to prevent problems with PLL configuration.
|
// Switch to MSI to prevent problems with PLL configuration.
|
||||||
if !RCC.cr().read().msion() {
|
if !RCC.cr().read().msion() {
|
||||||
|
|
|
@ -4,14 +4,19 @@ use embassy_hal_internal::into_ref;
|
||||||
|
|
||||||
use crate::gpio::sealed::AFType;
|
use crate::gpio::sealed::AFType;
|
||||||
use crate::gpio::Speed;
|
use crate::gpio::Speed;
|
||||||
pub use crate::pac::rcc::vals::{Mco1 as Mco1Source, Mco2 as Mco2Source};
|
#[cfg(not(stm32f1))]
|
||||||
|
pub use crate::pac::rcc::vals::Mcopre as McoPrescaler;
|
||||||
|
#[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))]
|
||||||
|
pub use crate::pac::rcc::vals::Mcosel as McoSource;
|
||||||
|
#[cfg(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7))]
|
||||||
|
pub use crate::pac::rcc::vals::{Mco1sel as Mco1Source, Mco2sel as Mco2Source};
|
||||||
use crate::pac::RCC;
|
use crate::pac::RCC;
|
||||||
use crate::{peripherals, Peripheral};
|
use crate::{peripherals, Peripheral};
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
pub trait McoInstance {
|
pub trait McoInstance {
|
||||||
type Source;
|
type Source;
|
||||||
unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8);
|
unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: super::McoPrescaler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,9 +29,15 @@ macro_rules! impl_peri {
|
||||||
impl sealed::McoInstance for peripherals::$peri {
|
impl sealed::McoInstance for peripherals::$peri {
|
||||||
type Source = $source;
|
type Source = $source;
|
||||||
|
|
||||||
unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8) {
|
unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: McoPrescaler) {
|
||||||
RCC.cfgr().modify(|w| {
|
#[cfg(not(any(stm32u5, stm32wba)))]
|
||||||
|
let r = RCC.cfgr();
|
||||||
|
#[cfg(any(stm32u5, stm32wba))]
|
||||||
|
let r = RCC.cfgr1();
|
||||||
|
|
||||||
|
r.modify(|w| {
|
||||||
w.$set_source(source);
|
w.$set_source(source);
|
||||||
|
#[cfg(not(stm32f1))]
|
||||||
w.$set_prescaler(prescaler);
|
w.$set_prescaler(prescaler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -36,8 +47,16 @@ macro_rules! impl_peri {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_peri!(MCO1, Mco1Source, set_mco1, set_mco1pre);
|
#[cfg(any(rcc_c0, rcc_g0))]
|
||||||
impl_peri!(MCO2, Mco2Source, set_mco2, set_mco2pre);
|
#[allow(unused_imports)]
|
||||||
|
use self::{McoSource as Mco1Source, McoSource as Mco2Source};
|
||||||
|
|
||||||
|
#[cfg(mco)]
|
||||||
|
impl_peri!(MCO, McoSource, set_mcosel, set_mcopre);
|
||||||
|
#[cfg(mco1)]
|
||||||
|
impl_peri!(MCO1, Mco1Source, set_mco1sel, set_mco1pre);
|
||||||
|
#[cfg(mco2)]
|
||||||
|
impl_peri!(MCO2, Mco2Source, set_mco2sel, set_mco2pre);
|
||||||
|
|
||||||
pub struct Mco<'d, T: McoInstance> {
|
pub struct Mco<'d, T: McoInstance> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
|
@ -45,23 +64,20 @@ pub struct Mco<'d, T: McoInstance> {
|
||||||
|
|
||||||
impl<'d, T: McoInstance> Mco<'d, T> {
|
impl<'d, T: McoInstance> Mco<'d, T> {
|
||||||
/// Create a new MCO instance.
|
/// Create a new MCO instance.
|
||||||
///
|
|
||||||
/// `prescaler` must be between 1 and 15.
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
_peri: impl Peripheral<P = T> + 'd,
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
pin: impl Peripheral<P = impl McoPin<T>> + 'd,
|
pin: impl Peripheral<P = impl McoPin<T>> + 'd,
|
||||||
source: T::Source,
|
source: T::Source,
|
||||||
prescaler: u8,
|
#[cfg(not(stm32f1))] prescaler: McoPrescaler,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
|
|
||||||
assert!(
|
|
||||||
1 <= prescaler && prescaler <= 15,
|
|
||||||
"Mco prescaler must be between 1 and 15. Refer to the reference manual for more information."
|
|
||||||
);
|
|
||||||
|
|
||||||
critical_section::with(|_| unsafe {
|
critical_section::with(|_| unsafe {
|
||||||
T::apply_clock_settings(source, prescaler);
|
T::apply_clock_settings(
|
||||||
|
source,
|
||||||
|
#[cfg(not(stm32f1))]
|
||||||
|
prescaler,
|
||||||
|
);
|
||||||
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
|
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
|
||||||
pin.set_speed(Speed::VeryHigh);
|
pin.set_speed(Speed::VeryHigh);
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,9 +7,7 @@ use crate::time::Hertz;
|
||||||
|
|
||||||
pub(crate) mod bd;
|
pub(crate) mod bd;
|
||||||
mod bus;
|
mod bus;
|
||||||
#[cfg(any(stm32h5, stm32h7))]
|
|
||||||
mod mco;
|
mod mco;
|
||||||
#[cfg(any(stm32h5, stm32h7))]
|
|
||||||
pub use mco::*;
|
pub use mco::*;
|
||||||
|
|
||||||
#[cfg_attr(rcc_f0, path = "f0.rs")]
|
#[cfg_attr(rcc_f0, path = "f0.rs")]
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoClock};
|
use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoPrescaler};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::Hsi, McoClock::DIV1);
|
let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV1);
|
||||||
let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::Pll, McoClock::DIV4);
|
let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::PLL, McoPrescaler::DIV4);
|
||||||
let mut led = Output::new(p.PB7, Level::High, Speed::Low);
|
let mut led = Output::new(p.PB7, Level::High, Speed::Low);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use embassy_executor::Spawner;
|
||||||
use embassy_stm32::dcmi::{self, *};
|
use embassy_stm32::dcmi::{self, *};
|
||||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
use embassy_stm32::i2c::I2c;
|
use embassy_stm32::i2c::I2c;
|
||||||
use embassy_stm32::rcc::{Mco, Mco1Source};
|
use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler};
|
||||||
use embassy_stm32::time::khz;
|
use embassy_stm32::time::khz;
|
||||||
use embassy_stm32::{bind_interrupts, i2c, peripherals, Config};
|
use embassy_stm32::{bind_interrupts, i2c, peripherals, Config};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
|
@ -49,7 +49,7 @@ async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
defmt::info!("Hello World!");
|
defmt::info!("Hello World!");
|
||||||
let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, 3);
|
let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV3);
|
||||||
|
|
||||||
let mut led = Output::new(p.PE3, Level::High, Speed::Low);
|
let mut led = Output::new(p.PE3, Level::High, Speed::Low);
|
||||||
let cam_i2c = I2c::new(
|
let cam_i2c = I2c::new(
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
use embassy_stm32::rcc::{Mco, Mco1Source};
|
use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) {
|
||||||
|
|
||||||
let mut led = Output::new(p.PB14, Level::High, Speed::Low);
|
let mut led = Output::new(p.PB14, Level::High, Speed::Low);
|
||||||
|
|
||||||
let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, 8);
|
let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV8);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
info!("high");
|
info!("high");
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
use embassy_stm32::rcc::{Mco, Mco1Source, McoClock};
|
use embassy_stm32::rcc::{Mco, McoPrescaler, McoSource};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let _mco = Mco::new(p.MCO, p.PA8, Mco1Source::Hsi16, McoClock::DIV1);
|
let _mco = Mco::new(p.MCO, p.PA8, McoSource::HSI16, McoPrescaler::DIV1);
|
||||||
|
|
||||||
let mut led = Output::new(p.PB14, Level::High, Speed::Low);
|
let mut led = Output::new(p.PB14, Level::High, Speed::Low);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue