blob: fce416d50179a9734f3dd2ba741df5d99a742e67 [file] [log] [blame]
.. _module-pw_clock_tree-examples:
--------
Examples
--------
.. pigweed-module-subpage::
:name: pw_clock_tree
.. grid:: 2
.. grid-item-card:: :octicon:`code-square` Integration into device driver
:link: module-pw_clock_tree-example-device_driver
:link-type: ref
:class-item: sales-pitch-cta-primary
Example that shows how to integrate the clock tree functionality
into a device driver.
.. grid-item-card:: :octicon:`code-square` Clock tree usage
:link: module-pw_clock_tree-example-clock_tree_usage
:link-type: ref
:class-item: sales-pitch-cta-secondary
Example that shows how to define platform specific clock tree elements
and how to interact with them to manage clocks of an embedded system.
.. _module-pw_clock_tree-example-device_driver:
Clock tree integration into device drivers
==========================================
The example below shows how the clock tree functionality can get integrated into a new
device driver that requires that a clock tree abstraction is present in the system.
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-IntegrationIntoDeviceDriversClassDef]
:end-before: [pw_clock_tree-examples-IntegrationIntoDeviceDriversClassDef]
.. _module-pw_clock_tree-example-clock_tree_usage:
Definition and use of clock tree elements
=========================================
For the example below we use a clock tree with two clock sources ``clock_a`` and ``clock_b``.
``clock_a`` can be selected as an input source by ``clock_selector_c``, and ``clock_b`` is an input into
divider ``clock_divider_d``, which can be selected as an alternative input source by
``clock_selector_c``.
.. mermaid::
flowchart LR
A(clock_a) -..-> C(clock_selector_c)
B(clock_b)--> D(clock_divider_d)
D -..-> C
.. cpp:namespace-push:: pw::clock_tree::Element
Derived ``ClockSourceExample`` class template that overrides
:cpp:func:`DoEnable` and :cpp:func:`DoDisable` methods.
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-ClockSourceExampleDef]
:end-before: [pw_clock_tree-examples-ClockSourceExampleDef]
Derived ``ClockDividerExample`` class template that overrides
:cpp:func:`DoEnable` method.
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-ClockDividerExampleDef]
:end-before: [pw_clock_tree-examples-ClockDividerExampleDef]
Derived ``ClockSelectorExample`` class template that overrides
:cpp:func:`DoEnable` and :cpp:func:`DoDisable` methods,
and defines the ``SetSource`` method to allow the clock selector to change from one dependent source to
another source. If the dependent source of a clock selector doesn't change at any point, one doesn't
need to implement a method like ``SetSource``.
.. cpp:namespace-pop::
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-ClockSelectorExampleDef]
:end-before: [pw_clock_tree-examples-ClockSelectorExampleDef]
.. cpp:namespace-push:: pw::clock_tree
Derived ``ClockTreeSetSource`` class that provides ``SetSource`` method to allow to change the
source a clock selector depends on. If ``ClockSelectorExample`` wouldn't provide the ``SetSource``
method, one could use the :cpp:class:`ClockTree` class directly in the example below.
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-ClockTreeSetSourcesExampleDef]
:end-before: [pw_clock_tree-examples-ClockTreeSetSourcesExampleDef]
Declare the :cpp:class:`ClockTree` class object.
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-ClockTreeDec]
:end-before: [pw_clock_tree-examples-ClockTreeDec]
Declare the clock tree elements.
``clock_selector_c`` depends on ``clock_a``, and ``clock_divider_d`` depends on ``clock_b``.
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-ClockTreeElementsDec]
:end-before: [pw_clock_tree-examples-ClockTreeElementsDec]
Acquire a reference to ``clock_selector_c``, which will acquire a reference to the dependent source
``clock_a``. When the reference to ``clock_a`` gets acquired, ``clock_a`` gets enabled. Once the
reference to ``clock_a`` has been acquired and it is enabled, ``clock_selector_c`` gets enabled.
.. mermaid::
flowchart LR
A(clock_A) -->C(clock_selector_c)
B(clock_B)--> D(clock_divider_d)
D -..-> C
style A fill:#0f0,stroke:#333,stroke-width:4px
style C fill:#0f0,stroke:#333,stroke-width:4px
style B fill:#f00,stroke:#333,stroke-width:4px
style D fill:#f00,stroke:#333,stroke-width:4px
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-AcquireClockSelectorC]
:end-before: [pw_clock_tree-examples-AcquireClockSelectorC]
Change the dependent source of ``clock_selector_c`` from ``clock_a`` to ``clock_divider_d`` while
the ``clock_selector_c`` is enabled. Before ``clock_divider_d`` can be configured as the new
dependent source, a reference to ``clock_divider_d`` will need to get acquired, which will acquire
a reference to ``clock_b`` and enable ``clock_b`` before ``clock_divider_d`` gets enabled.
Once the dependent source has been changed from ``clock_a`` to ``clock_divider_d``, the reference to
``clock_a`` will get released, which will disable ``clock_a``.
.. mermaid::
flowchart LR
A(clock_A) -..->C(clock_selector_c)
B(clock_B)--> D(clock_divider_d)
D --> C
style A fill:#f00,stroke:#333,stroke-width:4px
style C fill:#0f0,stroke:#333,stroke-width:4px
style B fill:#0f0,stroke:#333,stroke-width:4px
style D fill:#0f0,stroke:#333,stroke-width:4px
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-ChangeClockSelectorCDependentSource]
:end-before: [pw_clock_tree-examples-ChangeClockSelectorCDependentSource]
Set the clock divider value while the ``clock_divider_d`` is enabled.
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-SetClockDividerDValue]
:end-before: [pw_clock_tree-examples-SetClockDividerDValue]
Release the reference to the ``clock_selector_c``, which will disable ``clock_selector_c``, and
then release the reference to ``clock_divider_d``. Then ``clock_divider_d`` will get disabled before
it releases its reference to ``clock_b`` that gets disabled afterward. At this point all clock
tree elements are disabled.
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-ReleaseClockSelectorC]
:end-before: [pw_clock_tree-examples-ReleaseClockSelectorC]