Expand description
§Internal, ultra low power, 32 kHz oscillator
§Overview
The osculp32k module provides access to the 32 kHz ultra low power
internal oscillator (OSCULP32K) within the OSC32KCTRL peripheral.
The OSCULP32K clock is unlike most other clocks. First, it is an internal
clock that is always enabled and can’t be disabled. And second, it has two
separate outputs, one at 32 kHz and another divided down to 1 kHz. Moreover,
none, either or both of these outputs can be enabled at any given time.
We can see, then, that the OSCULP32K peripheral forms its own, miniature
clock tree. There is a 1:N producer clock that is always enabled; and there
are two possible consumer clocks that can be independently and optionally
enabled. In fact, this structure is illustrated by the OSCULP32K
register, which has no regular ENABLE bit and two different enable bits
for clock output, EN32K and EN1K.
To represent this structure in the type system, we divide the OSCULP32K
peripheral into these three clocks. Users get access to the 1:N
EnabledOscUlp32kBase clock Source at power-on reset, which can be
consumed by both the OscUlp32k and OscUlp1k clocks. Note that
OscUlp32k and OscUlp1k are themselves 1:N clocks as well.
§Write lock
Rhe OSCULP32K register has a dedicated write lock bit that will freeze its
configuration until the next power-on reset. We implement this by simply
dropping the OscUlp32kBase clock, which prevents any further access to
the OSCULP32K register.
§Example
Creating and configuring the OSCULP32K clocks proceeds according to the
principles outlined in the clock module documentation. It is best shown
with an example.
Let’s start by using clock_system_at_reset to access the HAL clocking
structs.
use atsamd_hal::{
clock::v2::{
clock_system_at_reset,
osculp32k::{OscUlp1k, OscUlp32k},
},
pac::Peripherals,
};
let mut pac = Peripherals::take().unwrap();
let (buses, clocks, tokens) = clock_system_at_reset(
pac.oscctrl,
pac.osc32kctrl,
pac.gclk,
pac.mclk,
&mut pac.nvmctrl,
);Next, we can extract the EnabledOscUlp32kBase clock from the Clocks
struct and use it to enable the OscUlp1k and OscUlp32k clocks.
let base = clocks.osculp32k_base;
let (osculp1k, base) = OscUlp1k::enable(tokens.osculp32k.osculp1k, base);
let (osculp32k, base) = OscUlp32k::enable(tokens.osculp32k.osculp32k, base);We can then override the calibration value read from flash at start up.
base.set_calibration(128);And finally, we can set the write lock bit to freeze the configuation until
the next power-on reset. Doing so also drops the EnabledOscUlp32kBase
clock.
base.write_lock();The complete example is shown below.
use atsamd_hal::{
clock::v2::{
clock_system_at_reset,
osculp32k::{OscUlp1k, OscUlp32k},
},
pac::Peripherals,
};
let mut pac = Peripherals::take().unwrap();
let (buses, clocks, tokens) = clock_system_at_reset(
pac.oscctrl,
pac.osc32kctrl,
pac.gclk,
pac.mclk,
&mut pac.nvmctrl,
);
let base = clocks.osculp32k_base;
let (osculp1k, base) = OscUlp1k::enable(tokens.osculp32k.osculp1k, base);
let (osculp32k, mut base) = OscUlp32k::enable(tokens.osculp32k.osculp32k, base);
base.set_calibration(128);
base.write_lock();Structs§
- OscUlp1k
- Clock representing the 1 kHz output of the
OscUlp32kBaseclock - OscUlp1k
Token - Singleton token that can be exchanged for
OscUlp1k - OscUlp32k
- Clock representing the 32 kHz output of the
OscUlp32kBaseclock - OscUlp32k
Base - OSC3ULP2K base clock, which feeds the
OscUlp1kandOscUlp32kclocks - OscUlp32k
Token - Singleton token that can be exchanged for
OscUlp32k - OscUlp32k
Tokens - Set of tokens representing the disabled OSCULP32K clocks power-on reset
Enums§
- OscUlp1k
Id - Type representing the identity of the
OscUlp1kclock - OscUlp32k
Id - Type representing the identity of the
OscUlp32kclock
Type Aliases§
- Enabled
OscUlp1k - The
EnabledOscUlp1kclock - Enabled
OscUlp32k - The
EnabledOscUlp32kclock - Enabled
OscUlp32k Base - The
EnabledOscUlp32kBaseclock