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:

flowchart LR A(fro_div_4) -->B(frg_0) B-->C(flexcomm_selector_0) C-->D(flexcomm_0) style A fill:#0f0,stroke:#333,stroke-width:2px style B fill:#0f0,stroke:#333,stroke-width:2px style C fill:#0f0,stroke:#333,stroke-width:2px style D fill:#0f0,stroke:#333,stroke-width:2px

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);
flowchart LR D(fro_div_8)--> E(i3c0_selector) E --> F(i3c0_divider) F --> G(i3c0) style D fill:#f0f,stroke:#333,stroke-width:2px style E fill:#f0f,stroke:#333,stroke-width:2px style F fill:#f0f,stroke:#333,stroke-width:2px style G fill:#f0f,stroke:#333,stroke-width:2px

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);
flowchart LR G(mclk) --> H(ctimer_selector_0) H --> I(ctimer_0) style G fill:#0ff,stroke:#333,stroke-width:2px style H fill:#0ff,stroke:#333,stroke-width:2px style I fill:#0ff,stroke:#333,stroke-width:2px

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);
flowchart LR I(lposc) style I fill:#ff0,stroke:#333,stroke-width:2px
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.

flowchart LR subgraph PLL [Audio PLL logic] B(audio_pll_selctor) -.-> C(PLL) C -.-> D(Phase Fraction divider) end A(clk_in) -->|as osc_clk| PLL PLL --> E(audio_pfd_bypass_selector) style A fill:#f0f,stroke:#333,stroke-width:2px style E fill:#f0f,stroke:#333,stroke-width:2px

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.

flowchart LR A(fro_div_8) --> B(audio_pfd_bypass_selector) style A fill:#0ff,stroke:#333,stroke-width:2px style B fill:#0ff,stroke:#333,stroke-width:2px
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.

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 class ElementBlocking or ElementNonBlockingCannotFail.

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.

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 class ElementBlocking or ElementNonBlockingCannotFail.

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.

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 class ElementBlocking or ElementNonBlockingCannotFail.

Public Functions

inline constexpr ClockMcuxpressoFrg(ElementType &source, const clock_frg_clk_config_t &config)#

Constructor specifying the source clock and FRG configuration.

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 class ElementBlocking or ElementNonBlockingCannotFail.

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 class ElementBlocking or ElementNonBlockingCannotFail.

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.

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 class ElementBlocking or ElementNonBlockingCannotFail.

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.

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 class ElementBlocking or ElementNonBlockingCannotFail.

Public Functions

inline constexpr ClockMcuxpressoRtc(ElementType &source)#

Constructor specifying the dependent clock tree element to enable the Rtc clock source.

ClockMcuxpressoClockIp#

template<typename ElementType>
class ClockMcuxpressoClockIp : public pw::clock_tree::DependentElement<ElementType>#

Class template implementing the clock_ip_name_t clocks. Managing clock_ip_name_t clocks with the clock tree allows to save power when FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL is set.

Template argument ElementType can be of class ElementBlocking or ElementNonBlockingCannotFail.

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.