atsamd_hal/peripherals/clock/d5x/v2/reset.rs
1//! This module is intentionally private. Its contents are publicly exported
2//! from the `v2` module, which is where the corresponding documentation will
3//! appear.
4
5use typenum::U1;
6
7use crate::pac::{Gclk, Mclk, Nvmctrl, Osc32kctrl, Oscctrl};
8
9use super::*;
10
11/// Collection of low-level PAC structs
12///
13/// This struct serves to guard access to the low-level PAC structs. It places
14/// them behind an `unsafe` barrier.
15///
16/// Normally, users trade the low-level PAC structs for the higher-level
17/// `clock::v2` API. However, in some cases, the `clock::v2` API may not be
18/// sufficient. In these cases, users can access the registers directly by
19/// calling [`Pac::steal`] to recover the PAC structs.
20pub struct Pac {
21 oscctrl: Oscctrl,
22 osc32kctrl: Osc32kctrl,
23 gclk: Gclk,
24 mclk: Mclk,
25}
26
27impl Pac {
28 /// Escape hatch allowing to access low-level PAC structs
29 ///
30 /// Consume the [`Pac`] and return the low-level PAC structs. This is
31 /// useful when the `clock::v2` API does not provide a necessary feature, or
32 /// when dealing with the legacy `clock::v1` API. For example, many of the
33 /// `clock::v1` functions require access to the [`Mclk`] peripheral.
34 ///
35 /// # Safety
36 ///
37 /// Directly configuring clocks through the PAC API can invalidate the
38 /// type-level guarantees of the `clock` module API.
39 pub unsafe fn steal(self) -> (Oscctrl, Osc32kctrl, Gclk, Mclk) {
40 (self.oscctrl, self.osc32kctrl, self.gclk, self.mclk)
41 }
42}
43
44/// Bus clock objects
45///
46/// This type is constructed using the [`clock_system_at_reset`] function, which
47/// consumes the PAC-level clocking structs and returns the HAL-level clocking
48/// structs in their reset state.
49///
50/// This type contains the [bus clocks](super#bus-clocks), which are a necessary
51/// to implement memory safety for the [`AhbClk`]s and [`ApbClk`]s.
52///
53/// [`AhbClk`]: super::ahb::AhbClk
54/// [`ApbClk`]: super::apb::ApbClk
55pub struct Buses {
56 pub ahb: ahb::Ahb,
57 pub apb: apb::Apb,
58}
59
60/// Enabled clocks at power-on reset
61///
62/// This type is constructed using the [`clock_system_at_reset`] function, which
63/// consumes the PAC-level clocking structs and returns the HAL-level clocking
64/// structs in their reset state.
65///
66/// This type represents the clocks as they are configured at power-on reset.
67/// The main clock, [`Gclk0`](gclk::Gclk0), runs at 48 MHz using the
68/// [`Dfll`](dfll::Dfll) in open-loop mode. The ultra-low power
69/// [base oscillator](osculp32k::OscUlp32kBase) is also enabled and running, as
70/// it can never be disabled.
71///
72/// As described in the [top-level](super::super) documentation for the `clock`
73/// module, only [`Enabled`] clocks can be used as a [`Source`] for downstream
74/// clocks. This struct contains all of the `Enabled` clocks at reset.
75///
76/// This struct also contains the [`Pac`] wrapper struct, which provides
77/// `unsafe` access to the low-level PAC structs.
78pub struct Clocks {
79 /// Wrapper providing `unsafe` access to low-level PAC structs
80 pub pac: Pac,
81 /// Enabled AHB clocks
82 pub ahbs: ahb::AhbClks,
83 /// Enabled APB clocks
84 pub apbs: apb::ApbClks,
85 /// Main system clock, driven at 48 MHz by the DFLL in open loop mode
86 pub gclk0: Enabled<gclk::Gclk0<dfll::DfllId>, U1>,
87 /// DFLL48 in open loop mode
88 pub dfll: Enabled<dfll::Dfll, U1>,
89 /// Always-enabled base oscillator for the [`OscUlp1k`](osculp32k::OscUlp1k)
90 /// and [`OscUlp32k`](osculp32k::OscUlp32k) clocks.
91 pub osculp32k_base: Enabled<osculp32k::OscUlp32kBase>,
92}
93
94/// Type-level tokens for unused clocks at power-on reset
95///
96/// This type is constructed using the [`clock_system_at_reset`] function, which
97/// consumes the PAC-level clocking structs and returns the HAL-level clocking
98/// structs in their reset state.
99///
100/// As described in the [top-level](super::super) documentation for the `clock`
101/// module, token types are used to guanrantee the uniqueness of each clock. To
102/// configure or enable a clock, you must provide the corresponding token.
103pub struct Tokens {
104 /// Tokens to create [`apb::ApbClk`]s
105 pub apbs: apb::ApbTokens,
106 /// Token to create [`dpll::Dpll0`]
107 pub dpll0: dpll::DpllToken<dpll::Dpll0Id>,
108 /// Token to create [`dpll::Dpll1`]
109 pub dpll1: dpll::DpllToken<dpll::Dpll1Id>,
110 /// Tokens to create [`gclk::Gclk`]
111 pub gclks: gclk::GclkTokens,
112 /// Tokens to create [`pclk::Pclk`]s
113 pub pclks: pclk::PclkTokens,
114 /// Tokens to create [`rtcosc::RtcOsc`]
115 pub rtcosc: rtcosc::RtcOscToken,
116 /// Tokens [`xosc::Xosc0`]
117 pub xosc0: xosc::XoscToken<xosc::Xosc0Id>,
118 /// Token to create [`xosc::Xosc1`]
119 pub xosc1: xosc::XoscToken<xosc::Xosc1Id>,
120 /// Tokens to create [`xosc32k::Xosc32kBase`], [`xosc32k::Xosc1k`] and
121 /// [`xosc32k::Xosc32k`]
122 pub xosc32k: xosc32k::Xosc32kTokens,
123 /// Tokens to create [`osculp32k::OscUlp1k`] and [`osculp32k::OscUlp32k`]
124 pub osculp32k: osculp32k::OscUlp32kTokens,
125}
126
127/// Consume the PAC clocking structs and return a HAL-level
128/// representation of the clocks at power-on reset
129///
130/// This function consumes the [`Oscctrl`], [`Osc32kctrl`], [`Gclk`] and
131/// [`Mclk`] PAC structs and returns the [`Buses`], [`Clocks`] and [`Tokens`].
132///
133/// See the [module-level documentation](super) for more details.
134#[inline]
135pub fn clock_system_at_reset(
136 oscctrl: Oscctrl,
137 osc32kctrl: Osc32kctrl,
138 gclk: Gclk,
139 mclk: Mclk,
140 nvmctrl: &mut Nvmctrl,
141) -> (Buses, Clocks, Tokens) {
142 // Safety: No bus, clock or token is instantiated more than once
143 unsafe {
144 let buses = Buses {
145 ahb: ahb::Ahb::new(),
146 apb: apb::Apb::new(),
147 };
148 let pac = Pac {
149 oscctrl,
150 osc32kctrl,
151 gclk,
152 mclk,
153 };
154 let dfll = Enabled::<_>::new(dfll::Dfll::open_loop(dfll::DfllToken::new()));
155 let (gclk0, dfll) = gclk::Gclk0::from_source(gclk::GclkToken::new(), dfll);
156 let gclk0 = Enabled::new(gclk0);
157 let clocks = Clocks {
158 pac,
159 ahbs: ahb::AhbClks::new(),
160 apbs: apb::ApbClks::new(),
161 gclk0,
162 dfll,
163 osculp32k_base: osculp32k::OscUlp32kBase::new(),
164 };
165 let tokens = Tokens {
166 apbs: apb::ApbTokens::new(),
167 dpll0: dpll::DpllToken::new(),
168 dpll1: dpll::DpllToken::new(),
169 gclks: gclk::GclkTokens::new(nvmctrl),
170 pclks: pclk::PclkTokens::new(),
171 rtcosc: rtcosc::RtcOscToken::new(),
172 xosc0: xosc::XoscToken::new(),
173 xosc1: xosc::XoscToken::new(),
174 xosc32k: xosc32k::Xosc32kTokens::new(),
175 osculp32k: osculp32k::OscUlp32kTokens::new(),
176 };
177 (buses, clocks, tokens)
178 }
179}