Skip to content

Commit fc6a348

Browse files
committed
clocks: Fix comments & rename approximate_frequency
1 parent 6cbfae2 commit fc6a348

File tree

1 file changed

+41
-6
lines changed

1 file changed

+41
-6
lines changed

rp2040-hal/src/clocks/mod.rs

+41-6
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,30 @@ pub use clock_sources::{GPin0, GPin1};
8484

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

87+
/// Frequency counter accuracy
88+
///
89+
/// See: https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#table-fc-test-interval
90+
#[repr(u8)]
91+
#[allow(missing_docs)]
92+
pub enum FCAccuracy {
93+
_2048kHz = 0,
94+
_1024kHz,
95+
_512kHz,
96+
_256kHz,
97+
_128kHz,
98+
_64kHz,
99+
_32kHz,
100+
_16kHz,
101+
_8kHz,
102+
_4kHz,
103+
_2kHz,
104+
_1kHz,
105+
_500Hz,
106+
_250Hz,
107+
_125Hz,
108+
_62_5Hz,
109+
}
110+
87111
#[derive(Copy, Clone)]
88112
/// Provides refs to the CLOCKS block.
89113
struct ShareableClocks {
@@ -305,8 +329,12 @@ impl ClocksManager {
305329
.configure_clock(&self.system_clock, self.system_clock.freq())
306330
}
307331

308-
/// Approximates the frequency of the given clock source.
309-
pub fn approximate_frequency<C: ClockSource>(&mut self, _trg_clk: C) -> HertzU32 {
332+
/// Measure the frequency of the given clock source by approximation.
333+
pub fn measure_frequency<C: ClockSource>(
334+
&mut self,
335+
_trg_clk: C,
336+
accuracy: FCAccuracy,
337+
) -> HertzU32 {
310338
// Wait for the frequency counter to be ready
311339
while self.clocks.fc0_status.read().running().bit_is_set() {
312340
core::hint::spin_loop()
@@ -318,10 +346,14 @@ impl ClocksManager {
318346
.bits(self.reference_clock.get_freq().to_kHz())
319347
});
320348

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

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

334-
// To measure rosc directly we use the value 0x03.
366+
// Select which clock to measure.
335367
self.clocks
336368
.fc0_src
337369
.write(|w| w.fc0_src().variant(C::FCOUNTER_SRC));
@@ -341,7 +373,10 @@ impl ClocksManager {
341373
core::hint::spin_loop()
342374
}
343375

344-
let speed_hz = self.clocks.fc0_result.read().khz().bits() * 1000;
376+
// TODO: the result may not be valid (eg clock stopped during measurement). We may want to
377+
// return a Result instead. Is it worth the hassle though?
378+
let result = self.clocks.fc0_result.read();
379+
let speed_hz = result.khz().bits() * 1000 + result.frac().bits();
345380
speed_hz.Hz()
346381
}
347382

0 commit comments

Comments
 (0)