pw_clock_tree_mcuxpresso#
NXP MCUXpresso SDK implementation for pw_clock_tree
Unstable C++17
pw_clock_tree_mcuxpresso
implements the pw_clock_tree
interface using the
NXP MCUXpresso SDK. It provides class implementations for the following clock tree elements
that can be directly instantiated:
Free-Running Oscillator (FRO)
32 kHz RTC Oscillator
Low-power Oscillator
Master Clock
External Clock Input as clock source for SYSOSCBYPASS clock selector to generate OSC_CLK
Fractional Rate Generator (FRG) for Flexcomm Interfaces
Clock Source Selector
Clock Divider
Audio PLL
System PLL
RTC
ClockIp
Other clock tree components such as PLLs can be instantiated by deriving custom class implementations from the abstract class DependentElement and overwriting DoEnable and DoDisable methods.
When enabling clock tree elements sourced from the audio PLL or the SYS PLL it is necessary to use the AcquireWith method.
Examples#
End-to-end Mcuxpresso clock tree example#
Definition of clock tree elements:
Please note that the clock tree element flexcomm_0
is only required if the
SDK is compiled with the define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL
set,
and that the connection between flexcomm_selector_0
and flexcomm_0
represents only a logical dependency connection between the two clock tree
elements. The flexcomm_0
ClockMcuxpressoClockIp gates the register access to the
Flexcomm 0
IP block, but it doesn’t gate the Flexcomm 0
clock source
itself. Nevertheless, to use Flexcomm 0
the Flexcomm 0
IP block and
Flexcomm 0
clock source need to be enabled, hence we established the
dependency between flexcomm_selector_0
and flexcomm_0
, so that
enabling flexcomm_0
enabled the Flexcomm 0
IP block and clock source.
1// Define FRO_DIV_4 clock source
2PW_CONSTINIT pw::clock_tree::ClockMcuxpressoFro fro_div4(kCLOCK_FroDiv4OutEn);
3
4// Define FRG0 configuration
5constexpr clock_frg_clk_config_t kFrg0Config = {
6 .num = 0,
7 .sfg_clock_src = _clock_frg_clk_config::kCLOCK_FrgFroDiv4,
8 .divider = 255U,
9 .mult = 144,
10};
11
12PW_CONSTINIT pw::clock_tree::ClockMcuxpressoFrgNonBlocking frg_0(fro_div4,
13 kFrg0Config);
14
15// Define clock source selector FLEXCOMM0
16PW_CONSTINIT pw::clock_tree::ClockMcuxpressoSelectorNonBlocking
17 flexcomm_selector_0(frg_0, kFRG_to_FLEXCOMM0, kNONE_to_FLEXCOMM0);
18
19// Define clock source clock ip name kCLOCK_Flexcomm0
20PW_CONSTINIT pw::clock_tree::ClockMcuxpressoClockIpNonBlocking flexcomm_0(
21 flexcomm_selector_0, kCLOCK_Flexcomm0);
Please note that the clock tree element i3c0
is only required if the SDK is
compiled with the define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL
set, and that
the connection between i3c0_selector
and i3c0
represents only a logical
dependency connection between the two clock tree elements. The i3c0
ClockMcuxpressoClockIp gates
the register access to the I3C
IP block, but it doesn’t gate the I3C
clock source itself. Nevertheless, to use I3C
the I3C
IP block and
I3C
clock source need to be enabled, hence we established the dependency
between i3c0_selector
and i3c0
, so that enabling i3c0
enabled the
I3C
IP block and clock source.
1// Define FRO_DIV8 clock source
2PW_CONSTINIT pw::clock_tree::ClockMcuxpressoFro fro_div8(kCLOCK_FroDiv8OutEn);
1// Define clock source selector I3C01FCLKSEL
2PW_CONSTINIT pw::clock_tree::ClockMcuxpressoSelectorNonBlocking i3c0_selector(
3 fro_div8, kFRO_DIV8_to_I3C_CLK, kNONE_to_I3C_CLK);
4
5// Define clock divider I3C01FCLKDIV
6PW_CONSTINIT pw::clock_tree::ClockMcuxpressoDividerNonBlocking i3c0_divider(
7 i3c0_selector, kCLOCK_DivI3cClk, 12);
8
9// Define clock source clock ip name kCLOCK_I3c0
10PW_CONSTINIT pw::clock_tree::ClockMcuxpressoClockIpNonBlocking i3c0(
11 i3c0_divider, kCLOCK_I3c0);
Please note that the clock tree element ctimer_0
is only required if the
SDK is compiled with the define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL
set,
and that the connection between ctimer_selector_0
and ctimer_0
represents only a logical dependency connection between the two clock tree
elements. The ctimer_0
ClockMcuxpressoClockIp gates the register access to the
CTimer 0
IP block, but it doesn’t gate the CTimer 0
clock source
itself. Nevertheless, to use CTimer 0
the CTimer 0
IP block and
CTimer 0
clock source need to be enabled, hence we established the
dependency between ctimer_selector_0
and ctimer_0
, so that enabling
ctimer_0
enabled the CTimer 0
IP block and clock source.
1// Need to define `ClockSourceNoOp` clock tree element to satisfy dependency for
2// `ClockMcuxpressoMclk` or `ClockMcuxpressoClkIn` class.
3PW_CONSTINIT pw::clock_tree::ClockSourceNoOp clock_source_no_op;
1// Define Master clock
2PW_CONSTINIT pw::clock_tree::ClockMcuxpressoMclkNonBlocking mclk(
3 clock_source_no_op, 19200000);
4
5// Define clock selector CTIMER0
6PW_CONSTINIT pw::clock_tree::ClockMcuxpressoSelectorNonBlocking
7 ctimer_selector_0(mclk, kMASTER_CLK_to_CTIMER0, kNONE_to_CTIMER0);
8
9// Define clock source clock ip name kCLOCK_Ct32b0
10PW_CONSTINIT pw::clock_tree::ClockMcuxpressoClockIpNonBlocking ctimer_0(
11 ctimer_selector_0, kCLOCK_Ct32b0);
1// Define Low-Power Oscillator
2PW_CONSTINIT pw::clock_tree::ClockMcuxpressoLpOsc lp_osc_clk;
Example usage of clock_tree
APIs:
1 // Enable the low-power oscillator
2 lp_osc_clk.Acquire();
3
4 // Enable the i3c0
5 i3c0.Acquire();
6
7 // Change the i3c0_divider value
8 i3c0_divider.SetDivider(24);
9
10 // Enable the flexcomm0 interface
11 flexcomm_0.Acquire();
12
13 // Disable the low-power oscillator
14 lp_osc_clk.Release();
Audio PLL examples#
The ClockMcuxpressoAudioPll can be configured in two different ways, either it can be configured where the audio PLL gets enabled, or it can be configured in bypass mode.
The first example shows where ClockMcuxpressoAudioPll enables the audio PLL and uses the
ClkIn pin clock source as OSC clock source that feeds into the audio PLL logic.
Since the audio PLL requires that the FRO_DIV8
clock source is enabled when
enabling the audio PLL, the AcquireWith needs to be used that ensures that the
FRO_DIV8
clock is enabled when enabling the audio PLL.
Definition of audio PLL related clock tree elements:
1// Need to define `ClockSourceNoOp` clock tree element to satisfy dependency for
2// `ClockMcuxpressoMclk` or `ClockMcuxpressoClkIn` class.
3PW_CONSTINIT pw::clock_tree::ClockSourceNoOp clock_source_no_op;
1// Define ClkIn pin clock source
2PW_CONSTINIT pw::clock_tree::ClockMcuxpressoClkInNonBlocking clk_in(
3 clock_source_no_op, 19200000);
4
5// Define audio PLL configuration with ClkIn pin as clock source
6const clock_audio_pll_config_t kAudioPllConfig = {
7 .audio_pll_src = kCLOCK_AudioPllXtalIn, /* OSC clock */
8 .numerator =
9 0, /* Numerator of the Audio PLL fractional loop divider is 0 */
10 .denominator =
11 1000, /* Denominator of the Audio PLL fractional loop divider is 1 */
12 .audio_pll_mult = kCLOCK_AudioPllMult16 /* Divide by 16 */
13};
14
15// Define Audio PLL sourced by ClkIn pin clock source
16PW_CONSTINIT pw::clock_tree::ClockMcuxpressoAudioPllNonBlocking audio_pll(
17 clk_in, kAudioPllConfig, 18);
Definition of FRO_DIV8
clock tree element:
1// Define FRO_DIV8 clock source
2PW_CONSTINIT pw::clock_tree::ClockMcuxpressoFro fro_div8(kCLOCK_FroDiv8OutEn);
Audio PLL clock tree element gets enabled and disabled. We use
AcquireWith to ensure that
FRO_DIV8
is enabled prior to configuring the audio PLL to a
non-FRO_DIV8
clock source.
1 // Enable audio PLL. We use AcquireWith to ensure that FRO_DIV8
2 // is enabled while enabling the audio PLL. If FRO_DIV8 wasn't enabled
3 // before, it will only be enabled while configuring the audio PLL
4 // and be disabled afterward to save power.
5 PW_TEST_EXPECT_OK(audio_pll.AcquireWith(fro_div8));
6
7 // Do something while audio PLL is enabled.
8
9 // Release audio PLL to save power.
10 audio_pll.Release();
The second example shows where ClockMcuxpressoAudioPll bypasses the audio PLL and
uses FRO_DIV8 pin
clock source.
1// Define Audio PLL in bypass mode sourced by FRO_DIV8 clock source
2PW_CONSTINIT pw::clock_tree::ClockMcuxpressoAudioPllNonBlocking
3 audio_pll_bypass(fro_div8, kCLOCK_AudioPllFroDiv8Clk);
API reference#
Moved: pw_clock_tree_mcuxpresso