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

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) 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
 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 flexcomm_0(
16    frg_0, kFRG_to_FLEXCOMM0, kNONE_to_FLEXCOMM0);
flowchart LR D(fro_div_8)--> E(i3c_selector) E --> F(i3c_divider) 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
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);
flowchart LR G(mclk) --> H(ctimer_0) style G fill:#0ff,stroke:#333,stroke-width:2px style H fill:#0ff,stroke:#333,stroke-width:2px
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 ctimer_0(
7    mclk, kMASTER_CLK_to_CTIMER0, kNONE_to_CTIMER0);
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_divider
 5  clock_tree.Acquire(i3c0_divider);
 6
 7  // Change the i3c0_divider value
 8  clock_tree.SetDividerValue(i3c0_divider, 24);
 9
10  // Disable the low-power oscillator
11  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.