#[cfg_attr(ra2a1, path = "clock/ra2a1.rs")]
#[cfg_attr(ra4m1, path = "clock/ra4m1.rs")]
#[cfg_attr(ra4l1, path = "clock/ra4l1.rs")]
#[cfg_attr(ra6m5, path = "clock/ra6m5.rs")]
#[cfg_attr(ra8m1, path = "clock/ra8m1.rs")]
mod _clock;
pub(crate) use _clock::init;
use embassy_sync::once_lock::OnceLock;
use fugit::{HertzU32, KilohertzU32, MegahertzU32};
use crate::pac;
#[cfg(sciclk)]
use _clock::SciClockSource;
#[cfg(slcdc)]
use _clock::SlcdcClockSource;
#[cfg(spiclk)]
use _clock::SpiClockSource;
#[cfg(usbclk)]
use _clock::UsbClockSource;
static CLOCK_STATUS: OnceLock<ClockStatus> = OnceLock::new();
const _1MHZ: HertzU32 = MegahertzU32::from_raw(1).convert();
pub struct ClockStatus {
pub master: HertzU32,
pub mosc: Option<HertzU32>,
pub sosc: bool,
pub hoco: HertzU32,
#[cfg(all(pll, not(ra8m1)))]
pub pll: Option<HertzU32>,
#[cfg(all(pll, ra8m1))]
pub pll: Option<(HertzU32, HertzU32, HertzU32)>,
#[cfg(all(pll2, not(ra8m1)))]
pub pll2: Option<HertzU32>,
#[cfg(all(pll2, ra8m1))]
pub pll2: Option<(HertzU32, HertzU32, HertzU32)>,
#[cfg(bclk)]
pub bus_clock: HertzU32,
pub system: HertzU32,
pub flash: HertzU32,
#[cfg(pclka)]
pub peripheral_a: HertzU32,
#[cfg(pclkb)]
pub peripheral_b: HertzU32,
#[cfg(pclkc)]
pub peripheral_c: HertzU32,
#[cfg(pclkd)]
pub peripheral_d: HertzU32,
#[cfg(pclke)]
pub peripheral_e: HertzU32,
#[cfg(usbclk)]
pub usb: Option<HertzU32>,
#[cfg(sciclk)]
pub sci: Option<HertzU32>,
#[cfg(spiclk)]
pub spi: Option<HertzU32>,
#[cfg(slcdc)]
pub slcdc: Option<HertzU32>,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum SystemClockSource {
Mosc,
Sosc,
Hoco,
Moco,
#[cfg(not(ra8m1))]
Loco,
#[cfg(all(not(ra8m1), pll))]
Pll,
#[cfg(ra8m1)]
Pll1P,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone)]
pub struct ClockConfig {
system: SystemClockSource,
hoco: HocoFrequency,
mosc: Option<HertzU32>,
sosc: bool,
#[cfg(pll)]
pll: Option<PllConfig>,
#[cfg(pll2)]
pll2: Option<PllConfig>,
#[cfg(usbclk)]
usb: Option<UsbClockSource>,
#[cfg(sciclk)]
sci: Option<(SciClockSource, HertzU32)>,
#[cfg(spiclk)]
spi: Option<(SpiClockSource, HertzU32)>,
#[cfg(slcdc)]
slcdc: Option<SlcdcClockSource>,
}
cfg_select! {
not(ra8m1) => {
#[cfg(all(pll, not(ra4m1)))]
pub use _clock::PllInDiv;
#[cfg(ra4m1)]
pub use _clock::PllOutDiv;
#[cfg(any(pll, pll2))]
pub use _clock::{PllInput, PllOutMul};
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg(any(pll, pll2))]
#[derive(Debug, Clone)]
pub struct PllConfig {
input: PllInput,
#[cfg(not(ra4m1))]
div: PllInDiv,
#[cfg(ra4m1)]
div: PllOutDiv,
mul: PllOutMul,
}
},
ra8m1 => {
pub use _clock::PllInDiv;
pub use _clock::{PllInput, PllPDiv, PllQDiv, PllRDiv, PllOutMul};
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone)]
pub struct PllConfig {
input: PllInput,
div: PllInDiv,
mul: PllOutMul,
div_p: PllPDiv,
div_q: PllQDiv,
div_r: PllRDiv,
}
}
}
pub fn clock_status() -> &'static ClockStatus {
CLOCK_STATUS
.try_get()
.expect("CLOCK_STATUS not initialized")
}
#[cfg(feature = "defmt")]
fn print_frequency(fmt: defmt::Formatter, label: &str, frequency: HertzU32) {
if frequency < _1MHZ {
let pll: KilohertzU32 = frequency.convert();
defmt::write!(fmt, ", {}: {}", label, pll);
} else {
let pll: MegahertzU32 = frequency.convert();
defmt::write!(fmt, ", {}: {}", label, pll);
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for ClockStatus {
fn format(&self, fmt: defmt::Formatter) {
let system = pac::SYSTEM;
let cksel = system.sckscr().read().cksel();
let &ClockStatus {
master: _,
system,
flash,
#[cfg(pclka)]
peripheral_a,
#[cfg(pclkb)]
peripheral_b,
#[cfg(pclkc)]
peripheral_c,
#[cfg(pclkd)]
peripheral_d,
#[cfg(pclke)]
peripheral_e,
hoco,
#[cfg(pll)]
pll,
#[cfg(pll2)]
pll2,
#[cfg(bclk)]
bus_clock,
sosc,
mosc,
#[cfg(usbclk)]
usb,
#[cfg(sciclk)]
sci,
#[cfg(spiclk)]
spi,
#[cfg(slcdc)]
slcdc,
} = clock_status();
defmt::write!(fmt, "SYSTEM: ");
if hoco < _1MHZ {
let hoco: KilohertzU32 = hoco.convert();
defmt::write!(fmt, "HOCO: {}", hoco);
} else {
let hoco: MegahertzU32 = hoco.convert();
defmt::write!(fmt, "HOCO: {}", hoco);
}
defmt::write!(fmt, ", SOSC: {}", sosc);
match mosc {
Some(mosc) => {
print_frequency(fmt, "MOSC", mosc.convert());
}
None => {
defmt::write!(fmt, ", MOSC: None");
}
}
#[cfg(pll)]
cfg_select! {
not(ra8m1) => {
match pll {
Some(pll) => print_frequency(fmt, "PLL", pll),
None => defmt::write!(fmt, ", PLL: OFF"),
}
}
ra8m1 => {
match pll {
Some((pll_p, pll_q, pll_r)) => {
print_frequency(fmt, "PLL.P", pll_p);
print_frequency(fmt, "PLL.Q", pll_q);
print_frequency(fmt, "PLL.R", pll_r);
}
None => defmt::write!(fmt, ", PLL: OFF"),
}
}
}
#[cfg(pll2)]
cfg_select! {
not(ra8m1) => {
match pll2 {
Some(pll) => print_frequency(fmt, "PLL2", pll),
None => defmt::write!(fmt, ", PLL2: OFF"),
}
}
ra8m1 => {
match pll2 {
Some((pll_p, pll_q, pll_r)) => {
print_frequency(fmt, "PLL2.P", pll_p);
print_frequency(fmt, "PLL2.Q", pll_q);
print_frequency(fmt, "PLL2.R", pll_r);
}
None => defmt::write!(fmt, ", PLL2: OFF"),
}
}
}
defmt::write!(fmt, ", ROOT: {}", cksel);
print_frequency(fmt, "ICLK", system.convert());
print_frequency(fmt, "FCLK", flash.convert());
#[cfg(bclk)]
print_frequency(fmt, "BCLK", bus_clock.convert());
#[cfg(pclka)]
print_frequency(fmt, "PCLKA", peripheral_a.convert());
#[cfg(pclkb)]
print_frequency(fmt, "PCLKB", peripheral_b.convert());
#[cfg(pclkc)]
print_frequency(fmt, "PCLKC", peripheral_c.convert());
#[cfg(pclkd)]
print_frequency(fmt, "PCLKD", peripheral_d.convert());
#[cfg(pclke)]
print_frequency(fmt, "PCLKE", peripheral_e.convert());
#[cfg(usbclk)]
if let Some(usb) = usb {
print_frequency(fmt, "USB", usb.convert());
} else {
defmt::write!(fmt, ", USB: OFF");
}
#[cfg(sciclk)]
if let Some(sci) = sci {
print_frequency(fmt, "SCI", sci.convert());
} else {
defmt::write!(fmt, ", SCI: OFF");
}
#[cfg(spiclk)]
if let Some(spi) = spi {
print_frequency(fmt, "SPI", spi.convert());
} else {
defmt::write!(fmt, ", SPI: OFF");
}
}
}
include!(concat!(env!("OUT_DIR"), "/hoco.rs"));