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
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
5const clock_frg_clk_config_t g_frg0Config_BOARD_BOOTCLOCKRUN = {
6 .num = 0,
7 .sfg_clock_src = _clock_frg_clk_config::kCLOCK_FrgFroDiv4,
8 .divider = 255U,
9 .mult = 144};
10
11PW_CONSTINIT pw::clock_tree::ClockMcuxpressoFrgNonBlocking frg_0(
12 fro_div4, g_frg0Config_BOARD_BOOTCLOCKRUN);
13
14// Define clock source selector FLEXCOMM0
15PW_CONSTINIT pw::clock_tree::ClockMcuxpressoSelectorNonBlocking
16 flexcomm_selector_0(frg_0, kFRG_to_FLEXCOMM0, kNONE_to_FLEXCOMM0);
17
18// Define clock source clock ip name kCLOCK_Flexcomm0
19PW_CONSTINIT pw::clock_tree::ClockMcuxpressoClockIpNonBlocking flexcomm_0(
20 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;
Definition of clock tree:
1// Create the clock tree
2pw::clock_tree::ClockTree clock_tree;
Example usage of clock_tree
APIs:
1 // Enable the low-power oscillator
2 clock_tree.Acquire(lp_osc_clk);
3
4 // Enable the i3c0
5 clock_tree.Acquire(i3c0);
6
7 // Change the i3c0_divider value
8 clock_tree.SetDividerValue(i3c0_divider, 24);
9
10 // Enable the flexcomm0 interface
11 clock_tree.Acquire(flexcomm_0);
12
13 // Disable the low-power oscillator
14 clock_tree.Release(lp_osc_clk);
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 clock tree:
1// Create the clock tree
2pw::clock_tree::ClockTree clock_tree;
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 clock_tree.AcquireWith(audio_pll, fro_div8);
6
7 // Do something while audio PLL is enabled.
8
9 // Release audio PLL to save power.
10 clock_tree.Release(audio_pll);
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);
APIs#
ClockMcuxpressoFro#
-
class ClockMcuxpressoFro : public pw::clock_tree::ClockSource<ElementNonBlockingCannotFail>#
Class implementing an FRO clock source.
Public Functions
-
inline constexpr ClockMcuxpressoFro(clock_fro_output_en_t fro_output)#
Constructor specifying the FRO divider output to manage.
-
inline constexpr ClockMcuxpressoFro(clock_fro_output_en_t fro_output)#
ClockMcuxpressoLpOsc#
-
class ClockMcuxpressoLpOsc : public pw::clock_tree::ClockSource<ElementNonBlockingCannotFail>#
Class implementing the low power oscillator clock source.
ClockMcuxpressoMclk#
-
template<typename ElementType>
class ClockMcuxpressoMclk : public pw::clock_tree::DependentElement<ElementType># Class template implementing the MCLK IN clock source.
Template argument
ElementType
can be of classElementBlocking
orElementNonBlockingCannotFail
.Public Functions
-
inline constexpr ClockMcuxpressoMclk(ElementType &source, uint32_t frequency)#
Constructor specifying the MCLK IN clock frequency in Hz and the dependent clock tree element to enable the MCLK clock source.
-
inline constexpr ClockMcuxpressoMclk(ElementType &source, uint32_t frequency)#
ClockMcuxpressoClkIn#
-
template<typename ElementType>
class ClockMcuxpressoClkIn : public pw::clock_tree::DependentElement<ElementType># Class template implementing the CLK IN pin clock source and selecting it as an input source for OSC Clock source.
Template argument
ElementType
can be of classElementBlocking
orElementNonBlockingCannotFail
.Public Functions
-
inline constexpr ClockMcuxpressoClkIn(ElementType &source, uint32_t frequency)#
Constructor specifying the CLK IN pin clock frequency in Hz and the dependent clock tree element to enable the CLK IN pin clock source.
-
inline constexpr ClockMcuxpressoClkIn(ElementType &source, uint32_t frequency)#
ClockMcuxpressoFrg#
-
template<typename ElementType>
class ClockMcuxpressoFrg : public pw::clock_tree::DependentElement<ElementType># Class template implementing the FRG clock tree element.
Template argument
ElementType
can be of classElementBlocking
orElementNonBlockingCannotFail
.Public Functions
-
inline constexpr ClockMcuxpressoFrg(ElementType &source, const clock_frg_clk_config_t &config)#
Constructor specifying the source clock and FRG configuration.
-
inline constexpr ClockMcuxpressoFrg(ElementType &source, const clock_frg_clk_config_t &config)#
ClockMcuxpressoSelector#
-
template<typename ElementType>
class ClockMcuxpressoSelector : public pw::clock_tree::DependentElement<ElementType># Class template implementing the clock selector element.
Template argument
ElementType
can be of classElementBlocking
orElementNonBlockingCannotFail
.Public Functions
- inline constexpr ClockMcuxpressoSelector(
- ElementType &source,
- clock_attach_id_t selector_enable,
- clock_attach_id_t selector_disable,
Constructor specifying the source clock and the selector value when the selector should get enabled, and the selector value when the selector should get disabled to save power.
ClockMcuxpressoDivider#
-
template<typename ElementType>
class ClockMcuxpressoDivider : public pw::clock_tree::ClockDividerElement<ElementType># Class template implementing the clock divider element.
Template argument
ElementType
can be of classElementBlocking
orElementNonBlockingCannotFail
.Public Functions
-
inline constexpr ClockMcuxpressoDivider(ElementType &source, clock_div_name_t divider_name, uint32_t divider)#
Constructor specifying the source clock, the name of the divder and the divider setting.
-
inline constexpr ClockMcuxpressoDivider(ElementType &source, clock_div_name_t divider_name, uint32_t divider)#
ClockMcuxpressoAudioPll#
-
template<typename ElementType>
class ClockMcuxpressoAudioPll : public pw::clock_tree::DependentElement<ElementType># Class template implementing the audio pll clock element.
The Audio PLL can either operate in the enabled mode where the PLL and the phase fractional divider are enabled, or it can operate in bypass mode, where both PLL and phase fractional divider are clock gated. When the Audio PLL clock tree gets disabled, both PLL and phase fractional divider will be clock gated.
Template argument
ElementType
can be of classElementBlocking
orElementNonBlockingCannotFail
.Public Functions
-
inline constexpr ClockMcuxpressoAudioPll(ElementType &source, const clock_audio_pll_config_t &config, uint8_t audio_pfd_divider)#
Constructor specifying the configuration for the enabled Audio PLL.
-
inline constexpr ClockMcuxpressoAudioPll(ElementType &source, audio_pll_src_t bypass_source)#
Constructor to place the Audio PLL into bypass mode.
-
inline constexpr ClockMcuxpressoAudioPll(ElementType &source, const clock_audio_pll_config_t &config, uint8_t audio_pfd_divider)#
ClockMcuxpressoRtc#
-
template<typename ElementType>
class ClockMcuxpressoRtc : public pw::clock_tree::DependentElement<ElementType># Class template implementing the Rtc clock tree element.
Template argument
ElementType
can be of classElementBlocking
orElementNonBlockingCannotFail
.Public Functions
-
inline constexpr ClockMcuxpressoRtc(ElementType &source)#
Constructor specifying the dependent clock tree element to enable the Rtc clock source.
-
inline constexpr ClockMcuxpressoRtc(ElementType &source)#
ClockMcuxpressoClockIp#
-
template<typename ElementType>
class ClockMcuxpressoClockIp : public pw::clock_tree::DependentElement<ElementType># Class template implementing the
clock_ip_name_t
clocks. Managingclock_ip_name_t
clocks with the clock tree allows to save power whenFSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL
is set.Template argument
ElementType
can be of classElementBlocking
orElementNonBlockingCannotFail
.Public Functions
-
inline constexpr ClockMcuxpressoClockIp(ElementType &source, clock_ip_name_t clock)#
Constructor specifying the dependent clock tree element to enable the
clock_ip_name_t
clock source.
-
inline constexpr ClockMcuxpressoClockIp(ElementType &source, clock_ip_name_t clock)#