1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_clock_tree_mcuxpresso/clock_tree.h"
16
17 // Test headers
18 #include "pw_unit_test/framework.h"
19
20 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-Flexcomm0]
21
22 // Define FRO_DIV_4 clock source
23 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoFro fro_div4(kCLOCK_FroDiv4OutEn);
24
25 // Define FRG0 configuration
26 const clock_frg_clk_config_t g_frg0Config_BOARD_BOOTCLOCKRUN = {
27 .num = 0,
28 .sfg_clock_src = _clock_frg_clk_config::kCLOCK_FrgFroDiv4,
29 .divider = 255U,
30 .mult = 144};
31
32 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoFrgNonBlocking frg_0(
33 fro_div4, g_frg0Config_BOARD_BOOTCLOCKRUN);
34
35 // Define clock source selector FLEXCOMM0
36 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoSelectorNonBlocking
37 flexcomm_selector_0(frg_0, kFRG_to_FLEXCOMM0, kNONE_to_FLEXCOMM0);
38
39 // Define clock source clock ip name kCLOCK_Flexcomm0
40 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoClockIpNonBlocking flexcomm_0(
41 flexcomm_selector_0, kCLOCK_Flexcomm0);
42
43 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-Flexcomm0]
44
45 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-fro_div8]
46
47 // Define FRO_DIV8 clock source
48 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoFro fro_div8(kCLOCK_FroDiv8OutEn);
49
50 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-fro_div8]
51
52 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-i3c0]
53
54 // Define clock source selector I3C01FCLKSEL
55 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoSelectorNonBlocking i3c0_selector(
56 fro_div8, kFRO_DIV8_to_I3C_CLK, kNONE_to_I3C_CLK);
57
58 // Define clock divider I3C01FCLKDIV
59 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoDividerNonBlocking i3c0_divider(
60 i3c0_selector, kCLOCK_DivI3cClk, 12);
61
62 // Define clock source clock ip name kCLOCK_I3c0
63 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoClockIpNonBlocking i3c0(
64 i3c0_divider, kCLOCK_I3c0);
65
66 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-i3c0]
67
68 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClkTreeElemDefs-ClockSourceNoOp]
69
70 // Need to define `ClockSourceNoOp` clock tree element to satisfy dependency for
71 // `ClockMcuxpressoMclk` or `ClockMcuxpressoClkIn` class.
72 PW_CONSTINIT pw::clock_tree::ClockSourceNoOp clock_source_no_op;
73
74 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClkTreeElemDefs-ClockSourceNoOp]
75
76 // inclusive-language: disable
77 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-Ctimer0]
78
79 // Define Master clock
80 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoMclkNonBlocking mclk(
81 clock_source_no_op, 19200000);
82
83 // Define clock selector CTIMER0
84 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoSelectorNonBlocking
85 ctimer_selector_0(mclk, kMASTER_CLK_to_CTIMER0, kNONE_to_CTIMER0);
86
87 // Define clock source clock ip name kCLOCK_Ct32b0
88 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoClockIpNonBlocking ctimer_0(
89 ctimer_selector_0, kCLOCK_Ct32b0);
90
91 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-Ctimer0]
92 // inclusive-language: enable
93
94 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-LpOsc]
95
96 // Define Low-Power Oscillator
97 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoLpOsc lp_osc_clk;
98
99 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-LpOsc]
100
101 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElemDefs-AudioPll]
102
103 // Define ClkIn pin clock source
104 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoClkInNonBlocking clk_in(
105 clock_source_no_op, 19200000);
106
107 // Define audio PLL configuration with ClkIn pin as clock source
108 const clock_audio_pll_config_t kAudioPllConfig = {
109 .audio_pll_src = kCLOCK_AudioPllXtalIn, /* OSC clock */
110 .numerator =
111 0, /* Numerator of the Audio PLL fractional loop divider is 0 */
112 .denominator =
113 1000, /* Denominator of the Audio PLL fractional loop divider is 1 */
114 .audio_pll_mult = kCLOCK_AudioPllMult16 /* Divide by 16 */
115 };
116
117 // Define Audio PLL sourced by ClkIn pin clock source
118 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoAudioPllNonBlocking audio_pll(
119 clk_in, kAudioPllConfig, 18);
120
121 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElemDefs-AudioPll]
122
123 // DOCSTAG:[pw_clock_tree_mcuxpresso-examples-ClockTreeElemDefs-AudioPllBypass]
124
125 // Define Audio PLL in bypass mode sourced by FRO_DIV8 clock source
126 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoAudioPllNonBlocking
127 audio_pll_bypass(fro_div8, kCLOCK_AudioPllFroDiv8Clk);
128
129 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeElemDefs-AudioPllBypass]
130
131 PW_CONSTINIT pw::clock_tree::ClockMcuxpressoRtcNonBlocking rtc(
132 clock_source_no_op);
133
134 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeDef]
135
136 // Create the clock tree
137 pw::clock_tree::ClockTree clock_tree;
138
139 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-ClockTreeDef]
140
TEST(ClockTreeMcuxpresso,UseExample)141 TEST(ClockTreeMcuxpresso, UseExample) {
142 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-UseExample]
143
144 // Enable the low-power oscillator
145 clock_tree.Acquire(lp_osc_clk);
146
147 // Enable the i3c0
148 clock_tree.Acquire(i3c0);
149
150 // Change the i3c0_divider value
151 clock_tree.SetDividerValue(i3c0_divider, 24);
152
153 // Enable the flexcomm0 interface
154 clock_tree.Acquire(flexcomm_0);
155
156 // Disable the low-power oscillator
157 clock_tree.Release(lp_osc_clk);
158
159 // DOCSTAG: [pw_clock_tree_mcuxpresso-examples-UseExample]
160 }
161
TEST(ClockTreeMcuxpresso,AudioPll)162 TEST(ClockTreeMcuxpresso, AudioPll) {
163 // DOCSTAG:[pw_clock_tree_mcuxpresso-examples-Use-AudioPll]
164
165 // Enable audio PLL. We use AcquireWith to ensure that FRO_DIV8
166 // is enabled while enabling the audio PLL. If FRO_DIV8 wasn't enabled
167 // before, it will only be enabled while configuring the audio PLL
168 // and be disabled afterward to save power.
169 clock_tree.AcquireWith(audio_pll, fro_div8);
170
171 // Do something while audio PLL is enabled.
172
173 // Release audio PLL to save power.
174 clock_tree.Release(audio_pll);
175 // DOCSTAG:[pw_clock_tree_mcuxpresso-examples-Use-AudioPll]
176 }
177
TEST(ClockTreeMcuxpresso,AudioPllBypass)178 TEST(ClockTreeMcuxpresso, AudioPllBypass) {
179 clock_tree.Acquire(audio_pll_bypass);
180 clock_tree.Release(audio_pll_bypass);
181 }
182
TEST(ClockTreeMcuxpresso,Rtc)183 TEST(ClockTreeMcuxpresso, Rtc) {
184 clock_tree.Acquire(rtc);
185 clock_tree.Release(rtc);
186 }
187