1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! Facts shared by the Clock Manager's peripheral clock generators.
//!
//! `CM_PWM` and `CM_PCM` are two instances of the same generator — they even
//! share a register block in the PAC — and [`crate::pwm`] and [`crate::pcm`]
//! program them identically: `PLLD_per` as the source, integer division only,
//! kill-then-reconfigure. What differs is which peripheral consumes the
//! result.
//!
//! The divisor limit and the arithmetic around it live here rather than being
//! restated in each driver, because a hardware fact copied into two places is
//! a hardware fact that can be right in one of them.
/// The rate of `PLLD_per`, the source both generators are configured to use.
///
/// Nominal rather than measured: the figure is commonly cited but this crate
/// has not independently confirmed it, and because it comes from a PLL there
/// is no crystal to derive it from. Every rate computed from it inherits that
/// caveat — see [`crate::pwm`]'s "Clock" section.
pub const SOURCE_HZ: u32 = 500_000_000;
/// The smallest usable integer divisor.
///
/// Zero is not division by one; it is not a meaningful setting for the
/// generator at all, so [`clamp_divisor`] lifts it to this.
pub const MIN_DIVISOR: u16 = 1;
/// The largest integer divisor a generator can hold — **`DIVI` is 12 bits**.
///
/// This is the interesting one, because nothing in the hardware or the PAC
/// complains about exceeding it. The PAC's field writer *masks* the value it
/// is given, so a divisor of 12500 is programmed as `12500 & 0xFFF` = 212 and
/// the clock comes out 59 times too fast, with every register reading back
/// exactly as written. That failure is invisible from software and presents
/// only as a peripheral running at an inexplicable rate.
///
/// Hence [`clamp_divisor`], which every caller here goes through: a clamped
/// divisor is still not what was asked for, but it is off by a bounded factor
/// and in the right direction, which is the difference between a wrong number
/// and a mystery.
pub const MAX_DIVISOR: u16 = 4095;
/// The slowest clock a generator can produce, at [`MAX_DIVISOR`].
///
/// Worth knowing before designing around a target rate: anything slower than
/// this is simply not reachable through the integer divider, and asking for
/// it yields this instead.
pub const MIN_CLOCK_HZ: u32 = SOURCE_HZ / MAX_DIVISOR as u32;
/// `divisor` brought into the range the hardware can actually hold.
pub const
/// The rate a generator runs at once programmed with `divisor`.
///
/// Applies [`clamp_divisor`] first, so this reports what the hardware will
/// *do* rather than what the caller asked for — which is the point of it
/// existing.
pub const
/// The divisor giving the closest rate at or above `target_hz`, clamped to
/// what the hardware can hold.
///
/// A zero target yields [`MAX_DIVISOR`] — the slowest clock available —
/// rather than dividing by zero.
pub const