rp-hal-boards/rp2040-hal/src/clocks/mod.rs

437 lines
13 KiB
Rust
Raw Normal View History

2021-05-01 23:18:37 +02:00
//! Clocks (CLOCKS)
// See [Chapter 2 Section 15](https://datasheets.raspberrypi.org/rp2040/rp2040_datasheet.pdf) for more details
use crate::pac::*;
#[macro_use]
mod macros;
#[derive(Copy, Clone)]
/// Provides refs to the CLOCKS block.
pub struct ShareableClocks {
2021-05-01 23:19:08 +02:00
_internal: (),
2021-05-01 23:18:37 +02:00
}
impl ShareableClocks {
fn new(_clocks: &mut CLOCKS) -> Self {
2021-05-01 23:19:08 +02:00
ShareableClocks { _internal: () }
2021-05-01 23:18:37 +02:00
}
unsafe fn get(&self) -> &clocks::RegisterBlock {
&*CLOCKS::ptr()
}
}
/// Abstraction layer providing Clock Management.
pub struct ClocksManager {
2021-05-01 23:19:08 +02:00
clocks: CLOCKS,
shared_clocks: ShareableClocks,
2021-05-01 23:18:37 +02:00
}
impl ClocksManager {
/// Exchanges CLOCKS block against Self.
pub fn new(mut clocks_block: CLOCKS) -> Self {
let shared_clocks = ShareableClocks::new(&mut clocks_block);
ClocksManager {
clocks: clocks_block,
2021-06-26 23:45:28 -05:00
shared_clocks,
2021-05-01 23:18:37 +02:00
}
}
/// Releases the CLOCKS block
pub fn free(self) -> CLOCKS {
self.clocks
}
/// Getter for the GPIO Output 0 Clock.
pub fn gpio_output0_clock(&self) -> GpioOutput0Clock {
GpioOutput0Clock {
shared_dev: self.shared_clocks,
}
}
/// Getter for the GPIO Output 1 Clock.
pub fn gpio_output1_clock(&self) -> GpioOutput1Clock {
GpioOutput1Clock {
shared_dev: self.shared_clocks,
}
}
/// Getter for the GPIO Output 2 Clock.
pub fn gpio_output2_clock(&self) -> GpioOutput2Clock {
GpioOutput2Clock {
shared_dev: self.shared_clocks,
}
}
/// Getter for the GPIO Output 3 Clock.
pub fn gpio_output3_clock(&self) -> GpioOutput3Clock {
GpioOutput3Clock {
shared_dev: self.shared_clocks,
}
}
2021-05-01 23:18:37 +02:00
/// Getter for the Reference Clock.
pub fn ref_clock(&self) -> ReferenceClock {
ReferenceClock {
2021-06-26 23:45:28 -05:00
shared_dev: self.shared_clocks,
2021-05-01 23:18:37 +02:00
}
}
/// Getter for the System Clock
pub fn sys_clock(&self) -> SystemClock {
SystemClock {
2021-06-26 23:45:28 -05:00
shared_dev: self.shared_clocks,
2021-05-01 23:18:37 +02:00
}
}
/// Getter for the PeripheralClock
pub fn peripheral_clock(&self) -> PeripheralClock {
PeripheralClock {
2021-06-26 23:45:28 -05:00
shared_dev: self.shared_clocks,
2021-05-01 23:18:37 +02:00
}
}
/// Getter for the Usb Clock
pub fn usb_clock(&self) -> UsbClock {
UsbClock {
shared_dev: self.shared_clocks,
}
}
/// Getter for the Adc Clock
pub fn adc_clock(&self) -> AdcClock {
AdcClock {
shared_dev: self.shared_clocks,
}
}
/// Getter for the Rtc Clock
pub fn rtc_clock(&self) -> RtcClock {
RtcClock {
shared_dev: self.shared_clocks,
}
}
2021-05-01 23:18:37 +02:00
}
/// For clocks with an integer divider.
pub trait IntegerDivision {
/// Set integer divider value.
fn set_int_div(&mut self, div: usize);
}
/// For clocks with a fraction divider.
pub trait FractionDivision {
/// Set fraction divider value.
fn set_frac_div(&mut self, div: usize);
}
/// For clocks that can have XOSC as source.
pub trait XOSCClockSource {
/// Set XOSC as a source.
fn set_xosc_src(&mut self);
}
/// For clocks that can have ROSC as source.
pub trait ROSCClockSource {
/// set ROSC as a source.
fn set_rosc_src(&mut self);
}
/// For clocks that can have ... itself (?) as a source (is that the "glitchless mux" ?)
pub trait SelfAuxClockSource {
/// Set ...
fn set_self_aux_src(&mut self);
}
/// For clocks that can have the Reference Clock as source.
pub trait ClockREFClockSource {
/// Set Reference Clock as
fn set_clkref_src(&mut self);
}
/// For clocks that can have the System Clock as an auxilliary source.
pub trait ClockSYSClockAuxSource {
/// Set System Clock as source.
fn set_clksys_auxsrc(&mut self);
}
/// For clocks that can have the USB Clock as an auxilliary source.
pub trait ClockUSBClockAuxSource {
/// Set USB Clock as source.
fn set_clkusb_auxsrc(&mut self);
}
/// For clocks that can have the ADC Clock as an auxilliary source.
pub trait ClockADCClockAuxSource {
/// Set ADC Clock as source.
fn set_clkadc_auxsrc(&mut self);
}
/// For clocks that can have the RTC Clock as an auxilliary source.
pub trait ClockRTCClockAuxSource {
/// Set RTC Clock as source.
fn set_clkrtc_auxsrc(&mut self);
}
/// For clocks that can have the Reference Clock as an auxilliary source.
pub trait ClockRefClockAuxSource {
/// Set Reference Clock as source.
fn set_clkref_auxsrc(&mut self);
}
2021-05-01 23:18:37 +02:00
/// For clocks that can have XOSC as an auxilliary source.
pub trait XOSCClockAuxSource {
/// Set XOSC as auxilliary source.
fn set_xosc_auxsrc(&mut self);
}
/// For clocks that can have ROSC as an auxilliary source.
pub trait ROSCClockAuxSource {
/// Set ROSC as auxilliary source.
fn set_rosc_auxsrc(&mut self);
}
/// For clocks that can have ROSC_PH as an auxilliary source.
pub trait ROSCPHClockAuxSource {
/// Set ROSC_PH as auxilliary source.
fn set_rosc_ph_auxsrc(&mut self);
}
/// For clocks that can have PLL_USB as an auxilliary source.
pub trait PLLUSBClockAuxSource {
/// Set PLL_USB as auxilliary source.
fn set_pll_usb_auxsrc(&mut self);
}
/// For clocks that can have PLL_SYS as an auxilliary source.
pub trait PLLSYSClockAuxSource {
/// Set PLL_SYS as auxilliary source.
fn set_pll_sys_auxsrc(&mut self);
}
/// For clocks that can have gpin0 as an auxilliary source.
pub trait Gpin0ClockAuxSource {
/// Set clock to be received from gpin0 (auxilliary)
fn set_gpin0_auxsrc(&mut self);
}
/// For clocks that can have gpin1 as an auxilliary source.
pub trait Gpin1ClockAuxSource {
/// Set clock to be received from gpin1
fn set_gpin1_auxsrc(&mut self);
}
/// For clocks having a generator.
pub trait ClockGenerator {
/// Enables the clock.
fn enable(&mut self);
/// Disables the clock.
fn disable(&mut self);
/// Kills the clock.
fn kill(&mut self);
}
/// GPIO Output 0 Clock
pub struct GpioOutput0Clock {
shared_dev: ShareableClocks,
}
clock_generator!(GpioOutput0Clock, clk_gpout0_ctrl);
// Clock aux sources
pll_sys_auxsource!(GpioOutput0Clock, clk_gpout0_ctrl);
gpin0_auxsource!(GpioOutput0Clock, clk_gpout0_ctrl);
gpin1_auxsource!(GpioOutput0Clock, clk_gpout0_ctrl);
pll_usb_auxsource!(GpioOutput0Clock, clk_gpout0_ctrl);
rosc_auxsource!(GpioOutput0Clock, clk_gpout0_ctrl);
xosc_auxsource!(GpioOutput0Clock, clk_gpout0_ctrl);
clocksys_auxsource!(GpioOutput0Clock, clk_gpout0_ctrl);
clockusb_auxsource!(GpioOutput0Clock, clk_gpout0_ctrl);
clockadc_auxsource!(GpioOutput0Clock, clk_gpout0_ctrl);
clockrtc_auxsource!(GpioOutput0Clock, clk_gpout0_ctrl);
clockref_auxsource!(GpioOutput0Clock, clk_gpout0_ctrl);
int_division!(GpioOutput0Clock, clk_gpout0_div, u32);
frac_division!(GpioOutput0Clock, clk_gpout0_div, u8);
/// GPIO Output 1 Clock
pub struct GpioOutput1Clock {
shared_dev: ShareableClocks,
}
clock_generator!(GpioOutput1Clock, clk_gpout1_ctrl);
// Clock aux sources
pll_sys_auxsource!(GpioOutput1Clock, clk_gpout1_ctrl);
gpin0_auxsource!(GpioOutput1Clock, clk_gpout1_ctrl);
gpin1_auxsource!(GpioOutput1Clock, clk_gpout1_ctrl);
pll_usb_auxsource!(GpioOutput1Clock, clk_gpout1_ctrl);
rosc_auxsource!(GpioOutput1Clock, clk_gpout1_ctrl);
xosc_auxsource!(GpioOutput1Clock, clk_gpout1_ctrl);
clocksys_auxsource!(GpioOutput1Clock, clk_gpout1_ctrl);
clockusb_auxsource!(GpioOutput1Clock, clk_gpout1_ctrl);
clockadc_auxsource!(GpioOutput1Clock, clk_gpout1_ctrl);
clockrtc_auxsource!(GpioOutput1Clock, clk_gpout1_ctrl);
clockref_auxsource!(GpioOutput1Clock, clk_gpout1_ctrl);
int_division!(GpioOutput1Clock, clk_gpout1_div, u32);
frac_division!(GpioOutput1Clock, clk_gpout1_div, u8);
/// GPIO Output 2 Clock
pub struct GpioOutput2Clock {
shared_dev: ShareableClocks,
}
clock_generator!(GpioOutput2Clock, clk_gpout2_ctrl);
// Clock aux sources
pll_sys_auxsource!(GpioOutput2Clock, clk_gpout2_ctrl);
gpin0_auxsource!(GpioOutput2Clock, clk_gpout2_ctrl);
gpin1_auxsource!(GpioOutput2Clock, clk_gpout2_ctrl);
pll_usb_auxsource!(GpioOutput2Clock, clk_gpout2_ctrl);
rosc_ph_auxsource!(GpioOutput2Clock, clk_gpout2_ctrl);
xosc_auxsource!(GpioOutput2Clock, clk_gpout2_ctrl);
clocksys_auxsource!(GpioOutput2Clock, clk_gpout2_ctrl);
clockusb_auxsource!(GpioOutput2Clock, clk_gpout2_ctrl);
clockadc_auxsource!(GpioOutput2Clock, clk_gpout2_ctrl);
clockrtc_auxsource!(GpioOutput2Clock, clk_gpout2_ctrl);
clockref_auxsource!(GpioOutput2Clock, clk_gpout2_ctrl);
int_division!(GpioOutput2Clock, clk_gpout2_div, u32);
frac_division!(GpioOutput2Clock, clk_gpout2_div, u8);
/// GPIO Output 3 Clock
pub struct GpioOutput3Clock {
shared_dev: ShareableClocks,
}
clock_generator!(GpioOutput3Clock, clk_gpout3_ctrl);
// Clock aux sources
pll_sys_auxsource!(GpioOutput3Clock, clk_gpout3_ctrl);
gpin0_auxsource!(GpioOutput3Clock, clk_gpout3_ctrl);
gpin1_auxsource!(GpioOutput3Clock, clk_gpout3_ctrl);
pll_usb_auxsource!(GpioOutput3Clock, clk_gpout3_ctrl);
rosc_ph_auxsource!(GpioOutput3Clock, clk_gpout3_ctrl);
xosc_auxsource!(GpioOutput3Clock, clk_gpout3_ctrl);
clocksys_auxsource!(GpioOutput3Clock, clk_gpout3_ctrl);
clockusb_auxsource!(GpioOutput3Clock, clk_gpout3_ctrl);
clockadc_auxsource!(GpioOutput3Clock, clk_gpout3_ctrl);
clockrtc_auxsource!(GpioOutput3Clock, clk_gpout3_ctrl);
clockref_auxsource!(GpioOutput3Clock, clk_gpout3_ctrl);
int_division!(GpioOutput3Clock, clk_gpout3_div, u32);
frac_division!(GpioOutput3Clock, clk_gpout3_div, u8);
2021-05-01 23:18:37 +02:00
/// Reference Clock
pub struct ReferenceClock {
shared_dev: ShareableClocks,
}
rosc_source!(ReferenceClock, clk_ref_ctrl);
selfaux_source!(ReferenceClock, clk_ref_ctrl, clksrc_clk_ref_aux);
xosc_source!(ReferenceClock, clk_ref_ctrl);
// Clock aux sources
pll_usb_auxsource!(ReferenceClock, clk_ref_ctrl);
2021-05-01 23:18:37 +02:00
gpin0_auxsource!(ReferenceClock, clk_ref_ctrl);
gpin1_auxsource!(ReferenceClock, clk_ref_ctrl);
2021-05-01 23:18:37 +02:00
int_division!(ReferenceClock, clk_ref_div, u8);
/// System Clock
pub struct SystemClock {
2021-05-01 23:19:08 +02:00
shared_dev: ShareableClocks,
2021-05-01 23:18:37 +02:00
}
impl SystemClock {
/// WIP - Helper function to reset source (blocking)
pub fn reset_source_await(&self) {
let shared_dev = unsafe { self.shared_dev.get() };
shared_dev.clk_sys_ctrl.write(|w| {
w.src().clear_bit();
w
});
self.await_select(0x1);
}
/// WIP - Helper function to select new source (blocking)
2021-05-01 23:19:08 +02:00
pub fn await_select(&self, clock: u8) {
2021-05-01 23:18:37 +02:00
let shared_dev = unsafe { self.shared_dev.get() };
while shared_dev.clk_sys_selected.read().bits() != clock as u32 {
cortex_m::asm::nop();
}
}
}
// Clock glitchless sources
2021-05-01 23:18:37 +02:00
clockref_source!(SystemClock, clk_sys_ctrl);
selfaux_source!(SystemClock, clk_sys_ctrl, clksrc_clk_sys_aux);
// Clock aux sources
2021-05-01 23:18:37 +02:00
pll_sys_auxsource!(SystemClock, clk_sys_ctrl);
pll_usb_auxsource!(SystemClock, clk_sys_ctrl);
2021-05-01 23:18:37 +02:00
rosc_auxsource!(SystemClock, clk_sys_ctrl);
xosc_auxsource!(SystemClock, clk_sys_ctrl);
gpin0_auxsource!(SystemClock, clk_sys_ctrl);
gpin1_auxsource!(SystemClock, clk_sys_ctrl);
2021-05-01 23:18:37 +02:00
int_division!(SystemClock, clk_sys_div, u32);
frac_division!(SystemClock, clk_sys_div, u8);
/// Peripheral Clock
pub struct PeripheralClock {
2021-05-01 23:19:08 +02:00
shared_dev: ShareableClocks,
2021-05-01 23:18:37 +02:00
}
clock_generator!(PeripheralClock, clk_peri_ctrl);
// Clock aux sources
clocksys_auxsource!(PeripheralClock, clk_peri_ctrl);
2021-05-01 23:18:37 +02:00
pll_sys_auxsource!(PeripheralClock, clk_peri_ctrl);
pll_usb_auxsource!(PeripheralClock, clk_peri_ctrl);
2021-05-01 23:18:37 +02:00
rosc_ph_auxsource!(PeripheralClock, clk_peri_ctrl);
xosc_auxsource!(PeripheralClock, clk_peri_ctrl);
gpin0_auxsource!(PeripheralClock, clk_peri_ctrl);
gpin1_auxsource!(PeripheralClock, clk_peri_ctrl);
/// USB Clock
pub struct UsbClock {
shared_dev: ShareableClocks,
}
clock_generator!(UsbClock, clk_usb_ctrl);
// Clock aux sources
pll_usb_auxsource!(UsbClock, clk_usb_ctrl);
pll_sys_auxsource!(UsbClock, clk_usb_ctrl);
rosc_ph_auxsource!(UsbClock, clk_usb_ctrl);
xosc_auxsource!(UsbClock, clk_usb_ctrl);
gpin0_auxsource!(UsbClock, clk_usb_ctrl);
gpin1_auxsource!(UsbClock, clk_usb_ctrl);
int_division!(UsbClock, clk_usb_div, u8);
/// Adc Clock
pub struct AdcClock {
shared_dev: ShareableClocks,
}
clock_generator!(AdcClock, clk_adc_ctrl);
// Clock aux sources
pll_usb_auxsource!(AdcClock, clk_adc_ctrl);
pll_sys_auxsource!(AdcClock, clk_adc_ctrl);
rosc_ph_auxsource!(AdcClock, clk_adc_ctrl);
xosc_auxsource!(AdcClock, clk_adc_ctrl);
gpin0_auxsource!(AdcClock, clk_adc_ctrl);
gpin1_auxsource!(AdcClock, clk_adc_ctrl);
int_division!(AdcClock, clk_adc_div, u8);
/// RTC Clock
pub struct RtcClock {
shared_dev: ShareableClocks,
}
clock_generator!(RtcClock, clk_rtc_ctrl);
// Clock aux sources
pll_usb_auxsource!(RtcClock, clk_rtc_ctrl);
pll_sys_auxsource!(RtcClock, clk_rtc_ctrl);
rosc_ph_auxsource!(RtcClock, clk_rtc_ctrl);
xosc_auxsource!(RtcClock, clk_rtc_ctrl);
gpin0_auxsource!(RtcClock, clk_rtc_ctrl);
gpin1_auxsource!(RtcClock, clk_rtc_ctrl);
int_division!(RtcClock, clk_rtc_div, u32);
frac_division!(RtcClock, clk_rtc_div, u8);