Skip to content

Commit

Permalink
clocks: Fix comments & rename approximate_frequency
Browse files Browse the repository at this point in the history
  • Loading branch information
ithinuel committed Sep 4, 2023
1 parent 6cbfae2 commit 3dfcd02
Showing 1 changed file with 35 additions and 5 deletions.
40 changes: 35 additions & 5 deletions rp2040-hal/src/clocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,30 @@ pub use clock_sources::{GPin0, GPin1};

use clock_sources::{PllSys, PllUsb, Rosc, Xosc};

/// Frequency counter accuracy
///
/// See: https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#table-fc-test-interval
#[repr(u8)]
#[allow(missing_docs)]
pub enum FCAccuracy {
_2048kHz = 0,
_1024kHz,
_512kHz,
_256kHz,
_128kHz,
_64kHz,
_32kHz,
_16kHz,
_8kHz,
_4kHz,
_2kHz,
_1kHz,
_500Hz,
_250Hz,
_125Hz,
_62_5Hz,
}

#[derive(Copy, Clone)]
/// Provides refs to the CLOCKS block.
struct ShareableClocks {
Expand Down Expand Up @@ -305,8 +329,8 @@ impl ClocksManager {
.configure_clock(&self.system_clock, self.system_clock.freq())
}

/// Approximates the frequency of the given clock source.
pub fn approximate_frequency<C: ClockSource>(&mut self, _trg_clk: C) -> HertzU32 {
/// Measure the frequency of the given clock source by approximation.
pub fn measure_frequency<C: ClockSource>(&mut self, _trg_clk: C, accuracy: FCAccuracy) -> HertzU32 {
// Wait for the frequency counter to be ready
while self.clocks.fc0_status.read().running().bit_is_set() {
core::hint::spin_loop()
Expand All @@ -318,10 +342,14 @@ impl ClocksManager {
.bits(self.reference_clock.get_freq().to_kHz())
});

// Corresponds to a 1ms test time, which seems to give good enough accuracy
// > The test interval is 0.98us * 2**interval, but let's call it 1us * 2**interval.
// > The default gives a test interval of 250us
//
// https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#reg-clocks-FC0_INTERVAL
// https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#table-fc-test-interval
self.clocks
.fc0_interval
.write(|w| unsafe { w.fc0_interval().bits(10) });
.write(|w| unsafe { w.fc0_interval().bits(accuracy as u8) });

// We don't really care about the min/max, so these are just set to min/max values.
self.clocks
Expand All @@ -331,7 +359,7 @@ impl ClocksManager {
.fc0_max_khz
.write(|w| unsafe { w.fc0_max_khz().bits(0xffffffff) });

// To measure rosc directly we use the value 0x03.
// Select which clock to measure.
self.clocks
.fc0_src
.write(|w| w.fc0_src().variant(C::FCOUNTER_SRC));
Expand All @@ -341,6 +369,8 @@ impl ClocksManager {
core::hint::spin_loop()
}

// TODO: the result may not be valid (eg clock stopped during measurement). We may want to
// return a Result instead. Is it worth the hassle though?
let speed_hz = self.clocks.fc0_result.read().khz().bits() * 1000;
speed_hz.Hz()
}
Expand Down

0 comments on commit 3dfcd02

Please sign in to comment.