atsamd_hal/peripherals/clock/d5x/v2/gclk.rs
1//! # Generic Clock Controllers
2//!
3//! ## Overview
4//!
5//! The generic clock controller is central to the clocking system in ATSAMD
6//! chips. It provides 12 generic clock generators to modify and distribute
7//! clocks to other peripherals. Within the clock tree, these clock generators
8//! act as the branch clocks, connecting internal or external root or branch
9//! clocks to other branch or leaf clocks.
10//!
11//! Each clock generator takes an input clock, optionally divides it, and
12//! produces an output clock. The input clock can be:
13//!
14//! - A GPIO input ([`Pin`])
15//! - An external crystal oscillator ([`Xosc`])
16//! - An external 32 kHz oscillator ([`Xosc32k`])
17//! - The ultra-low power 32 kHz oscillator ([`OscUlp32k`])
18//! - The 48 MHz DFLL ([`Dfll`])
19//! - A DPLL ([`Dpll`])
20//! - Generic clock generator #1 ([`Gclk1`])
21//!
22//! The output clock can be:
23//! - A peripheral channel clock ([`Pclk`])
24//! - A GPIO pin ([`GclkOut`])
25//!
26//! ## Example
27//!
28//! The configuration of a [`Gclk`] is best shown with an example. However, the
29//! example assumes you are already familiar with the basics of the `clock`
30//! module. See the [`clock` module documentation](super) for an overview.
31//!
32//! Suppose we start with the default clock tree after power-on reset.
33//!
34//! ```text
35//! DFLL (48 MHz)
36//! └── GCLK0 (48 MHz)
37//! └── Main clock (48 MHz)
38//! ```
39//!
40//! We would like to transform it to a clock tree like this:
41//!
42//! ```text
43//! DFLL (48 MHz)
44//! └── GCLK0 (48 MHz)
45//! └── Main clock (48 MHz)
46//!
47//! GCLK_IN1 (PB14, 24 MHz)
48//! └── GCLK1 (12 MHz)
49//! ├── SERCOM0
50//! └── GCLK2 (3 MHz)
51//! ├── SERCOM1
52//! └── GCLK_OUT2 (PA16, 3 MHz)
53//! ```
54//!
55//! Let's start by using [`clock_system_at_reset`] to access the HAL clocking
56//! structs. We will also need access to the [`gpio`] [`Pins`].
57//!
58//! ```no_run
59//! use atsamd_hal::{
60//! clock::v2::{
61//! clock_system_at_reset,
62//! gclk::{Gclk, GclkDiv8, GclkDiv16},
63//! pclk::Pclk,
64//! },
65//! gpio::Pins,
66//! pac::Peripherals,
67//! fugit::RateExtU32,
68//! };
69//! let mut pac = Peripherals::take().unwrap();
70//! let (mut buses, clocks, tokens) = clock_system_at_reset(
71//! pac.oscctrl,
72//! pac.osc32kctrl,
73//! pac.gclk,
74//! pac.mclk,
75//! &mut pac.nvmctrl,
76//! );
77//! let pins = Pins::new(pac.port);
78//! ```
79//!
80//! Next, we use [`Gclk::from_pin`] to create a [`Gclk`] from a [`GclkToken`],
81//! GPIO [`Pin`] and frequency, in [`Hertz`]. In this case, we create an
82//! instance of [`Gclk1`].
83//!
84//! At this point, notice that [`Gclk<G, I>`] takes two type parameters. `G` is
85//! a [`GclkId`] identifying which of the 12 generators this `Gclk` represents.
86//! [`Gclk1<I>`] is simply an alias for `Gclk<Gclk1Id, I>`. `I` is an
87//! [`Id` type](super#id-types) identifying the input clock, which must be a
88//! valid [`GclkSourceId`]. In this case, `I` is [`PB14`](gpio::PB14), which is
89//! a `GclkSourceId` for `Gclk1`, because it implements [`GclkIo`] with
90//! [`GclkIo::GclkId`]` = Gclk1Id`.
91//!
92//! ```no_run
93//! # use atsamd_hal::{
94//! # clock::v2::{
95//! # clock_system_at_reset,
96//! # gclk::{Gclk, GclkDiv8, GclkDiv16},
97//! # pclk::Pclk,
98//! # },
99//! # gpio::Pins,
100//! # pac::Peripherals,
101//! # fugit::RateExtU32,
102//! # };
103//! # let mut pac = Peripherals::take().unwrap();
104//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
105//! # pac.oscctrl,
106//! # pac.osc32kctrl,
107//! # pac.gclk,
108//! # pac.mclk,
109//! # &mut pac.nvmctrl,
110//! # );
111//! # let pins = Pins::new(pac.port);
112//! let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
113//! ```
114//!
115//! While we have created a [`Gclk`], we have not yet enabled it. But before
116//! doing so, we would like to set the divider to reduce the input frequency of
117//! 24 MHz to a 12 MHz output. We call `Gclk::div`, which uses a builder API, so
118//! that it can be chained with the call to `Gclk::enable`.
119//!
120//! ```no_run
121//! # use atsamd_hal::{
122//! # clock::v2::{
123//! # clock_system_at_reset,
124//! # gclk::{Gclk, GclkDiv8, GclkDiv16},
125//! # pclk::Pclk,
126//! # },
127//! # gpio::Pins,
128//! # pac::Peripherals,
129//! # fugit::RateExtU32,
130//! # };
131//! # let mut pac = Peripherals::take().unwrap();
132//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
133//! # pac.oscctrl,
134//! # pac.osc32kctrl,
135//! # pac.gclk,
136//! # pac.mclk,
137//! # &mut pac.nvmctrl,
138//! # );
139//! # let pins = Pins::new(pac.port);
140//! # let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
141//! let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
142//! ```
143//!
144//! Note that the divider value supplied to `Gclk::div` must be wrapped by the
145//! [`GclkDiv16`] enum. This is for a few different reasons. First, [`Gclk1`]
146//! accepts a wider range of divider values than the other [`Gclk`]s, which use
147//! [`GclkDiv8`] instead. Second, the actual divider value is controlled by two
148//! register fields, and the set of valid values is best expressed as a Rust
149//! enum. The `GclkDiv8` and `GclkDiv16` enums are connected by the
150//! [`GclkDivider`] trait.
151//!
152//! Once [`Gclk1`] is enabled, we can use it to enable the [`Pclk`] for
153//! [`Sercom0`]. This follows the usual pattern. We provide a [`PclkToken`] and
154//! the [`EnabledGclk1`]. In return, we get an enabled [`Pclk`] and the
155//! [`EnabledGclk1`] counter is [`Increment`]ed.
156//!
157//! ```no_run
158//! # use atsamd_hal::{
159//! # clock::v2::{
160//! # clock_system_at_reset,
161//! # gclk::{Gclk, GclkDiv8, GclkDiv16},
162//! # pclk::Pclk,
163//! # },
164//! # gpio::Pins,
165//! # pac::Peripherals,
166//! # fugit::RateExtU32,
167//! # };
168//! # let mut pac = Peripherals::take().unwrap();
169//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
170//! # pac.oscctrl,
171//! # pac.osc32kctrl,
172//! # pac.gclk,
173//! # pac.mclk,
174//! # &mut pac.nvmctrl,
175//! # );
176//! # let pins = Pins::new(pac.port);
177//! # let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
178//! # let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
179//! let (pclk_sercom0, gclk1) = Pclk::enable(tokens.pclks.sercom0, gclk1);
180//! ```
181//!
182//! Next, we use [`Gclk1`] as a clock [`Source`] to create an instance of
183//! [`Gclk2`] with [`Gclk::from_source`]. However, keep in mind that this is
184//! only true for [`Gclk1`]. No other [`Gclk`] can act as a [`Source`] for
185//! another [`Gclk`].
186//!
187//! ```no_run
188//! # use atsamd_hal::{
189//! # clock::v2::{
190//! # clock_system_at_reset,
191//! # gclk::{Gclk, GclkDiv8, GclkDiv16},
192//! # pclk::Pclk,
193//! # },
194//! # gpio::Pins,
195//! # pac::Peripherals,
196//! # fugit::RateExtU32,
197//! # };
198//! # let mut pac = Peripherals::take().unwrap();
199//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
200//! # pac.oscctrl,
201//! # pac.osc32kctrl,
202//! # pac.gclk,
203//! # pac.mclk,
204//! # &mut pac.nvmctrl,
205//! # );
206//! # let pins = Pins::new(pac.port);
207//! # let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
208//! # let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
209//! # let (pclk_sercom0, gclk1) = Pclk::enable(tokens.pclks.sercom0, gclk1);
210//! let (gclk2, gclk1) = Gclk::from_source(tokens.gclks.gclk2, gclk1);
211//! ```
212//!
213//! The pattern repeats now. We divide [`Gclk1`] by 4 to produce the [`Gclk2`]
214//! output. Then we enable it to produce an [`EnabledGclk2`] and use it to yield
215//! another [`Pclk`].
216//!
217//! ```no_run
218//! # use atsamd_hal::{
219//! # clock::v2::{
220//! # clock_system_at_reset,
221//! # gclk::{Gclk, GclkDiv8, GclkDiv16},
222//! # pclk::Pclk,
223//! # },
224//! # gpio::Pins,
225//! # pac::Peripherals,
226//! # fugit::RateExtU32,
227//! # };
228//! # let mut pac = Peripherals::take().unwrap();
229//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
230//! # pac.oscctrl,
231//! # pac.osc32kctrl,
232//! # pac.gclk,
233//! # pac.mclk,
234//! # &mut pac.nvmctrl,
235//! # );
236//! # let pins = Pins::new(pac.port);
237//! # let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
238//! # let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
239//! # let (pclk_sercom0, gclk1) = Pclk::enable(tokens.pclks.sercom0, gclk1);
240//! # let (gclk2, gclk1) = Gclk::from_source(tokens.gclks.gclk2, gclk1);
241//! let gclk2 = gclk2.div(GclkDiv8::Div(4)).enable();
242//! let (pclk_sercom1, gclk2) = Pclk::enable(tokens.pclks.sercom1, gclk2);
243//! ```
244//!
245//! Finally, we output [`Gclk2`] directly to a GPIO pin. We supply the GPIO
246//! [`Pin`] to the [`EnabledGclk2`] to yield a [`GclkOut`].
247//!
248//! ```no_run
249//! # use atsamd_hal::{
250//! # clock::v2::{
251//! # clock_system_at_reset,
252//! # gclk::{Gclk, GclkDiv8, GclkDiv16},
253//! # pclk::Pclk,
254//! # },
255//! # gpio::Pins,
256//! # pac::Peripherals,
257//! # fugit::RateExtU32,
258//! # };
259//! # let mut pac = Peripherals::take().unwrap();
260//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
261//! # pac.oscctrl,
262//! # pac.osc32kctrl,
263//! # pac.gclk,
264//! # pac.mclk,
265//! # &mut pac.nvmctrl,
266//! # );
267//! # let pins = Pins::new(pac.port);
268//! # let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
269//! # let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
270//! # let (pclk_sercom0, gclk1) = Pclk::enable(tokens.pclks.sercom0, gclk1);
271//! # let (gclk2, gclk1) = Gclk::from_source(tokens.gclks.gclk2, gclk1);
272//! # let gclk2 = gclk2.div(GclkDiv8::Div(4)).enable();
273//! # let (pclk_sercom1, gclk2) = Pclk::enable(tokens.pclks.sercom1, gclk2);
274//! let (gclk2, gclk2_out) = gclk2.enable_gclk_out(pins.pa16);
275//! ```
276//!
277//! The full example is provided below.
278//!
279//! ```no_run
280//! use atsamd_hal::{
281//! clock::v2::{
282//! clock_system_at_reset,
283//! gclk::{Gclk, GclkDiv8, GclkDiv16},
284//! pclk::Pclk,
285//! },
286//! gpio::Pins,
287//! pac::Peripherals,
288//! fugit::RateExtU32,
289//! };
290//! let mut pac = Peripherals::take().unwrap();
291//! let (mut buses, clocks, tokens) = clock_system_at_reset(
292//! pac.oscctrl,
293//! pac.osc32kctrl,
294//! pac.gclk,
295//! pac.mclk,
296//! &mut pac.nvmctrl,
297//! );
298//! let pins = Pins::new(pac.port);
299//! let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
300//! let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
301//! let (pclk_sercom0, gclk1) = Pclk::enable(tokens.pclks.sercom0, gclk1);
302//! let (gclk2, gclk1) = Gclk::from_source(tokens.gclks.gclk2, gclk1);
303//! let gclk2 = gclk2.div(GclkDiv8::Div(4)).enable();
304//! let (pclk_sercom1, gclk2) = Pclk::enable(tokens.pclks.sercom1, gclk2);
305//! let (gclk2, gclk2_out) = gclk2.enable_gclk_out(pins.pa16);
306//! ```
307//!
308//! ## `Gclk0`
309//!
310//! [`Gclk0`] is significant and special relative to the other [`Gclk`]s. It is
311//! the clock generator for the processor's main clock, so it can never be
312//! disabled. Consequently, it has a special API not available to the other
313//! `Gclk`s. While normal `Gclk`s can only change their clock [`Source`] or
314//! divider while disabled, `Gclk0` can never be disabled, so we provide this
315//! functionality on [`EnabledGclk0`] instead.
316//!
317//! We model the main clock's consumption of `Gclk0` by setting its [`Enabled`]
318//! counter to [`U1`] in [`clock_system_at_reset`]. This prevents users from
319//! ever disabling `EnabledGclk0`, because there is no way to [`Decrement`] its
320//! `Counter` to [`U0`].
321//!
322//! Additionally, we provide functions to change the clock `Source`, divider,
323//! etc. on `EnabledGclk0`, but we restrict them to the case where `N = U1`.
324//! This prevents users from changing its `Source` or divider if any *other,
325//! additional* clock consumes it (besides the main clock).
326//!
327//! [`clock_system_at_reset`]: super::clock_system_at_reset
328//! [`Xosc`]: super::xosc::Xosc
329//! [`Xosc32k`]: super::xosc32k::Xosc32k
330//! [`OscUlp32k`]: super::osculp32k::OscUlp32k
331//! [`Dfll`]: super::dfll::Dfll
332//! [`Dpll`]: super::dpll::Dpll
333//! [`PclkToken`]: super::pclk::PclkToken
334//! [`Pclk`]: super::pclk::Pclk
335//! [`Pins`]: crate::gpio::Pins
336//! [`Sercom0`]: crate::sercom::Sercom0
337
338use core::cmp::max;
339use core::marker::PhantomData;
340
341use paste::paste;
342use seq_macro::seq;
343use typenum::{U0, U1};
344
345use crate::pac;
346use crate::pac::Nvmctrl;
347use crate::pac::gclk::genctrl::Divselselect;
348
349use crate::gpio::{self, AlternateM, AnyPin, Pin, PinId};
350use crate::pac::gclk::Genctrl;
351use crate::pac::gclk::genctrl::Srcselect;
352use crate::time::Hertz;
353use crate::typelevel::{Decrement, Increment, PrivateDecrement, PrivateIncrement, Sealed};
354
355use super::dfll::DfllId;
356use super::dpll::{Dpll0Id, Dpll1Id};
357use super::osculp32k::OscUlp32kId;
358use super::xosc::{Xosc0Id, Xosc1Id};
359use super::xosc32k::Xosc32kId;
360use super::{Enabled, Source};
361
362//==============================================================================
363// GclkToken
364//==============================================================================
365
366/// Singleton token that can be exchanged for a [`Gclk`]
367///
368/// As explained in the [`clock` module documentation](super), instances of
369/// various `Token` types can be exchanged for actual clock types. They
370/// typically represent clocks that are disabled at power-on reset.
371///
372/// [`GclkToken`]s are no different. All [`Gclk`]s other than [`Gclk0`] are
373/// disabled at power-on reset. To use a [`Gclk`], you must first exchange the
374/// token for an actual clock with [`Gclk::from_source`] or [`Gclk::from_pin`].
375///
376/// [`GclkToken`] is generic over the [`GclkId`], where each corresponding token
377/// represents one of the 12 respective [`Gclk`]s.
378pub struct GclkToken<G: GclkId> {
379 generator: PhantomData<G>,
380}
381
382impl<G: GclkId> GclkToken<G> {
383 /// Create a new instance of [`GclkToken`]
384 ///
385 /// # Safety
386 ///
387 /// Each `GclkToken`s is a singleton. There must never be two simulatenous
388 /// instances with the same [`GclkId`]. See the notes on `Token` types and
389 /// memory safety in the root of the `clock` module for more details.
390 #[inline]
391 pub(super) unsafe fn new() -> Self {
392 GclkToken {
393 generator: PhantomData,
394 }
395 }
396
397 /// SYNCBUSY register mask for the corresponding GCLK
398 const MASK: u16 = 1 << G::NUM;
399
400 /// Provide a reference to the corresponding [`Genctrl`] register
401 #[inline]
402 fn genctrl(&self) -> &Genctrl {
403 // Safety: Each `GclkToken` only has access to a mutually exclusive set
404 // of registers for the corresponding `GclkId`, and we use a shared
405 // reference to the register block. See the notes on `Token` types and
406 // memory safety in the root of the `clock` module for more details.
407 unsafe { (*pac::Gclk::PTR).genctrl(G::NUM) }
408 }
409
410 /// Block until synchronization has completed
411 ///
412 /// Reads or writes to synchronized fields must be accompanied by a check of
413 /// the `SYNCBUSY` register. See the datasheet for more details.
414 #[inline]
415 fn wait_syncbusy(&self) {
416 // Safety: We are only reading from the `SYNCBUSY` register, and we are
417 // only observing the bit corresponding to this particular `GclkId`, so
418 // there is no risk of memory corruption.
419 let syncbusy = unsafe { &(*pac::Gclk::PTR).syncbusy() };
420 while syncbusy.read().genctrl().bits() & Self::MASK != 0 {}
421 }
422
423 /// Set the clock source for this [`Gclk`]
424 #[inline]
425 fn set_source(&mut self, source: DynGclkSourceId) {
426 self.genctrl().modify(|_, w| w.src().variant(source.into()));
427 self.wait_syncbusy();
428 }
429
430 /// Set the [`GclkDivider`] value
431 ///
432 /// Use the internal interface of [`GclkDivider`] to set the `DIV` and
433 /// `DIVSEL` fields of the `GENCTRL` register.
434 #[inline]
435 fn set_div(&mut self, div: G::Divider) {
436 let (divsel, div) = div.divsel_div();
437 // Safety: The `DIVSEL` and `DIV` values are derived from the
438 // `GclkDivider` type, so they are guaranteed to be valid.
439 self.genctrl().modify(|_, w| unsafe {
440 w.divsel().variant(divsel);
441 w.div().bits(div)
442 });
443 self.wait_syncbusy();
444 }
445
446 /// Output a 50-50 duty-cycle clock when using an odd division factor
447 #[inline]
448 fn improve_duty_cycle(&mut self, flag: bool) {
449 self.genctrl().modify(|_, w| w.idc().bit(flag));
450 self.wait_syncbusy();
451 }
452
453 /// Set the state of [`GclkOut`] pins when the GCLK_IO output is disabled
454 #[inline]
455 fn output_off_value(&mut self, high: bool) {
456 self.genctrl().modify(|_, w| w.oov().bit(high));
457 self.wait_syncbusy();
458 }
459
460 /// Enable [`Gclk`] output to a GPIO [`Pin`]
461 #[inline]
462 fn enable_gclk_out(&mut self) {
463 self.genctrl().modify(|_, w| w.oe().set_bit());
464 self.wait_syncbusy();
465 }
466
467 /// Disable [`Gclk`] output on a GPIO [`Pin`]
468 ///
469 /// If a corresponding [`Pin`] is in the [`AlternateM`] mode, it's logic
470 /// level will depend on the [`output_off_value`].
471 #[inline]
472 fn disable_gclk_out(&mut self) {
473 self.genctrl().modify(|_, w| w.oe().clear_bit());
474 self.wait_syncbusy();
475 }
476
477 #[inline]
478 fn configure(&mut self, id: DynGclkSourceId, settings: Settings<G>) {
479 let (divsel, div) = settings.div.divsel_div();
480 self.genctrl().modify(|_, w| {
481 // Safety: The `DIVSEL` and `DIV` values are derived from the
482 // `GclkDivider` type, so they are guaranteed to be valid.
483 unsafe {
484 w.divsel().variant(divsel);
485 w.div().bits(div);
486 };
487 w.src().variant(id.into());
488 w.idc().bit(settings.improve_duty_cycle);
489 w.oov().bit(settings.output_off_value)
490 });
491 self.wait_syncbusy();
492 }
493
494 /// Enable the [`Gclk`]
495 #[inline]
496 fn enable(&mut self) {
497 self.genctrl().modify(|_, w| w.genen().set_bit());
498 self.wait_syncbusy();
499 }
500
501 /// Disable the [`Gclk`]
502 #[inline]
503 fn disable(&mut self) {
504 self.genctrl().modify(|_, w| w.genen().clear_bit());
505 self.wait_syncbusy();
506 }
507}
508
509//==============================================================================
510// DynGclkId
511//==============================================================================
512
513/// Value-level enum identifying one of 12 possible [`Gclk`]s
514///
515/// The variants of this enum identify one of the 12 possible generic clock
516/// generators.
517///
518/// `DynGclkId` is the value-level equivalent of [`GclkId`].
519pub enum DynGclkId {
520 Gclk0,
521 Gclk1,
522 Gclk2,
523 Gclk3,
524 Gclk4,
525 Gclk5,
526 Gclk6,
527 Gclk7,
528 Gclk8,
529 Gclk9,
530 Gclk10,
531 Gclk11,
532}
533
534//==============================================================================
535// GclkId
536//==============================================================================
537
538/// Type-level enum identifying one of 12 possible [`Gclk`]s
539///
540/// The types implementing this trait, i.e. [`Gclk0Id`] - [`Gclk11Id`], are
541/// type-level variants of `GclkId`, and they identify one of the 12 possible
542/// generic clock generators.
543///
544/// `GclkId` is the type-level equivalent of [`DynGclkId`]. See the
545/// documentation on [type-level programming] and specifically
546/// [type-level enums] for more details.
547///
548/// [type-level programming]: crate::typelevel
549/// [type-level enums]: crate::typelevel#type-level-enums
550pub trait GclkId: Sealed {
551 /// Corresponding variant of [`DynGclkId`]
552 const DYN: DynGclkId;
553 /// Corresponding numeric index (0..12)
554 const NUM: usize;
555 /// Corresponding [`GclkDivider`] type
556 ///
557 /// [`Gclk1`] uses [`GclkDiv16`], while all other [`Gclk`]s use
558 /// [`GclkDiv8`].
559 type Divider: GclkDivider;
560}
561
562/// Type-level variant of [`GclkId`] representing the identity of GCLK0
563///
564/// See the documentation on [type-level programming] and specifically
565/// [type-level enums] for more details.
566///
567/// [type-level programming]: crate::typelevel
568/// [type-level enums]: crate::typelevel#type-level-enums
569pub enum Gclk0Id {}
570impl Sealed for Gclk0Id {}
571impl GclkId for Gclk0Id {
572 const DYN: DynGclkId = DynGclkId::Gclk0;
573 const NUM: usize = 0;
574 type Divider = GclkDiv8;
575}
576
577/// Type-level variant of [`GclkId`] representing the identity of GCLK1
578///
579/// See the documentation on [type-level programming] and specifically
580/// [type-level enums] for more details.
581///
582/// [type-level programming]: crate::typelevel
583/// [type-level enums]: crate::typelevel#type-level-enums
584pub enum Gclk1Id {}
585impl Sealed for Gclk1Id {}
586impl GclkId for Gclk1Id {
587 const DYN: DynGclkId = DynGclkId::Gclk1;
588 const NUM: usize = 1;
589 type Divider = GclkDiv16;
590}
591
592seq!(N in 2..=11 {
593 paste! {
594 /// Type-level variant of [`GclkId`] representing the identity of
595 #[doc = "GCLK" N]
596 ///
597 /// See the documentation on [type-level programming] and specifically
598 /// [type-level enums] for more details.
599 ///
600 /// [type-level programming]: crate::typelevel
601 /// [type-level enums]: crate::typelevel#type-level-enums
602 pub enum [<Gclk N Id>] {}
603 impl Sealed for [<Gclk N Id>] {}
604 impl GclkId for [<Gclk N Id>] {
605 const DYN: DynGclkId = DynGclkId::Gclk~N;
606 const NUM: usize = N;
607 type Divider = GclkDiv8;
608 }
609 }
610});
611
612//==============================================================================
613// GclkDivider
614//==============================================================================
615
616/// Trait unifying the two [`Gclk`] divider types, [`GclkDiv8`] and
617/// [`GclkDiv16`]
618///
619/// Choosing a [`Gclk`] division factor can be complicated. [`Gclk1`] can accept
620/// a 16-bit divider value, while all other [`Gclk`]s only take an 8-bit value.
621/// Moreover, the set of valid clock dividers does not form a contiguous range.
622/// For example, the valid set of dividers for most [`Gclk`]s is 1-256 and 512.
623///
624/// The [`GclkDiv8`] and [`GclkDiv16`] enums provide simple and intuitive
625/// user-facing interfaces to choose the *actual* clock divider value. This
626/// trait, on the other hand, provides an internal-facing interface used by HAL
627/// authors to extract the clock divider and convert it to the corresponding
628/// `DIVSEL` and `DIV` register fields. Users should have no reason to interact
629/// with this trait directly.
630pub trait GclkDivider: Sealed + Default + Copy {
631 /// Returns the actual clock divider value as a `u32`
632 fn divider(&self) -> u32;
633 /// Return the corresponding `DIVSEL` and and `DIV` register fields
634 fn divsel_div(&self) -> (Divselselect, u16);
635}
636
637//==============================================================================
638// GclkDiv8
639//==============================================================================
640
641/// Enum for the clock division factor of all [`Gclk`]s other than [`Gclk1`]
642///
643/// Choosing a [`Gclk`] division factor can be complicated, because the set of
644/// valid values is not contiguous. For clocks other than [`Gclk1`], the
645/// division factor can be 1-256 or 512. `GclkDiv8` provides an enum interface
646/// to enforce validity of the division factor. See the datasheet for more
647/// details.
648#[derive(Clone, Copy)]
649pub enum GclkDiv8 {
650 /// Use a literal division factor
651 ///
652 /// All values in the range `[1-255]` are valid. Zero is also valid, but it
653 /// is interpreted as `1`.
654 Div(u8),
655 /// Use a division factor of `2^8 = 256`
656 Div2Pow8,
657 /// Use a division factor of `2^9 = 512`
658 Div2Pow9,
659}
660
661impl Sealed for GclkDiv8 {}
662
663impl Default for GclkDiv8 {
664 #[inline]
665 fn default() -> Self {
666 Self::Div(0)
667 }
668}
669
670impl GclkDivider for GclkDiv8 {
671 #[inline]
672 fn divider(&self) -> u32 {
673 match self {
674 GclkDiv8::Div(div) => (*div).into(),
675 GclkDiv8::Div2Pow8 => 256,
676 GclkDiv8::Div2Pow9 => 512,
677 }
678 }
679
680 #[inline]
681 fn divsel_div(&self) -> (Divselselect, u16) {
682 match self {
683 GclkDiv8::Div(div) => (Divselselect::Div1, (*div).into()),
684 GclkDiv8::Div2Pow8 => (Divselselect::Div2, 7),
685 GclkDiv8::Div2Pow9 => (Divselselect::Div2, 8),
686 }
687 }
688}
689
690//==============================================================================
691// GclkDiv16
692//==============================================================================
693
694/// Enum for the clock division factor of [`Gclk1`] only
695///
696/// Choosing the [`Gclk1`] division factor can be complicated, because the set
697/// of valid values is not contiguous. For [`Gclk1`], the division factor can be
698/// 1-65536 or 131072. `GclkDiv16` provides an enum interface to enforce
699/// validity of the division factor. See the datasheet for more details.
700#[derive(Clone, Copy)]
701pub enum GclkDiv16 {
702 /// Use a literal division factor
703 ///
704 /// All values in the range `[1-65535]` are valid. Zero is also valid, but
705 /// it is interpreted as `1`.
706 Div(u16),
707 /// Use a division factor of `2^16 = 65536`
708 Div2Pow16,
709 /// Use a division factor of `2^17 = 131072`
710 Div2Pow17,
711}
712
713impl Sealed for GclkDiv16 {}
714
715impl Default for GclkDiv16 {
716 #[inline]
717 fn default() -> Self {
718 Self::Div(0)
719 }
720}
721
722impl GclkDivider for GclkDiv16 {
723 #[inline]
724 fn divider(&self) -> u32 {
725 match self {
726 GclkDiv16::Div(div) => (*div).into(),
727 GclkDiv16::Div2Pow16 => 65536,
728 GclkDiv16::Div2Pow17 => 131072,
729 }
730 }
731
732 #[inline]
733 fn divsel_div(&self) -> (Divselselect, u16) {
734 match self {
735 GclkDiv16::Div(div) => (Divselselect::Div1, *div),
736 GclkDiv16::Div2Pow16 => (Divselselect::Div2, 15),
737 GclkDiv16::Div2Pow17 => (Divselselect::Div2, 16),
738 }
739 }
740}
741
742//==============================================================================
743// GclkIo
744//==============================================================================
745
746/// Trait mapping each [`PinId`] to its corresponding [`GclkId`] when used as a
747/// [`Gclk`] input or output
748///
749/// If a given [`PinId`] can be used as a [`Gclk`] input or output, it can only
750/// be used with one specific [`GclkId`]. This trait provides a mapping from
751/// such a `PinId` to its corresponding `GclkId`.
752pub trait GclkIo: PinId {
753 /// Corresponding [`GclkId`] for this [`PinId`]
754 type GclkId: GclkId;
755}
756
757// These implementations are much easier to read with `#[rustfmt::skip]`
758#[rustfmt::skip]
759mod gclkio_impl {
760 use atsamd_hal_macros::hal_cfg;
761
762 use super::*;
763
764 #[hal_cfg("pa10")]
765 impl GclkIo for gpio::PA10 { type GclkId = Gclk4Id; }
766 #[hal_cfg("pa11")]
767 impl GclkIo for gpio::PA11 { type GclkId = Gclk5Id; }
768 #[hal_cfg("pa14")]
769 impl GclkIo for gpio::PA14 { type GclkId = Gclk0Id; }
770 #[hal_cfg("pa15")]
771 impl GclkIo for gpio::PA15 { type GclkId = Gclk1Id; }
772 #[hal_cfg("pa16")]
773 impl GclkIo for gpio::PA16 { type GclkId = Gclk2Id; }
774 #[hal_cfg("pa17")]
775 impl GclkIo for gpio::PA17 { type GclkId = Gclk3Id; }
776 #[hal_cfg("pa27")]
777 impl GclkIo for gpio::PA27 { type GclkId = Gclk1Id; }
778 #[hal_cfg("pa30")]
779 impl GclkIo for gpio::PA30 { type GclkId = Gclk0Id; }
780 #[hal_cfg("pb10")]
781 impl GclkIo for gpio::PB10 { type GclkId = Gclk4Id; }
782 #[hal_cfg("pb11")]
783 impl GclkIo for gpio::PB11 { type GclkId = Gclk5Id; }
784 #[hal_cfg("pb12")]
785 impl GclkIo for gpio::PB12 { type GclkId = Gclk6Id; }
786 #[hal_cfg("pb13")]
787 impl GclkIo for gpio::PB13 { type GclkId = Gclk7Id; }
788 #[hal_cfg("pb14")]
789 impl GclkIo for gpio::PB14 { type GclkId = Gclk0Id; }
790 #[hal_cfg("pb15")]
791 impl GclkIo for gpio::PB15 { type GclkId = Gclk1Id; }
792 #[hal_cfg("pb16")]
793 impl GclkIo for gpio::PB16 { type GclkId = Gclk2Id; }
794 #[hal_cfg("pb17")]
795 impl GclkIo for gpio::PB17 { type GclkId = Gclk3Id; }
796 #[hal_cfg("pb18")]
797 impl GclkIo for gpio::PB18 { type GclkId = Gclk4Id; }
798 #[hal_cfg("pb19")]
799 impl GclkIo for gpio::PB19 { type GclkId = Gclk5Id; }
800 #[hal_cfg("pb20")]
801 impl GclkIo for gpio::PB20 { type GclkId = Gclk6Id; }
802 #[hal_cfg("pb21")]
803 impl GclkIo for gpio::PB21 { type GclkId = Gclk7Id; }
804 #[hal_cfg("pb22")]
805 impl GclkIo for gpio::PB22 { type GclkId = Gclk0Id; }
806 #[hal_cfg("pb23")]
807 impl GclkIo for gpio::PB23 { type GclkId = Gclk1Id; }
808}
809
810//==============================================================================
811// Gclk0Io
812//==============================================================================
813
814/// Set of [`PinId`]s whose implementations of [`GclkIo`] map to [`Gclk0Id`]
815///
816/// This is effectively a trait alias for [`PinId`]s that implement [`GclkIo`]
817/// with a `GclkId` associated type of [`Gclk0Id`], i.e.
818/// `GclkIo<GclkId = Gclk0Id>`. The trait is useful to simply some function
819/// signatures and to help type inference in a few cases.
820pub trait Gclk0Io
821where
822 Self: Sized,
823 Self: GclkIo<GclkId = Gclk0Id>,
824 Self: GclkSourceId<Resource = Pin<Self, AlternateM>>,
825{
826}
827
828impl<I: GclkIo<GclkId = Gclk0Id>> Gclk0Io for I {}
829
830//==============================================================================
831// DynGclkSourceId
832//==============================================================================
833
834/// Value-level enum of possible clock sources for a [`Gclk`]
835///
836/// The variants of this enum identify one of nine possible clock sources for
837/// a given [`Gclk`].
838///
839/// `DynGclkSourceId` is the value-level equivalent of [`GclkSourceId`].
840#[derive(Copy, Clone, PartialEq, Eq)]
841pub enum DynGclkSourceId {
842 Dfll,
843 Dpll0,
844 Dpll1,
845 Gclk1,
846 GclkIn,
847 OscUlp32k,
848 Xosc0,
849 Xosc1,
850 Xosc32k,
851}
852
853impl From<DynGclkSourceId> for Srcselect {
854 fn from(source: DynGclkSourceId) -> Self {
855 use DynGclkSourceId::*;
856 match source {
857 Dfll => Self::Dfll,
858 Dpll0 => Self::Dpll0,
859 Dpll1 => Self::Dpll1,
860 Gclk1 => Self::Gclkgen1,
861 GclkIn => Self::Gclkin,
862 OscUlp32k => Self::Osculp32k,
863 Xosc0 => Self::Xosc0,
864 Xosc1 => Self::Xosc1,
865 Xosc32k => Self::Xosc32k,
866 }
867 }
868}
869
870//==============================================================================
871// GclkSourceId
872//==============================================================================
873
874/// Type-level enum of possible clock [`Source`]s for a [`Gclk`]
875///
876/// The types implementing this trait are type-level variants of `GclkSourceId`,
877/// and they identify one of nine possible clock [`Source`]s for a given
878/// [`Gclk`]. All implementers of this trait are `Id` types, which are described
879/// in more detail in the [`clock` module documentation](super).
880///
881/// `GclkSourceId` is the type-level equivalent of [`DynGclkSourceId`]. See the
882/// documentation on [type-level programming] and specifically
883/// [type-level enums] for more details.
884///
885/// [type-level programming]: crate::typelevel
886/// [type-level enums]: crate::typelevel#type-level-enums
887pub trait GclkSourceId {
888 /// Corresponding variant of [`DynGclkSourceId`]
889 const DYN: DynGclkSourceId;
890
891 /// Resource to store in the [`Gclk`]
892 ///
893 /// Maps to the corresponding [`Pin`] for [`GclkIo`] types. In all other
894 /// cases, there is nothing to store, so it is `()`.
895 #[doc(hidden)]
896 type Resource;
897}
898
899impl GclkSourceId for DfllId {
900 const DYN: DynGclkSourceId = DynGclkSourceId::Dfll;
901 type Resource = ();
902}
903impl GclkSourceId for Dpll0Id {
904 const DYN: DynGclkSourceId = DynGclkSourceId::Dpll0;
905 type Resource = ();
906}
907impl GclkSourceId for Dpll1Id {
908 const DYN: DynGclkSourceId = DynGclkSourceId::Dpll1;
909 type Resource = ();
910}
911impl GclkSourceId for Gclk1Id {
912 const DYN: DynGclkSourceId = DynGclkSourceId::Gclk1;
913 type Resource = ();
914}
915impl<I: GclkIo> GclkSourceId for I {
916 const DYN: DynGclkSourceId = DynGclkSourceId::GclkIn;
917 type Resource = Pin<I, AlternateM>;
918}
919impl GclkSourceId for OscUlp32kId {
920 const DYN: DynGclkSourceId = DynGclkSourceId::OscUlp32k;
921 type Resource = ();
922}
923impl GclkSourceId for Xosc0Id {
924 const DYN: DynGclkSourceId = DynGclkSourceId::Xosc0;
925 type Resource = ();
926}
927impl GclkSourceId for Xosc1Id {
928 const DYN: DynGclkSourceId = DynGclkSourceId::Xosc1;
929 type Resource = ();
930}
931impl GclkSourceId for Xosc32kId {
932 const DYN: DynGclkSourceId = DynGclkSourceId::Xosc32k;
933 type Resource = ();
934}
935
936//==============================================================================
937// NotGclkIo
938//==============================================================================
939
940/// Type-level enum of [`GclkSourceId`] types that are not a [`GclkIo`]
941///
942/// The datasheet notes that a [`Gclk`] can use a GPIO [`Pin`] as either input
943/// or output, but not both. Stated differently, you cannot create a [`GclkOut`]
944/// from a `Gclk` where the [`GclkSourceId`] is a [`PinId`].
945///
946/// This trait acts as a [type-level enum] narrowing [`GclkSourceId`] to exclude
947/// any types which implement [`GclkIo`].
948///
949/// [type-level enum]: crate::typelevel#type-level-enums
950pub trait NotGclkIo: GclkSourceId<Resource = ()> {}
951
952impl<I: GclkSourceId<Resource = ()>> NotGclkIo for I {}
953
954//==============================================================================
955// Settings
956//==============================================================================
957
958/// Collection of [`Gclk`] settings to configure on enable
959struct Settings<G: GclkId> {
960 div: G::Divider,
961 output_off_value: bool,
962 improve_duty_cycle: bool,
963}
964
965impl<G: GclkId> Clone for Settings<G> {
966 fn clone(&self) -> Self {
967 *self
968 }
969}
970
971impl<G: GclkId> Copy for Settings<G> {}
972
973impl<G: GclkId> Default for Settings<G> {
974 fn default() -> Self {
975 Settings {
976 div: G::Divider::default(),
977 output_off_value: false,
978 improve_duty_cycle: false,
979 }
980 }
981}
982
983//==============================================================================
984// Gclk
985//==============================================================================
986
987/// Generic clock generator used to distribute clocks to various peripherals
988///
989/// A generic clock generator acts as a branch in the clock tree. It can connect
990/// a root or branch clock to other branch or leaf clocks. In particular, all
991/// peripheral [`Pclk`]s must be derived from a `Gclk`.
992///
993/// The type parameter `G` is a [`GclkId`] that determines which of the 12
994/// generators this [`Gclk`] represents ([`Gclk0`] - [`Gclk11`]). The type
995/// parameter `I` represents the `Id` type for the clock [`Source`] driving this
996/// `Gclk`. It must be one of the valid [`GclkSourceId`]s. Alternatively, if the
997/// `Gclk` is driven by a [GPIO](gpio) [`Pin`], then `I` is a [`PinId`]
998/// implementing [`GclkIo`]. See the [`clock` module documentation](super) for
999/// more detail on `Id` types.
1000///
1001/// On its own, an instance of `Gclk` does not represent an enabled clock
1002/// generator. Instead, it must first be wrapped with [`Enabled`], which
1003/// implements compile-time safety of the clock tree.
1004///
1005/// Because the terminal call to [`enable`] consumes the `Gclk` and returns an
1006/// [`EnabledGclk`], the remaining API uses the builder pattern, where each
1007/// method takes and returns `self` by value, allowing them to be easily
1008/// chained.
1009///
1010/// See the [module-level documentation](self) for an example of creating,
1011/// configuring and using a `Gclk`.
1012///
1013/// [`Pclk`]: super::pclk::Pclk
1014/// [`enable`]: Gclk::enable
1015pub struct Gclk<G, I>
1016where
1017 G: GclkId,
1018 I: GclkSourceId,
1019{
1020 token: GclkToken<G>,
1021 resource: I::Resource,
1022 src_freq: Hertz,
1023 settings: Settings<G>,
1024}
1025
1026/// An [`Enabled`] [`Gclk`]
1027///
1028/// As described in the [`clock` module documentation](super), the [`Enabled`]
1029/// wrapper implements compile-time clock tree safety by tracking the number of
1030/// clocks consuming this [`Gclk`] and restricts access to the underlying
1031/// [`Gclk`] to prevent misuse.
1032///
1033/// As with [`Enabled`], the default value for `N` is `U0`; if left unspecified,
1034/// the counter is assumed to be zero.
1035pub type EnabledGclk<G, I, N = U0> = Enabled<Gclk<G, I>, N>;
1036
1037/// Type alias for the corresponding [`Gclk`]
1038///
1039/// As mentioned in the [module-level documentation](self), `Gclk0` is special,
1040/// because it provides the processor main clock. We represent this by
1041/// permanently [`Increment`]ing the counter for [`EnabledGclk0`], which
1042/// prevents it from ever being disabled. Accordingly, we also provide a few
1043/// special methods on [`EnabledGclk0`] to configure the `Gclk` while it is
1044/// actively running.
1045pub type Gclk0<I> = Gclk<Gclk0Id, I>;
1046
1047/// Type alias for the corresponding [`EnabledGclk`]
1048///
1049/// As mentioned in the [module-level documentation](self), `Gclk0` is special,
1050/// because it provides the processor main clock. We represent this by
1051/// permanently [`Increment`]ing the counter for [`EnabledGclk0`], which
1052/// prevents it from ever being disabled. Thus, the default value for `N` is
1053/// [`U1`] instead of [`U0`]. Accordingly, we also provide a few special methods
1054/// on [`EnabledGclk0`] to configure the `Gclk` while it is actively running.
1055pub type EnabledGclk0<I, N = U1> = EnabledGclk<Gclk0Id, I, N>;
1056
1057seq!(G in 1..=11 {
1058 paste! {
1059 /// Type alias for the corresponding [`Gclk`]
1060 pub type Gclk~G<I> = Gclk<[<Gclk G Id>], I>;
1061
1062 /// Type alias for the corresponding [`EnabledGclk`]
1063 pub type EnabledGclk~G<I, N = U0> = EnabledGclk<[<Gclk G Id>], I, N>;
1064 }
1065});
1066
1067impl<G, I> Gclk<G, I>
1068where
1069 G: GclkId,
1070 I: GclkIo<GclkId = G>,
1071{
1072 /// Create a new [`Gclk`] from a GPIO [`Pin`]
1073 ///
1074 /// Creating a [`Gclk`] does not modify any of the hardware registers. It
1075 /// only serves to consume the [`Pin`] and create a struct to track the GCLK
1076 /// configuration.
1077 ///
1078 /// The configuration data is stored until the user calls [`enable`]. At
1079 /// that point, all of the registers are written according to the
1080 /// initialization procedures specified in the datasheet, and an
1081 /// [`EnabledGclk`] is returned. The `Gclk` is not active or useful until
1082 /// that point.
1083 ///
1084 /// [`enable`]: Gclk::enable
1085 pub fn from_pin<P>(token: GclkToken<G>, pin: P, freq: impl Into<Hertz>) -> Self
1086 where
1087 P: AnyPin<Id = I>,
1088 {
1089 Gclk {
1090 token,
1091 resource: pin.into().into_mode(),
1092 src_freq: freq.into(),
1093 settings: Settings::default(),
1094 }
1095 }
1096
1097 /// Consume the [`Gclk`] and free its corresponding resources
1098 ///
1099 /// Freeing a [`Gclk`] returns the corresponding [`GclkToken`] and GPIO
1100 /// [`Pin`].
1101 pub fn free_pin(self) -> (GclkToken<G>, Pin<I, AlternateM>) {
1102 (self.token, self.resource)
1103 }
1104}
1105
1106impl<G, I> Gclk<G, I>
1107where
1108 G: GclkId,
1109 I: NotGclkIo,
1110{
1111 /// Create a new [`Gclk`] from a clock [`Source`]
1112 ///
1113 /// Creating a [`Gclk`] does not modify any of the hardware registers. It
1114 /// only serves to [`Increment`] the [`Source`]'s [`Enabled`] counter
1115 /// and create a struct to track the GCLK configuration.
1116 ///
1117 /// The configuration data is stored until the user calls [`enable`]. At
1118 /// that point, all of the registers are written according to the
1119 /// initialization procedures specified in the datasheet, and an
1120 /// [`EnabledGclk`] is returned. The `Gclk` is not active or useful until
1121 /// that point.
1122 ///
1123 /// [`enable`]: Gclk::enable
1124 #[inline]
1125 pub fn from_source<S>(token: GclkToken<G>, source: S) -> (Gclk<G, I>, S::Inc)
1126 where
1127 S: Source<Id = I> + Increment,
1128 {
1129 let config = Gclk {
1130 token,
1131 resource: (),
1132 src_freq: source.freq(),
1133 settings: Settings::default(),
1134 };
1135 (config, source.inc())
1136 }
1137
1138 /// Consume the [`Gclk`] and free its corresponding resources
1139 ///
1140 /// Freeing a [`Gclk`] returns the corresponding [`GclkToken`] and
1141 /// [`Decrement`]s the [`Source`]'s [`Enabled`] counter.
1142 #[inline]
1143 pub fn free_source<S>(self, source: S) -> (GclkToken<G>, S::Dec)
1144 where
1145 S: Source<Id = I> + Decrement,
1146 {
1147 (self.token, source.dec())
1148 }
1149}
1150
1151impl<G, I> Gclk<G, I>
1152where
1153 G: GclkId,
1154 I: GclkSourceId,
1155{
1156 /// Modify the source of an existing clock
1157 ///
1158 /// This is a helper function for swapping Gclk0 to different clock sources.
1159 fn change_source<N: GclkSourceId>(
1160 mut self,
1161 resource: N::Resource,
1162 freq: Hertz,
1163 ) -> (Gclk<G, N>, I::Resource) {
1164 self.token.set_source(N::DYN);
1165 let gclk = Gclk {
1166 token: self.token,
1167 resource,
1168 src_freq: freq,
1169 settings: self.settings,
1170 };
1171 (gclk, self.resource)
1172 }
1173
1174 /// Set the [`GclkDivider`] value
1175 ///
1176 /// Set the clock division factor from input to output. This takes either a
1177 /// [`GclkDiv8`] or [`GclkDiv16`] enum, restricting the possible division
1178 /// factors to only the valid ones for the given [`Gclk`]. See the
1179 /// [`GclkDivider`] trait for more details.
1180 #[inline]
1181 #[allow(clippy::should_implement_trait)]
1182 pub fn div(mut self, div: G::Divider) -> Self {
1183 self.settings.div = div;
1184 self
1185 }
1186
1187 /// Output a 50-50 duty cycle clock when using an odd [`GclkDivider`]
1188 #[inline]
1189 pub fn improve_duty_cycle(mut self, flag: bool) -> Self {
1190 self.settings.improve_duty_cycle = flag;
1191 self
1192 }
1193
1194 /// Return the [`Gclk`] ouput frequency
1195 ///
1196 /// This is the input frequency divided by the [`GclkDivider`].
1197 #[inline]
1198 pub fn freq(&self) -> Hertz {
1199 let div = max(1, self.settings.div.divider());
1200 self.src_freq / div
1201 }
1202
1203 /// Set the state of [`GclkOut`] pins when [`GclkIo`] output is disabled
1204 ///
1205 /// The output off value (OOV) determines the logic level of a [GPIO](gpio)
1206 /// [`Pin`] (configured as a [`GclkIo`] output) when the [`Gclk`] is
1207 /// disabled **OR** the [`GclkOut`] is disabled.
1208 ///
1209 /// As mentioned in the [`Gclk`] documentation, configuration options are
1210 /// not usually applied until the call to [`Gclk::enable`]. However, because
1211 /// the OOV is relevant when the `Gclk` is *disabled*, we make an exception.
1212 /// When calling this function, the new OOV will take effect immediately.
1213 ///
1214 /// However, remember that the `Pin` is not controlled by the `Gclk` unless
1215 /// the `Pin` is configured in [`AlternateM`] mode. `Pin`s are automatically
1216 /// set to `AlternateM` mode when calling [`enable_gclk_out`], but by that
1217 /// point, the OOV is irrelevant. If you need the `Pin` to be set to its
1218 /// OOV, you must *manually* set it to `AlternateM` mode before constructing
1219 /// the `GclkOut`.
1220 ///
1221 /// [`enable_gclk_out`]: EnabledGclk::enable_gclk_out
1222 #[inline]
1223 pub fn output_off_value(mut self, high: bool) -> Self {
1224 self.settings.output_off_value = high;
1225 self.token.output_off_value(high);
1226 self
1227 }
1228
1229 /// Enable the [`Gclk`], so that it can be used as a clock [`Source`]
1230 ///
1231 /// As mentioned in the [`Gclk`] documentation, no hardware registers are
1232 /// actually modified until this call. Rather, the desired configuration is
1233 /// stored internally, and the [`Gclk`] is initialized and configured here
1234 /// according to the datasheet.
1235 ///
1236 /// The returned value is an [`EnabledGclk`] that can be used as a clock
1237 /// [`Source`] for other clocks.
1238 #[inline]
1239 pub fn enable(mut self) -> EnabledGclk<G, I> {
1240 self.token.configure(I::DYN, self.settings);
1241 self.token.enable();
1242 Enabled::new(self)
1243 }
1244}
1245
1246impl<G, I> EnabledGclk<G, I>
1247where
1248 G: GclkId,
1249 I: GclkSourceId,
1250{
1251 /// Disable the [`Gclk`]
1252 ///
1253 /// This method is only implemented for `N = U0`, which means the clock can
1254 /// only be disabled when no other clocks consume this [`Gclk`].
1255 #[inline]
1256 pub fn disable(mut self) -> Gclk<G, I> {
1257 self.0.token.disable();
1258 self.0
1259 }
1260}
1261
1262/// Special methods for an [`Enabled`] [`Gclk0`]
1263///
1264/// [`Gclk0`] is special, because it drives the processor's main clock, which
1265/// can never be disabled. As discussed in the [module-level documentation],
1266/// this fact is represented by permanently [`Increment`]ing the counter for
1267/// [`EnabledGclk0`]. Thus, the minimum value for `N` is `U1` and
1268/// [`EnabledGclk0`] can never be disabled.
1269///
1270/// These methods represent actions that can be taken when `N = U1`, i.e. the
1271/// [`Enabled`] counter is at its minimum value. This is the only time it's
1272/// safe to change the [`Gclk0`] [`Source`] or change its [`GclkDivider`] value.
1273///
1274/// [module-level documentation]: self
1275impl<I: GclkSourceId> EnabledGclk0<I, U1> {
1276 /// Swap [`Gclk0`] from one clock [`Source`] to another
1277 ///
1278 /// `Gclk0` will remain fully enabled during the swap.
1279 #[inline]
1280 pub fn swap_sources<O, N>(self, old: O, new: N) -> (EnabledGclk0<N::Id, U1>, O::Dec, N::Inc)
1281 where
1282 O: Source<Id = I> + Decrement,
1283 N: Source + Increment,
1284 N::Id: NotGclkIo,
1285 {
1286 let (gclk, _) = self.0.change_source((), new.freq());
1287 let enabled = Enabled::new(gclk);
1288 (enabled, old.dec(), new.inc())
1289 }
1290
1291 /// Swap [`Gclk0`] from one [`GclkIo`] [`Pin`] to another
1292 ///
1293 /// `Gclk0` will remain fully enabled during the swap.
1294 #[inline]
1295 pub fn swap_pins<P>(
1296 self,
1297 pin: P,
1298 freq: impl Into<Hertz>,
1299 ) -> (EnabledGclk0<P::Id, U1>, Pin<I, AlternateM>)
1300 where
1301 I: Gclk0Io,
1302 P: AnyPin,
1303 P::Id: Gclk0Io,
1304 {
1305 let pin = pin.into().into_mode();
1306 let (gclk, pin) = self.0.change_source(pin, freq.into());
1307 let enabled = Enabled::new(gclk);
1308 (enabled, pin)
1309 }
1310
1311 /// Swap [`Gclk0`] from a clock [`Source`] to a [`GclkIo`] [`Pin`]
1312 ///
1313 /// `Gclk0` will remain fully enabled during the swap.
1314 #[inline]
1315 pub fn swap_source_for_pin<S, P>(
1316 self,
1317 source: S,
1318 pin: P,
1319 freq: impl Into<Hertz>,
1320 ) -> (EnabledGclk0<P::Id, U1>, S::Dec)
1321 where
1322 S: Source<Id = I> + Decrement,
1323 P: AnyPin,
1324 P::Id: Gclk0Io,
1325 {
1326 let pin = pin.into().into_mode();
1327 let (gclk, _) = self.0.change_source(pin, freq.into());
1328 let enabled = Enabled::new(gclk);
1329 (enabled, source.dec())
1330 }
1331
1332 /// Swap [`Gclk0`] from a [`GclkIo`] [`Pin`] to a clock [`Source`]
1333 ///
1334 /// `Gclk0` will remain fully enabled during the swap.
1335 #[inline]
1336 #[allow(clippy::type_complexity)]
1337 pub fn swap_pin_for_source<S>(
1338 self,
1339 source: S,
1340 ) -> (EnabledGclk0<S::Id, U1>, Pin<I, AlternateM>, S::Inc)
1341 where
1342 I: Gclk0Io,
1343 S: Source + Increment,
1344 S::Id: NotGclkIo,
1345 {
1346 let (gclk, pin) = self.0.change_source((), source.freq());
1347 let enabled = Enabled::new(gclk);
1348 (enabled, pin, source.inc())
1349 }
1350
1351 /// Set the [`GclkDivider`] value for [`Gclk0`]
1352 ///
1353 /// See [`Gclk::div`] documentation for more details.
1354 #[inline]
1355 pub fn div(&mut self, div: GclkDiv8) {
1356 self.0.settings.div = div;
1357 self.0.token.set_div(div);
1358 }
1359
1360 /// Output a 50-50 duty cycle clock when using an odd [`GclkDivider`]
1361 #[inline]
1362 pub fn improve_duty_cycle(&mut self, flag: bool) {
1363 self.0.settings.improve_duty_cycle = flag;
1364 self.0.token.improve_duty_cycle(flag);
1365 }
1366
1367 /// Return the [`Gclk0`] frequency
1368 ///
1369 /// See [`Gclk::freq`] documentation for more details.
1370 #[inline]
1371 pub fn freq(&self) -> Hertz {
1372 self.0.freq()
1373 }
1374
1375 /// Set the state of [`GclkOut`] pins when [`GclkIo`] output is disabled
1376 ///
1377 /// See [`Gclk::output_off_value`] documentation for more details.
1378 #[inline]
1379 pub fn output_off_value(&mut self, high: bool) {
1380 self.0.settings.output_off_value = high;
1381 self.0.token.output_off_value(high);
1382 }
1383}
1384
1385//==============================================================================
1386// Source
1387//==============================================================================
1388
1389impl<G, I, N> Source for EnabledGclk<G, I, N>
1390where
1391 G: GclkId,
1392 I: GclkSourceId,
1393{
1394 type Id = G;
1395
1396 #[inline]
1397 fn freq(&self) -> Hertz {
1398 self.0.freq()
1399 }
1400}
1401
1402//==============================================================================
1403// Tokens
1404//==============================================================================
1405
1406seq!(N in 1..=11 {
1407 paste! {
1408 /// Set of [`GclkToken`]s representing the disabled [`Gclk`]s at
1409 /// power-on reset
1410 pub struct GclkTokens {
1411 #(
1412 /// [`GclkToken`] for
1413 #[doc = "[`Gclk" N "`]"]
1414 pub gclk~N: GclkToken<[<Gclk N Id>]>,
1415 )*
1416 }
1417
1418 impl GclkTokens {
1419 /// Create the set of [`GclkToken`]s
1420 ///
1421 /// # Safety
1422 ///
1423 /// All of the invariants required by `GclkToken::new` must be
1424 /// upheld here as well.
1425 #[inline]
1426 pub(super) unsafe fn new(nvmctrl: &mut Nvmctrl) -> Self {
1427 unsafe {
1428 // Use auto wait states
1429 nvmctrl.ctrla().modify(|_, w| w.autows().set_bit());
1430 GclkTokens {
1431 #( gclk~N: GclkToken::new(), )*
1432 }
1433 }
1434 }
1435 }
1436 }
1437});
1438
1439//==============================================================================
1440// GclkOut
1441//==============================================================================
1442
1443/// A GPIO [`Pin`] configured as a [`Gclk`] output
1444///
1445/// The existence of this struct serves as proof that the corresponding [`Gclk`]
1446/// is [`Enabled`] and that it has been output to [`PinId`] `I`.
1447///
1448/// See the [module-level documentation](self) for an example of creating a
1449/// [`GclkOut`] from an [`EnabledGclk`].
1450pub struct GclkOut<I: GclkIo> {
1451 pin: Pin<I, AlternateM>,
1452 freq: Hertz,
1453}
1454
1455impl<G, I> GclkOut<I>
1456where
1457 G: GclkId,
1458 I: GclkIo<GclkId = G>,
1459{
1460 /// Return the frequency of the corresponding [`Gclk`]
1461 #[inline]
1462 pub fn freq(&self) -> Hertz {
1463 self.freq
1464 }
1465}
1466
1467impl<G, S, N> EnabledGclk<G, S, N>
1468where
1469 G: GclkId,
1470 S: NotGclkIo,
1471{
1472 /// Create and enable a [`GclkOut`]
1473 ///
1474 /// Enabling [`GclkIo`] output will [`Increment`] the `EnabledGclk`
1475 /// counter, which will prevent it from being disabled while the
1476 /// `GclkOut` exists.
1477 ///
1478 /// Note that a given [`Gclk`] can only use [`GclkIo`] for input **or**
1479 /// output, but not both simultaneously. The [`NotGclkIo`] trait exists to
1480 /// enforce this requirement.
1481 ///
1482 /// Finally, when a [`GclkOut`] is disabled, but the [`Pin`] is still in
1483 /// [`AlternateM`] mode, it takes the "output off value" of the `Gclk`. See
1484 /// the [`Gclk::output_off_value`] documentation for more details.
1485 #[inline]
1486 pub fn enable_gclk_out<P>(mut self, pin: P) -> (EnabledGclk<G, S, N::Inc>, GclkOut<P::Id>)
1487 where
1488 N: Increment,
1489 P: AnyPin,
1490 P::Id: GclkIo<GclkId = G>,
1491 {
1492 let pin = pin.into().into_mode();
1493 let freq = self.freq();
1494 self.0.token.enable_gclk_out();
1495 let gclk_out = GclkOut { pin, freq };
1496 (self.inc(), gclk_out)
1497 }
1498
1499 /// Disable a [`GclkOut`] and free its [`Pin`]
1500 ///
1501 /// Disabling [`GclkIo`] output will [`Decrement`] the [`EnabledGclk`]
1502 /// counter. When a [`GclkOut`] is disabled, but the [`Pin`] is still in
1503 /// [`AlternateM`] mode, it takes the "output off value" of the `Gclk`. See
1504 /// the [`Gclk::output_off_value`] documentation for more details.
1505 #[inline]
1506 pub fn disable_gclk_out<I>(
1507 mut self,
1508 gclk_out: GclkOut<I>,
1509 ) -> (EnabledGclk<G, S, N::Dec>, Pin<I, AlternateM>)
1510 where
1511 N: Decrement,
1512 I: GclkIo<GclkId = G>,
1513 {
1514 self.0.token.disable_gclk_out();
1515 (self.dec(), gclk_out.pin)
1516 }
1517}