| .. _module-pw_clock_tree_mcuxpresso: |
| |
| =========================== |
| pw_clock_tree_mcuxpresso |
| =========================== |
| .. pigweed-module:: |
| :name: pw_clock_tree_mcuxpresso |
| |
| ``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: |
| |
| .. inclusive-language: disable |
| |
| * 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 |
| * Synchronized Clock Source Selector |
| * Clock Divider |
| * Audio PLL |
| * System PLL |
| * RTC |
| * ClockIp |
| |
| .. inclusive-language: enable |
| |
| .. cpp:namespace-push:: pw::clock_tree::Element |
| |
| Other clock tree components such as PLLs can be instantiated by deriving custom |
| class implementations from the abstract class :cc:`DependentElement |
| <pw::clock_tree::DependentElement>` and overwriting :cc:`DoEnable |
| <pw::clock_tree::Element::DoEnable>` and :cc:`DoDisable |
| <pw::clock_tree::Element::DoDisable>` methods. |
| |
| .. cpp:namespace-pop:: |
| |
| .. cpp:namespace-push:: pw::clock_tree::Element |
| |
| When enabling clock tree elements sourced from the audio PLL or the SYS PLL it |
| is necessary to use the :cc:`AcquireWith |
| <pw::clock_tree::Element::AcquireWith>` method. |
| |
| .. cpp:namespace-pop:: |
| |
| Examples |
| ======== |
| |
| ---------------------------------------- |
| End-to-end Mcuxpresso clock tree example |
| ---------------------------------------- |
| |
| Definition of clock tree elements: |
| |
| .. mermaid:: |
| |
| flowchart LR |
| A(fro_div_4) -->B(frg_0) |
| B-->C(flexcomm_selector_0) |
| C-->D(flexcomm_0) |
| style A fill:#848,stroke:#333,stroke-width:2px |
| style B fill:#848,stroke:#333,stroke-width:2px |
| style C fill:#848,stroke:#333,stroke-width:2px |
| style D fill:#848,stroke:#333,stroke-width:2px |
| |
| .. cpp:namespace-push:: pw::clock_tree |
| |
| 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`` :cc:`ClockMcuxpressoClockIp |
| <pw::clock_tree::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. |
| |
| .. cpp:namespace-pop:: |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-Flexcomm0] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-Flexcomm0] |
| |
| .. mermaid:: |
| |
| 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 |
| |
| .. cpp:namespace-push:: pw::clock_tree |
| |
| 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`` |
| :cc:`ClockMcuxpressoClockIp <pw::clock_tree::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. |
| |
| .. cpp:namespace-pop:: |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-fro_div8] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-fro_div8] |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-i3c0] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-i3c0] |
| |
| .. mermaid:: |
| |
| flowchart LR |
| G(mclk) --> H(ctimer_selector_0) |
| H --> I(ctimer_0) |
| style G fill:#a00,stroke:#333,stroke-width:2px |
| style H fill:#a00,stroke:#333,stroke-width:2px |
| style I fill:#a00,stroke:#333,stroke-width:2px |
| |
| .. cpp:namespace-push:: pw::clock_tree |
| |
| 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`` :cc:`ClockMcuxpressoClockIp |
| <pw::clock_tree::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. |
| |
| .. cpp:namespace-pop:: |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClkTreeElemDefs-ClockSourceNoOpB] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClkTreeElemDefs-ClockSourceNoOpB] |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-Ctimer0] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-Ctimer0] |
| |
| .. mermaid:: |
| |
| flowchart LR |
| G(mclk) --> H(ctimer_sync_selector_1) |
| H --> I(ctimer_1) |
| J(fro_div1) --> H(ctimer_sync_selector_1) |
| style G fill:#f00,stroke:#333,stroke-width:2px |
| style H fill:#f00,stroke:#333,stroke-width:2px |
| style I fill:#f00,stroke:#333,stroke-width:2px |
| style J fill:#f00,stroke:#333,stroke-width:2px |
| |
| .. cpp:namespace-push:: pw::clock_tree |
| |
| The difference between ``ctimer_1`` and ``ctimer_0`` is that |
| ``ctimer_1`` can also be sourced by the non-blocking ``FRO_DIV1`` clock |
| source. The clock source can be changed between the blocking `mclk` and |
| the non-blocking ``FRO_DIV1`` while the ``ctimer_1`` is running or while |
| it is disabled. |
| |
| .. cpp:namespace-pop:: |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClkTreeElemDefs-ClockSourceNoOpB] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClkTreeElemDefs-ClockSourceNoOpB] |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-Ctimer1] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-Ctimer1] |
| |
| .. mermaid:: |
| |
| flowchart LR |
| I(lposc) |
| style I fill:#f60,stroke:#333,stroke-width:2px |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-LpOsc] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-LpOsc] |
| |
| Example usage of ``clock_tree`` APIs: |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-UseExample] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-UseExample] |
| |
| ------------------ |
| Audio PLL examples |
| ------------------ |
| |
| .. cpp:namespace-push:: pw::clock_tree::Element |
| |
| The :cc:`ClockMcuxpressoAudioPll |
| <pw::clock_tree::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 :cc:`ClockMcuxpressoAudioPll |
| <pw::clock_tree::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 :cc:`AcquireWith |
| <pw::clock_tree::Element::AcquireWith>` needs to be used that ensures that the |
| ``FRO_DIV8`` clock is enabled when enabling the audio PLL. |
| |
| .. mermaid:: |
| |
| 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 audio PLL related clock tree elements: |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClkTreeElemDefs-ClockSourceNoOp] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClkTreeElemDefs-ClockSourceNoOp] |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClockTreeElemDefs-AudioPll] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClockTreeElemDefs-AudioPll] |
| |
| Definition of ``FRO_DIV8`` clock tree element: |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-fro_div8] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClockTreeElementDefs-fro_div8] |
| |
| Audio PLL clock tree element gets enabled and disabled. We use |
| :cc:`AcquireWith <pw::clock_tree::Element::AcquireWith>` to ensure that |
| ``FRO_DIV8`` is enabled prior to configuring the audio PLL to a |
| non-``FRO_DIV8`` clock source. |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-Use-AudioPll] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-Use-AudioPll] |
| |
| The second example shows where :cc:`ClockMcuxpressoAudioPll |
| <pw::clock_tree::ClockMcuxpressoAudioPll>` bypasses the audio PLL and |
| uses ``FRO_DIV8 pin`` clock source. |
| |
| .. cpp:namespace-pop:: |
| |
| .. mermaid:: |
| |
| flowchart LR |
| A(fro_div_8) --> B(audio_pfd_bypass_selector) |
| style A fill:#560,stroke:#333,stroke-width:2px |
| style B fill:#560,stroke:#333,stroke-width:2px |
| |
| .. literalinclude:: examples.cc |
| :language: cpp |
| :linenos: |
| :start-after: [pw_clock_tree_mcuxpresso-examples-ClockTreeElemDefs-AudioPllBypass] |
| :end-before: [pw_clock_tree_mcuxpresso-examples-ClockTreeElemDefs-AudioPllBypass] |
| |
| API reference |
| ============= |
| Moved: :cc:`pw_clock_tree_mcuxpresso` |