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::gclk::genctrl::Divselselect;
347use crate::pac::Nvmctrl;
348
349use crate::gpio::{self, AlternateM, AnyPin, Pin, PinId};
350use crate::pac::gclk::genctrl::Srcselect;
351use crate::pac::gclk::Genctrl;
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 gen: 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 { gen: PhantomData }
393 }
394
395 /// SYNCBUSY register mask for the corresponding GCLK
396 const MASK: u16 = 1 << G::NUM;
397
398 /// Provide a reference to the corresponding [`Genctrl`] register
399 #[inline]
400 fn genctrl(&self) -> &Genctrl {
401 // Safety: Each `GclkToken` only has access to a mutually exclusive set
402 // of registers for the corresponding `GclkId`, and we use a shared
403 // reference to the register block. See the notes on `Token` types and
404 // memory safety in the root of the `clock` module for more details.
405 unsafe { (*pac::Gclk::PTR).genctrl(G::NUM) }
406 }
407
408 /// Block until synchronization has completed
409 ///
410 /// Reads or writes to synchronized fields must be accompanied by a check of
411 /// the `SYNCBUSY` register. See the datasheet for more details.
412 #[inline]
413 fn wait_syncbusy(&self) {
414 // Safety: We are only reading from the `SYNCBUSY` register, and we are
415 // only observing the bit corresponding to this particular `GclkId`, so
416 // there is no risk of memory corruption.
417 let syncbusy = unsafe { &(*pac::Gclk::PTR).syncbusy() };
418 while syncbusy.read().genctrl().bits() & Self::MASK != 0 {}
419 }
420
421 /// Set the clock source for this [`Gclk`]
422 #[inline]
423 fn set_source(&mut self, source: DynGclkSourceId) {
424 self.genctrl().modify(|_, w| w.src().variant(source.into()));
425 self.wait_syncbusy();
426 }
427
428 /// Set the [`GclkDivider`] value
429 ///
430 /// Use the internal interface of [`GclkDivider`] to set the `DIV` and
431 /// `DIVSEL` fields of the `GENCTRL` register.
432 #[inline]
433 fn set_div(&mut self, div: G::Divider) {
434 let (divsel, div) = div.divsel_div();
435 // Safety: The `DIVSEL` and `DIV` values are derived from the
436 // `GclkDivider` type, so they are guaranteed to be valid.
437 self.genctrl().modify(|_, w| unsafe {
438 w.divsel().variant(divsel);
439 w.div().bits(div)
440 });
441 self.wait_syncbusy();
442 }
443
444 /// Output a 50-50 duty-cycle clock when using an odd division factor
445 #[inline]
446 fn improve_duty_cycle(&mut self, flag: bool) {
447 self.genctrl().modify(|_, w| w.idc().bit(flag));
448 self.wait_syncbusy();
449 }
450
451 /// Set the state of [`GclkOut`] pins when the GCLK_IO output is disabled
452 #[inline]
453 fn output_off_value(&mut self, high: bool) {
454 self.genctrl().modify(|_, w| w.oov().bit(high));
455 self.wait_syncbusy();
456 }
457
458 /// Enable [`Gclk`] output to a GPIO [`Pin`]
459 #[inline]
460 fn enable_gclk_out(&mut self) {
461 self.genctrl().modify(|_, w| w.oe().set_bit());
462 self.wait_syncbusy();
463 }
464
465 /// Disable [`Gclk`] output on a GPIO [`Pin`]
466 ///
467 /// If a corresponding [`Pin`] is in the [`AlternateM`] mode, it's logic
468 /// level will depend on the [`output_off_value`].
469 #[inline]
470 fn disable_gclk_out(&mut self) {
471 self.genctrl().modify(|_, w| w.oe().clear_bit());
472 self.wait_syncbusy();
473 }
474
475 #[inline]
476 fn configure(&mut self, id: DynGclkSourceId, settings: Settings<G>) {
477 let (divsel, div) = settings.div.divsel_div();
478 self.genctrl().modify(|_, w| {
479 // Safety: The `DIVSEL` and `DIV` values are derived from the
480 // `GclkDivider` type, so they are guaranteed to be valid.
481 unsafe {
482 w.divsel().variant(divsel);
483 w.div().bits(div);
484 };
485 w.src().variant(id.into());
486 w.idc().bit(settings.improve_duty_cycle);
487 w.oov().bit(settings.output_off_value)
488 });
489 self.wait_syncbusy();
490 }
491
492 /// Enable the [`Gclk`]
493 #[inline]
494 fn enable(&mut self) {
495 self.genctrl().modify(|_, w| w.genen().set_bit());
496 self.wait_syncbusy();
497 }
498
499 /// Disable the [`Gclk`]
500 #[inline]
501 fn disable(&mut self) {
502 self.genctrl().modify(|_, w| w.genen().clear_bit());
503 self.wait_syncbusy();
504 }
505}
506
507//==============================================================================
508// DynGclkId
509//==============================================================================
510
511/// Value-level enum identifying one of 12 possible [`Gclk`]s
512///
513/// The variants of this enum identify one of the 12 possible generic clock
514/// generators.
515///
516/// `DynGclkId` is the value-level equivalent of [`GclkId`].
517pub enum DynGclkId {
518 Gclk0,
519 Gclk1,
520 Gclk2,
521 Gclk3,
522 Gclk4,
523 Gclk5,
524 Gclk6,
525 Gclk7,
526 Gclk8,
527 Gclk9,
528 Gclk10,
529 Gclk11,
530}
531
532//==============================================================================
533// GclkId
534//==============================================================================
535
536/// Type-level enum identifying one of 12 possible [`Gclk`]s
537///
538/// The types implementing this trait, i.e. [`Gclk0Id`] - [`Gclk11Id`], are
539/// type-level variants of `GclkId`, and they identify one of the 12 possible
540/// generic clock generators.
541///
542/// `GclkId` is the type-level equivalent of [`DynGclkId`]. See the
543/// documentation on [type-level programming] and specifically
544/// [type-level enums] for more details.
545///
546/// [type-level programming]: crate::typelevel
547/// [type-level enums]: crate::typelevel#type-level-enums
548pub trait GclkId: Sealed {
549 /// Corresponding variant of [`DynGclkId`]
550 const DYN: DynGclkId;
551 /// Corresponding numeric index (0..12)
552 const NUM: usize;
553 /// Corresponding [`GclkDivider`] type
554 ///
555 /// [`Gclk1`] uses [`GclkDiv16`], while all other [`Gclk`]s use
556 /// [`GclkDiv8`].
557 type Divider: GclkDivider;
558}
559
560/// Type-level variant of [`GclkId`] representing the identity of GCLK0
561///
562/// See the documentation on [type-level programming] and specifically
563/// [type-level enums] for more details.
564///
565/// [type-level programming]: crate::typelevel
566/// [type-level enums]: crate::typelevel#type-level-enums
567pub enum Gclk0Id {}
568impl Sealed for Gclk0Id {}
569impl GclkId for Gclk0Id {
570 const DYN: DynGclkId = DynGclkId::Gclk0;
571 const NUM: usize = 0;
572 type Divider = GclkDiv8;
573}
574
575/// Type-level variant of [`GclkId`] representing the identity of GCLK1
576///
577/// See the documentation on [type-level programming] and specifically
578/// [type-level enums] for more details.
579///
580/// [type-level programming]: crate::typelevel
581/// [type-level enums]: crate::typelevel#type-level-enums
582pub enum Gclk1Id {}
583impl Sealed for Gclk1Id {}
584impl GclkId for Gclk1Id {
585 const DYN: DynGclkId = DynGclkId::Gclk1;
586 const NUM: usize = 1;
587 type Divider = GclkDiv16;
588}
589
590seq!(N in 2..=11 {
591 paste! {
592 /// Type-level variant of [`GclkId`] representing the identity of
593 #[doc = "GCLK" N]
594 ///
595 /// See the documentation on [type-level programming] and specifically
596 /// [type-level enums] for more details.
597 ///
598 /// [type-level programming]: crate::typelevel
599 /// [type-level enums]: crate::typelevel#type-level-enums
600 pub enum [<Gclk N Id>] {}
601 impl Sealed for [<Gclk N Id>] {}
602 impl GclkId for [<Gclk N Id>] {
603 const DYN: DynGclkId = DynGclkId::Gclk~N;
604 const NUM: usize = N;
605 type Divider = GclkDiv8;
606 }
607 }
608});
609
610//==============================================================================
611// GclkDivider
612//==============================================================================
613
614/// Trait unifying the two [`Gclk`] divider types, [`GclkDiv8`] and
615/// [`GclkDiv16`]
616///
617/// Choosing a [`Gclk`] division factor can be complicated. [`Gclk1`] can accept
618/// a 16-bit divider value, while all other [`Gclk`]s only take an 8-bit value.
619/// Moreover, the set of valid clock dividers does not form a contiguous range.
620/// For example, the valid set of dividers for most [`Gclk`]s is 1-256 and 512.
621///
622/// The [`GclkDiv8`] and [`GclkDiv16`] enums provide simple and intuitive
623/// user-facing interfaces to choose the *actual* clock divider value. This
624/// trait, on the other hand, provides an internal-facing interface used by HAL
625/// authors to extract the clock divider and convert it to the corresponding
626/// `DIVSEL` and `DIV` register fields. Users should have no reason to interact
627/// with this trait directly.
628pub trait GclkDivider: Sealed + Default + Copy {
629 /// Returns the actual clock divider value as a `u32`
630 fn divider(&self) -> u32;
631 /// Return the corresponding `DIVSEL` and and `DIV` register fields
632 fn divsel_div(&self) -> (Divselselect, u16);
633}
634
635//==============================================================================
636// GclkDiv8
637//==============================================================================
638
639/// Enum for the clock division factor of all [`Gclk`]s other than [`Gclk1`]
640///
641/// Choosing a [`Gclk`] division factor can be complicated, because the set of
642/// valid values is not contiguous. For clocks other than [`Gclk1`], the
643/// division factor can be 1-256 or 512. `GclkDiv8` provides an enum interface
644/// to enforce validity of the division factor. See the datasheet for more
645/// details.
646#[derive(Clone, Copy)]
647pub enum GclkDiv8 {
648 /// Use a literal division factor
649 ///
650 /// All values in the range `[1-255]` are valid. Zero is also valid, but it
651 /// is interpreted as `1`.
652 Div(u8),
653 /// Use a division factor of `2^8 = 256`
654 Div2Pow8,
655 /// Use a division factor of `2^9 = 512`
656 Div2Pow9,
657}
658
659impl Sealed for GclkDiv8 {}
660
661impl Default for GclkDiv8 {
662 #[inline]
663 fn default() -> Self {
664 Self::Div(0)
665 }
666}
667
668impl GclkDivider for GclkDiv8 {
669 #[inline]
670 fn divider(&self) -> u32 {
671 match self {
672 GclkDiv8::Div(div) => (*div).into(),
673 GclkDiv8::Div2Pow8 => 256,
674 GclkDiv8::Div2Pow9 => 512,
675 }
676 }
677
678 #[inline]
679 fn divsel_div(&self) -> (Divselselect, u16) {
680 match self {
681 GclkDiv8::Div(div) => (Divselselect::Div1, (*div).into()),
682 GclkDiv8::Div2Pow8 => (Divselselect::Div2, 7),
683 GclkDiv8::Div2Pow9 => (Divselselect::Div2, 8),
684 }
685 }
686}
687
688//==============================================================================
689// GclkDiv16
690//==============================================================================
691
692/// Enum for the clock division factor of [`Gclk1`] only
693///
694/// Choosing the [`Gclk1`] division factor can be complicated, because the set
695/// of valid values is not contiguous. For [`Gclk1`], the division factor can be
696/// 1-65536 or 131072. `GclkDiv16` provides an enum interface to enforce
697/// validity of the division factor. See the datasheet for more details.
698#[derive(Clone, Copy)]
699pub enum GclkDiv16 {
700 /// Use a literal division factor
701 ///
702 /// All values in the range `[1-65535]` are valid. Zero is also valid, but
703 /// it is interpreted as `1`.
704 Div(u16),
705 /// Use a division factor of `2^16 = 65536`
706 Div2Pow16,
707 /// Use a division factor of `2^17 = 131072`
708 Div2Pow17,
709}
710
711impl Sealed for GclkDiv16 {}
712
713impl Default for GclkDiv16 {
714 #[inline]
715 fn default() -> Self {
716 Self::Div(0)
717 }
718}
719
720impl GclkDivider for GclkDiv16 {
721 #[inline]
722 fn divider(&self) -> u32 {
723 match self {
724 GclkDiv16::Div(div) => (*div).into(),
725 GclkDiv16::Div2Pow16 => 65536,
726 GclkDiv16::Div2Pow17 => 131072,
727 }
728 }
729
730 #[inline]
731 fn divsel_div(&self) -> (Divselselect, u16) {
732 match self {
733 GclkDiv16::Div(div) => (Divselselect::Div1, *div),
734 GclkDiv16::Div2Pow16 => (Divselselect::Div2, 15),
735 GclkDiv16::Div2Pow17 => (Divselselect::Div2, 16),
736 }
737 }
738}
739
740//==============================================================================
741// GclkIo
742//==============================================================================
743
744/// Trait mapping each [`PinId`] to its corresponding [`GclkId`] when used as a
745/// [`Gclk`] input or output
746///
747/// If a given [`PinId`] can be used as a [`Gclk`] input or output, it can only
748/// be used with one specific [`GclkId`]. This trait provides a mapping from
749/// such a `PinId` to its corresponding `GclkId`.
750pub trait GclkIo: PinId {
751 /// Corresponding [`GclkId`] for this [`PinId`]
752 type GclkId: GclkId;
753}
754
755// These implementations are much easier to read with `#[rustfmt::skip]`
756#[rustfmt::skip]
757mod gclkio_impl {
758 use atsamd_hal_macros::hal_cfg;
759
760 use super::*;
761
762 #[hal_cfg("pa10")]
763 impl GclkIo for gpio::PA10 { type GclkId = Gclk4Id; }
764 #[hal_cfg("pa11")]
765 impl GclkIo for gpio::PA11 { type GclkId = Gclk5Id; }
766 #[hal_cfg("pa14")]
767 impl GclkIo for gpio::PA14 { type GclkId = Gclk0Id; }
768 #[hal_cfg("pa15")]
769 impl GclkIo for gpio::PA15 { type GclkId = Gclk1Id; }
770 #[hal_cfg("pa16")]
771 impl GclkIo for gpio::PA16 { type GclkId = Gclk2Id; }
772 #[hal_cfg("pa17")]
773 impl GclkIo for gpio::PA17 { type GclkId = Gclk3Id; }
774 #[hal_cfg("pa27")]
775 impl GclkIo for gpio::PA27 { type GclkId = Gclk1Id; }
776 #[hal_cfg("pa30")]
777 impl GclkIo for gpio::PA30 { type GclkId = Gclk0Id; }
778 #[hal_cfg("pb10")]
779 impl GclkIo for gpio::PB10 { type GclkId = Gclk4Id; }
780 #[hal_cfg("pb11")]
781 impl GclkIo for gpio::PB11 { type GclkId = Gclk5Id; }
782 #[hal_cfg("pb12")]
783 impl GclkIo for gpio::PB12 { type GclkId = Gclk6Id; }
784 #[hal_cfg("pb13")]
785 impl GclkIo for gpio::PB13 { type GclkId = Gclk7Id; }
786 #[hal_cfg("pb14")]
787 impl GclkIo for gpio::PB14 { type GclkId = Gclk0Id; }
788 #[hal_cfg("pb15")]
789 impl GclkIo for gpio::PB15 { type GclkId = Gclk1Id; }
790 #[hal_cfg("pb16")]
791 impl GclkIo for gpio::PB16 { type GclkId = Gclk2Id; }
792 #[hal_cfg("pb17")]
793 impl GclkIo for gpio::PB17 { type GclkId = Gclk3Id; }
794 #[hal_cfg("pb18")]
795 impl GclkIo for gpio::PB18 { type GclkId = Gclk4Id; }
796 #[hal_cfg("pb19")]
797 impl GclkIo for gpio::PB19 { type GclkId = Gclk5Id; }
798 #[hal_cfg("pb20")]
799 impl GclkIo for gpio::PB20 { type GclkId = Gclk6Id; }
800 #[hal_cfg("pb21")]
801 impl GclkIo for gpio::PB21 { type GclkId = Gclk7Id; }
802 #[hal_cfg("pb22")]
803 impl GclkIo for gpio::PB22 { type GclkId = Gclk0Id; }
804 #[hal_cfg("pb23")]
805 impl GclkIo for gpio::PB23 { type GclkId = Gclk1Id; }
806}
807
808//==============================================================================
809// Gclk0Io
810//==============================================================================
811
812/// Set of [`PinId`]s whose implementations of [`GclkIo`] map to [`Gclk0Id`]
813///
814/// This is effectively a trait alias for [`PinId`]s that implement [`GclkIo`]
815/// with a `GclkId` associated type of [`Gclk0Id`], i.e.
816/// `GclkIo<GclkId = Gclk0Id>`. The trait is useful to simply some function
817/// signatures and to help type inference in a few cases.
818pub trait Gclk0Io
819where
820 Self: Sized,
821 Self: GclkIo<GclkId = Gclk0Id>,
822 Self: GclkSourceId<Resource = Pin<Self, AlternateM>>,
823{
824}
825
826impl<I: GclkIo<GclkId = Gclk0Id>> Gclk0Io for I {}
827
828//==============================================================================
829// DynGclkSourceId
830//==============================================================================
831
832/// Value-level enum of possible clock sources for a [`Gclk`]
833///
834/// The variants of this enum identify one of nine possible clock sources for
835/// a given [`Gclk`].
836///
837/// `DynGclkSourceId` is the value-level equivalent of [`GclkSourceId`].
838#[derive(Copy, Clone, PartialEq, Eq)]
839pub enum DynGclkSourceId {
840 Dfll,
841 Dpll0,
842 Dpll1,
843 Gclk1,
844 GclkIn,
845 OscUlp32k,
846 Xosc0,
847 Xosc1,
848 Xosc32k,
849}
850
851impl From<DynGclkSourceId> for Srcselect {
852 fn from(source: DynGclkSourceId) -> Self {
853 use DynGclkSourceId::*;
854 match source {
855 Dfll => Self::Dfll,
856 Dpll0 => Self::Dpll0,
857 Dpll1 => Self::Dpll1,
858 Gclk1 => Self::Gclkgen1,
859 GclkIn => Self::Gclkin,
860 OscUlp32k => Self::Osculp32k,
861 Xosc0 => Self::Xosc0,
862 Xosc1 => Self::Xosc1,
863 Xosc32k => Self::Xosc32k,
864 }
865 }
866}
867
868//==============================================================================
869// GclkSourceId
870//==============================================================================
871
872/// Type-level enum of possible clock [`Source`]s for a [`Gclk`]
873///
874/// The types implementing this trait are type-level variants of `GclkSourceId`,
875/// and they identify one of nine possible clock [`Source`]s for a given
876/// [`Gclk`]. All implementers of this trait are `Id` types, which are described
877/// in more detail in the [`clock` module documentation](super).
878///
879/// `GclkSourceId` is the type-level equivalent of [`DynGclkSourceId`]. See the
880/// documentation on [type-level programming] and specifically
881/// [type-level enums] for more details.
882///
883/// [type-level programming]: crate::typelevel
884/// [type-level enums]: crate::typelevel#type-level-enums
885pub trait GclkSourceId {
886 /// Corresponding variant of [`DynGclkSourceId`]
887 const DYN: DynGclkSourceId;
888
889 /// Resource to store in the [`Gclk`]
890 ///
891 /// Maps to the corresponding [`Pin`] for [`GclkIo`] types. In all other
892 /// cases, there is nothing to store, so it is `()`.
893 #[doc(hidden)]
894 type Resource;
895}
896
897impl GclkSourceId for DfllId {
898 const DYN: DynGclkSourceId = DynGclkSourceId::Dfll;
899 type Resource = ();
900}
901impl GclkSourceId for Dpll0Id {
902 const DYN: DynGclkSourceId = DynGclkSourceId::Dpll0;
903 type Resource = ();
904}
905impl GclkSourceId for Dpll1Id {
906 const DYN: DynGclkSourceId = DynGclkSourceId::Dpll1;
907 type Resource = ();
908}
909impl GclkSourceId for Gclk1Id {
910 const DYN: DynGclkSourceId = DynGclkSourceId::Gclk1;
911 type Resource = ();
912}
913impl<I: GclkIo> GclkSourceId for I {
914 const DYN: DynGclkSourceId = DynGclkSourceId::GclkIn;
915 type Resource = Pin<I, AlternateM>;
916}
917impl GclkSourceId for OscUlp32kId {
918 const DYN: DynGclkSourceId = DynGclkSourceId::OscUlp32k;
919 type Resource = ();
920}
921impl GclkSourceId for Xosc0Id {
922 const DYN: DynGclkSourceId = DynGclkSourceId::Xosc0;
923 type Resource = ();
924}
925impl GclkSourceId for Xosc1Id {
926 const DYN: DynGclkSourceId = DynGclkSourceId::Xosc1;
927 type Resource = ();
928}
929impl GclkSourceId for Xosc32kId {
930 const DYN: DynGclkSourceId = DynGclkSourceId::Xosc32k;
931 type Resource = ();
932}
933
934//==============================================================================
935// NotGclkIo
936//==============================================================================
937
938/// Type-level enum of [`GclkSourceId`] types that are not a [`GclkIo`]
939///
940/// The datasheet notes that a [`Gclk`] can use a GPIO [`Pin`] as either input
941/// or output, but not both. Stated differently, you cannot create a [`GclkOut`]
942/// from a `Gclk` where the [`GclkSourceId`] is a [`PinId`].
943///
944/// This trait acts as a [type-level enum] narrowing [`GclkSourceId`] to exclude
945/// any types which implement [`GclkIo`].
946///
947/// [type-level enum]: crate::typelevel#type-level-enums
948pub trait NotGclkIo: GclkSourceId<Resource = ()> {}
949
950impl<I: GclkSourceId<Resource = ()>> NotGclkIo for I {}
951
952//==============================================================================
953// Settings
954//==============================================================================
955
956/// Collection of [`Gclk`] settings to configure on enable
957struct Settings<G: GclkId> {
958 div: G::Divider,
959 output_off_value: bool,
960 improve_duty_cycle: bool,
961}
962
963impl<G: GclkId> Clone for Settings<G> {
964 fn clone(&self) -> Self {
965 *self
966 }
967}
968
969impl<G: GclkId> Copy for Settings<G> {}
970
971impl<G: GclkId> Default for Settings<G> {
972 fn default() -> Self {
973 Settings {
974 div: G::Divider::default(),
975 output_off_value: false,
976 improve_duty_cycle: false,
977 }
978 }
979}
980
981//==============================================================================
982// Gclk
983//==============================================================================
984
985/// Generic clock generator used to distribute clocks to various peripherals
986///
987/// A generic clock generator acts as a branch in the clock tree. It can connect
988/// a root or branch clock to other branch or leaf clocks. In particular, all
989/// peripheral [`Pclk`]s must be derived from a `Gclk`.
990///
991/// The type parameter `G` is a [`GclkId`] that determines which of the 12
992/// generators this [`Gclk`] represents ([`Gclk0`] - [`Gclk11`]). The type
993/// parameter `I` represents the `Id` type for the clock [`Source`] driving this
994/// `Gclk`. It must be one of the valid [`GclkSourceId`]s. Alternatively, if the
995/// `Gclk` is driven by a [GPIO](gpio) [`Pin`], then `I` is a [`PinId`]
996/// implementing [`GclkIo`]. See the [`clock` module documentation](super) for
997/// more detail on `Id` types.
998///
999/// On its own, an instance of `Gclk` does not represent an enabled clock
1000/// generator. Instead, it must first be wrapped with [`Enabled`], which
1001/// implements compile-time safety of the clock tree.
1002///
1003/// Because the terminal call to [`enable`] consumes the `Gclk` and returns an
1004/// [`EnabledGclk`], the remaining API uses the builder pattern, where each
1005/// method takes and returns `self` by value, allowing them to be easily
1006/// chained.
1007///
1008/// See the [module-level documentation](self) for an example of creating,
1009/// configuring and using a `Gclk`.
1010///
1011/// [`Pclk`]: super::pclk::Pclk
1012/// [`enable`]: Gclk::enable
1013pub struct Gclk<G, I>
1014where
1015 G: GclkId,
1016 I: GclkSourceId,
1017{
1018 token: GclkToken<G>,
1019 resource: I::Resource,
1020 src_freq: Hertz,
1021 settings: Settings<G>,
1022}
1023
1024/// An [`Enabled`] [`Gclk`]
1025///
1026/// As described in the [`clock` module documentation](super), the [`Enabled`]
1027/// wrapper implements compile-time clock tree safety by tracking the number of
1028/// clocks consuming this [`Gclk`] and restricts access to the underlying
1029/// [`Gclk`] to prevent misuse.
1030///
1031/// As with [`Enabled`], the default value for `N` is `U0`; if left unspecified,
1032/// the counter is assumed to be zero.
1033pub type EnabledGclk<G, I, N = U0> = Enabled<Gclk<G, I>, N>;
1034
1035/// Type alias for the corresponding [`Gclk`]
1036///
1037/// As mentioned in the [module-level documentation](self), `Gclk0` is special,
1038/// because it provides the processor main clock. We represent this by
1039/// permanently [`Increment`]ing the counter for [`EnabledGclk0`], which
1040/// prevents it from ever being disabled. Accordingly, we also provide a few
1041/// special methods on [`EnabledGclk0`] to configure the `Gclk` while it is
1042/// actively running.
1043pub type Gclk0<I> = Gclk<Gclk0Id, I>;
1044
1045/// Type alias for the corresponding [`EnabledGclk`]
1046///
1047/// As mentioned in the [module-level documentation](self), `Gclk0` is special,
1048/// because it provides the processor main clock. We represent this by
1049/// permanently [`Increment`]ing the counter for [`EnabledGclk0`], which
1050/// prevents it from ever being disabled. Thus, the default value for `N` is
1051/// [`U1`] instead of [`U0`]. Accordingly, we also provide a few special methods
1052/// on [`EnabledGclk0`] to configure the `Gclk` while it is actively running.
1053pub type EnabledGclk0<I, N = U1> = EnabledGclk<Gclk0Id, I, N>;
1054
1055seq!(G in 1..=11 {
1056 paste! {
1057 /// Type alias for the corresponding [`Gclk`]
1058 pub type Gclk~G<I> = Gclk<[<Gclk G Id>], I>;
1059
1060 /// Type alias for the corresponding [`EnabledGclk`]
1061 pub type EnabledGclk~G<I, N = U0> = EnabledGclk<[<Gclk G Id>], I, N>;
1062 }
1063});
1064
1065impl<G, I> Gclk<G, I>
1066where
1067 G: GclkId,
1068 I: GclkIo<GclkId = G>,
1069{
1070 /// Create a new [`Gclk`] from a GPIO [`Pin`]
1071 ///
1072 /// Creating a [`Gclk`] does not modify any of the hardware registers. It
1073 /// only serves to consume the [`Pin`] and create a struct to track the GCLK
1074 /// configuration.
1075 ///
1076 /// The configuration data is stored until the user calls [`enable`]. At
1077 /// that point, all of the registers are written according to the
1078 /// initialization procedures specified in the datasheet, and an
1079 /// [`EnabledGclk`] is returned. The `Gclk` is not active or useful until
1080 /// that point.
1081 ///
1082 /// [`enable`]: Gclk::enable
1083 pub fn from_pin<P>(token: GclkToken<G>, pin: P, freq: impl Into<Hertz>) -> Self
1084 where
1085 P: AnyPin<Id = I>,
1086 {
1087 Gclk {
1088 token,
1089 resource: pin.into().into_mode(),
1090 src_freq: freq.into(),
1091 settings: Settings::default(),
1092 }
1093 }
1094
1095 /// Consume the [`Gclk`] and free its corresponding resources
1096 ///
1097 /// Freeing a [`Gclk`] returns the corresponding [`GclkToken`] and GPIO
1098 /// [`Pin`].
1099 pub fn free_pin(self) -> (GclkToken<G>, Pin<I, AlternateM>) {
1100 (self.token, self.resource)
1101 }
1102}
1103
1104impl<G, I> Gclk<G, I>
1105where
1106 G: GclkId,
1107 I: NotGclkIo,
1108{
1109 /// Create a new [`Gclk`] from a clock [`Source`]
1110 ///
1111 /// Creating a [`Gclk`] does not modify any of the hardware registers. It
1112 /// only serves to [`Increment`] the [`Source`]'s [`Enabled`] counter
1113 /// and create a struct to track the GCLK configuration.
1114 ///
1115 /// The configuration data is stored until the user calls [`enable`]. At
1116 /// that point, all of the registers are written according to the
1117 /// initialization procedures specified in the datasheet, and an
1118 /// [`EnabledGclk`] is returned. The `Gclk` is not active or useful until
1119 /// that point.
1120 ///
1121 /// [`enable`]: Gclk::enable
1122 #[inline]
1123 pub fn from_source<S>(token: GclkToken<G>, source: S) -> (Gclk<G, I>, S::Inc)
1124 where
1125 S: Source<Id = I> + Increment,
1126 {
1127 let config = Gclk {
1128 token,
1129 resource: (),
1130 src_freq: source.freq(),
1131 settings: Settings::default(),
1132 };
1133 (config, source.inc())
1134 }
1135
1136 /// Consume the [`Gclk`] and free its corresponding resources
1137 ///
1138 /// Freeing a [`Gclk`] returns the corresponding [`GclkToken`] and
1139 /// [`Decrement`]s the [`Source`]'s [`Enabled`] counter.
1140 #[inline]
1141 pub fn free_source<S>(self, source: S) -> (GclkToken<G>, S::Dec)
1142 where
1143 S: Source<Id = I> + Decrement,
1144 {
1145 (self.token, source.dec())
1146 }
1147}
1148
1149impl<G, I> Gclk<G, I>
1150where
1151 G: GclkId,
1152 I: GclkSourceId,
1153{
1154 /// Modify the source of an existing clock
1155 ///
1156 /// This is a helper function for swapping Gclk0 to different clock sources.
1157 fn change_source<N: GclkSourceId>(
1158 mut self,
1159 resource: N::Resource,
1160 freq: Hertz,
1161 ) -> (Gclk<G, N>, I::Resource) {
1162 self.token.set_source(N::DYN);
1163 let gclk = Gclk {
1164 token: self.token,
1165 resource,
1166 src_freq: freq,
1167 settings: self.settings,
1168 };
1169 (gclk, self.resource)
1170 }
1171
1172 /// Set the [`GclkDivider`] value
1173 ///
1174 /// Set the clock division factor from input to output. This takes either a
1175 /// [`GclkDiv8`] or [`GclkDiv16`] enum, restricting the possible division
1176 /// factors to only the valid ones for the given [`Gclk`]. See the
1177 /// [`GclkDivider`] trait for more details.
1178 #[inline]
1179 #[allow(clippy::should_implement_trait)]
1180 pub fn div(mut self, div: G::Divider) -> Self {
1181 self.settings.div = div;
1182 self
1183 }
1184
1185 /// Output a 50-50 duty cycle clock when using an odd [`GclkDivider`]
1186 #[inline]
1187 pub fn improve_duty_cycle(mut self, flag: bool) -> Self {
1188 self.settings.improve_duty_cycle = flag;
1189 self
1190 }
1191
1192 /// Return the [`Gclk`] ouput frequency
1193 ///
1194 /// This is the input frequency divided by the [`GclkDivider`].
1195 #[inline]
1196 pub fn freq(&self) -> Hertz {
1197 let div = max(1, self.settings.div.divider());
1198 self.src_freq / div
1199 }
1200
1201 /// Set the state of [`GclkOut`] pins when [`GclkIo`] output is disabled
1202 ///
1203 /// The output off value (OOV) determines the logic level of a [GPIO](gpio)
1204 /// [`Pin`] (configured as a [`GclkIo`] output) when the [`Gclk`] is
1205 /// disabled **OR** the [`GclkOut`] is disabled.
1206 ///
1207 /// As mentioned in the [`Gclk`] documentation, configuration options are
1208 /// not usually applied until the call to [`Gclk::enable`]. However, because
1209 /// the OOV is relevant when the `Gclk` is *disabled*, we make an exception.
1210 /// When calling this function, the new OOV will take effect immediately.
1211 ///
1212 /// However, remember that the `Pin` is not controlled by the `Gclk` unless
1213 /// the `Pin` is configured in [`AlternateM`] mode. `Pin`s are automatically
1214 /// set to `AlternateM` mode when calling [`enable_gclk_out`], but by that
1215 /// point, the OOV is irrelevant. If you need the `Pin` to be set to its
1216 /// OOV, you must *manually* set it to `AlternateM` mode before constructing
1217 /// the `GclkOut`.
1218 ///
1219 /// [`enable_gclk_out`]: EnabledGclk::enable_gclk_out
1220 #[inline]
1221 pub fn output_off_value(mut self, high: bool) -> Self {
1222 self.settings.output_off_value = high;
1223 self.token.output_off_value(high);
1224 self
1225 }
1226
1227 /// Enable the [`Gclk`], so that it can be used as a clock [`Source`]
1228 ///
1229 /// As mentioned in the [`Gclk`] documentation, no hardware registers are
1230 /// actually modified until this call. Rather, the desired configuration is
1231 /// stored internally, and the [`Gclk`] is initialized and configured here
1232 /// according to the datasheet.
1233 ///
1234 /// The returned value is an [`EnabledGclk`] that can be used as a clock
1235 /// [`Source`] for other clocks.
1236 #[inline]
1237 pub fn enable(mut self) -> EnabledGclk<G, I> {
1238 self.token.configure(I::DYN, self.settings);
1239 self.token.enable();
1240 Enabled::new(self)
1241 }
1242}
1243
1244impl<G, I> EnabledGclk<G, I>
1245where
1246 G: GclkId,
1247 I: GclkSourceId,
1248{
1249 /// Disable the [`Gclk`]
1250 ///
1251 /// This method is only implemented for `N = U0`, which means the clock can
1252 /// only be disabled when no other clocks consume this [`Gclk`].
1253 #[inline]
1254 pub fn disable(mut self) -> Gclk<G, I> {
1255 self.0.token.disable();
1256 self.0
1257 }
1258}
1259
1260/// Special methods for an [`Enabled`] [`Gclk0`]
1261///
1262/// [`Gclk0`] is special, because it drives the processor's main clock, which
1263/// can never be disabled. As discussed in the [module-level documentation],
1264/// this fact is represented by permanently [`Increment`]ing the counter for
1265/// [`EnabledGclk0`]. Thus, the minimum value for `N` is `U1` and
1266/// [`EnabledGclk0`] can never be disabled.
1267///
1268/// These methods represent actions that can be taken when `N = U1`, i.e. the
1269/// [`Enabled`] counter is at its minimum value. This is the only time it's
1270/// safe to change the [`Gclk0`] [`Source`] or change its [`GclkDivider`] value.
1271///
1272/// [module-level documentation]: self
1273impl<I: GclkSourceId> EnabledGclk0<I, U1> {
1274 /// Swap [`Gclk0`] from one clock [`Source`] to another
1275 ///
1276 /// `Gclk0` will remain fully enabled during the swap.
1277 #[inline]
1278 pub fn swap_sources<O, N>(self, old: O, new: N) -> (EnabledGclk0<N::Id, U1>, O::Dec, N::Inc)
1279 where
1280 O: Source<Id = I> + Decrement,
1281 N: Source + Increment,
1282 N::Id: NotGclkIo,
1283 {
1284 let (gclk, _) = self.0.change_source((), new.freq());
1285 let enabled = Enabled::new(gclk);
1286 (enabled, old.dec(), new.inc())
1287 }
1288
1289 /// Swap [`Gclk0`] from one [`GclkIo`] [`Pin`] to another
1290 ///
1291 /// `Gclk0` will remain fully enabled during the swap.
1292 #[inline]
1293 pub fn swap_pins<P>(
1294 self,
1295 pin: P,
1296 freq: impl Into<Hertz>,
1297 ) -> (EnabledGclk0<P::Id, U1>, Pin<I, AlternateM>)
1298 where
1299 I: Gclk0Io,
1300 P: AnyPin,
1301 P::Id: Gclk0Io,
1302 {
1303 let pin = pin.into().into_mode();
1304 let (gclk, pin) = self.0.change_source(pin, freq.into());
1305 let enabled = Enabled::new(gclk);
1306 (enabled, pin)
1307 }
1308
1309 /// Swap [`Gclk0`] from a clock [`Source`] to a [`GclkIo`] [`Pin`]
1310 ///
1311 /// `Gclk0` will remain fully enabled during the swap.
1312 #[inline]
1313 pub fn swap_source_for_pin<S, P>(
1314 self,
1315 source: S,
1316 pin: P,
1317 freq: impl Into<Hertz>,
1318 ) -> (EnabledGclk0<P::Id, U1>, S::Dec)
1319 where
1320 S: Source<Id = I> + Decrement,
1321 P: AnyPin,
1322 P::Id: Gclk0Io,
1323 {
1324 let pin = pin.into().into_mode();
1325 let (gclk, _) = self.0.change_source(pin, freq.into());
1326 let enabled = Enabled::new(gclk);
1327 (enabled, source.dec())
1328 }
1329
1330 /// Swap [`Gclk0`] from a [`GclkIo`] [`Pin`] to a clock [`Source`]
1331 ///
1332 /// `Gclk0` will remain fully enabled during the swap.
1333 #[inline]
1334 #[allow(clippy::type_complexity)]
1335 pub fn swap_pin_for_source<S>(
1336 self,
1337 source: S,
1338 ) -> (EnabledGclk0<S::Id, U1>, Pin<I, AlternateM>, S::Inc)
1339 where
1340 I: Gclk0Io,
1341 S: Source + Increment,
1342 S::Id: NotGclkIo,
1343 {
1344 let (gclk, pin) = self.0.change_source((), source.freq());
1345 let enabled = Enabled::new(gclk);
1346 (enabled, pin, source.inc())
1347 }
1348
1349 /// Set the [`GclkDivider`] value for [`Gclk0`]
1350 ///
1351 /// See [`Gclk::div`] documentation for more details.
1352 #[inline]
1353 pub fn div(&mut self, div: GclkDiv8) {
1354 self.0.settings.div = div;
1355 self.0.token.set_div(div);
1356 }
1357
1358 /// Output a 50-50 duty cycle clock when using an odd [`GclkDivider`]
1359 #[inline]
1360 pub fn improve_duty_cycle(&mut self, flag: bool) {
1361 self.0.settings.improve_duty_cycle = flag;
1362 self.0.token.improve_duty_cycle(flag);
1363 }
1364
1365 /// Return the [`Gclk0`] frequency
1366 ///
1367 /// See [`Gclk::freq`] documentation for more details.
1368 #[inline]
1369 pub fn freq(&self) -> Hertz {
1370 self.0.freq()
1371 }
1372
1373 /// Set the state of [`GclkOut`] pins when [`GclkIo`] output is disabled
1374 ///
1375 /// See [`Gclk::output_off_value`] documentation for more details.
1376 #[inline]
1377 pub fn output_off_value(&mut self, high: bool) {
1378 self.0.settings.output_off_value = high;
1379 self.0.token.output_off_value(high);
1380 }
1381}
1382
1383//==============================================================================
1384// Source
1385//==============================================================================
1386
1387impl<G, I, N> Source for EnabledGclk<G, I, N>
1388where
1389 G: GclkId,
1390 I: GclkSourceId,
1391{
1392 type Id = G;
1393
1394 #[inline]
1395 fn freq(&self) -> Hertz {
1396 self.0.freq()
1397 }
1398}
1399
1400//==============================================================================
1401// Tokens
1402//==============================================================================
1403
1404seq!(N in 1..=11 {
1405 paste! {
1406 /// Set of [`GclkToken`]s representing the disabled [`Gclk`]s at
1407 /// power-on reset
1408 pub struct GclkTokens {
1409 #(
1410 /// [`GclkToken`] for
1411 #[doc = "[`Gclk" N "`]"]
1412 pub gclk~N: GclkToken<[<Gclk N Id>]>,
1413 )*
1414 }
1415
1416 impl GclkTokens {
1417 /// Create the set of [`GclkToken`]s
1418 ///
1419 /// # Safety
1420 ///
1421 /// All of the invariants required by `GclkToken::new` must be
1422 /// upheld here as well.
1423 #[inline]
1424 pub(super) unsafe fn new(nvmctrl: &mut Nvmctrl) -> Self {
1425 // Use auto wait states
1426 nvmctrl.ctrla().modify(|_, w| w.autows().set_bit());
1427 GclkTokens {
1428 #( gclk~N: GclkToken::new(), )*
1429 }
1430 }
1431 }
1432 }
1433});
1434
1435//==============================================================================
1436// GclkOut
1437//==============================================================================
1438
1439/// A GPIO [`Pin`] configured as a [`Gclk`] output
1440///
1441/// The existence of this struct serves as proof that the corresponding [`Gclk`]
1442/// is [`Enabled`] and that it has been output to [`PinId`] `I`.
1443///
1444/// See the [module-level documentation](self) for an example of creating a
1445/// [`GclkOut`] from an [`EnabledGclk`].
1446pub struct GclkOut<I: GclkIo> {
1447 pin: Pin<I, AlternateM>,
1448 freq: Hertz,
1449}
1450
1451impl<G, I> GclkOut<I>
1452where
1453 G: GclkId,
1454 I: GclkIo<GclkId = G>,
1455{
1456 /// Return the frequency of the corresponding [`Gclk`]
1457 #[inline]
1458 pub fn freq(&self) -> Hertz {
1459 self.freq
1460 }
1461}
1462
1463impl<G, S, N> EnabledGclk<G, S, N>
1464where
1465 G: GclkId,
1466 S: NotGclkIo,
1467{
1468 /// Create and enable a [`GclkOut`]
1469 ///
1470 /// Enabling [`GclkIo`] output will [`Increment`] the `EnabledGclk`
1471 /// counter, which will prevent it from being disabled while the
1472 /// `GclkOut` exists.
1473 ///
1474 /// Note that a given [`Gclk`] can only use [`GclkIo`] for input **or**
1475 /// output, but not both simultaneously. The [`NotGclkIo`] trait exists to
1476 /// enforce this requirement.
1477 ///
1478 /// Finally, when a [`GclkOut`] is disabled, but the [`Pin`] is still in
1479 /// [`AlternateM`] mode, it takes the "output off value" of the `Gclk`. See
1480 /// the [`Gclk::output_off_value`] documentation for more details.
1481 #[inline]
1482 pub fn enable_gclk_out<P>(mut self, pin: P) -> (EnabledGclk<G, S, N::Inc>, GclkOut<P::Id>)
1483 where
1484 N: Increment,
1485 P: AnyPin,
1486 P::Id: GclkIo<GclkId = G>,
1487 {
1488 let pin = pin.into().into_mode();
1489 let freq = self.freq();
1490 self.0.token.enable_gclk_out();
1491 let gclk_out = GclkOut { pin, freq };
1492 (self.inc(), gclk_out)
1493 }
1494
1495 /// Disable a [`GclkOut`] and free its [`Pin`]
1496 ///
1497 /// Disabling [`GclkIo`] output will [`Decrement`] the [`EnabledGclk`]
1498 /// counter. When a [`GclkOut`] is disabled, but the [`Pin`] is still in
1499 /// [`AlternateM`] mode, it takes the "output off value" of the `Gclk`. See
1500 /// the [`Gclk::output_off_value`] documentation for more details.
1501 #[inline]
1502 pub fn disable_gclk_out<I>(
1503 mut self,
1504 gclk_out: GclkOut<I>,
1505 ) -> (EnabledGclk<G, S, N::Dec>, Pin<I, AlternateM>)
1506 where
1507 N: Decrement,
1508 I: GclkIo<GclkId = G>,
1509 {
1510 self.0.token.disable_gclk_out();
1511 (self.dec(), gclk_out.pin)
1512 }
1513}