blob: 589c8c2e7d889bbb41a88b8efbd9d42628b79fa5 [file]
.. _module-pw_clock_tree:
================
pw_clock_tree
================
.. pigweed-module::
:name: pw_clock_tree
- **Constinit compatible**: Clock tree elements can be declared as ``constinit``
- **Platform independent**: Clock tree management sits above the platform layer
- **Handles complex topologies**: Clock tree elements can be used to model
complex clock tree topologies
``pw_clock_tree`` provides class definitions to implement a platform
specific clock tree management solution. By passing the clock tree element
that clocks a particular device to the corresponding device driver, the
device driver can ensure that the clock is only enabled when required to
maximize power savings.
For example the clock tree functionality could be integrated into a uart device driver
like this:
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-IntegrationIntoDeviceDriversClassDef]
:end-before: // Device constructor that optionally accepts
It could be initialized and used like this:
.. literalinclude:: examples.cc
:language: cpp
:linenos:
:start-after: [pw_clock_tree-examples-IntegrationIntoDeviceDriversUsage]
:end-before: [pw_clock_tree-examples-IntegrationIntoDeviceDriversUsage]
.. grid:: 2
.. grid-item-card:: :octicon:`rocket` Quickstart
:link: module-pw_clock_tree-examples
:link-type: ref
:class-item: sales-pitch-cta-primary
Examples that show how to integrate a clock tree into a device driver,
and how to define and use platform specific clock tree elements.
.. grid-item-card:: :octicon:`code-square` Reference
:link: ../api/cc/group__pw__clock__tree.html
:link-type: url
:class-item: sales-pitch-cta-secondary
API references for ``pw::clock_tree::Element``,
``pw::clock_tree::DependentElement``, and more.
--------
Overview
--------
Pigweed's clock tree module provides the ability to represent the clock tree of an embedded device,
and to manage the individual clocks and clock tree elements.
.. cpp:namespace-push:: pw::clock_tree::Element
The :cpp:class:`Element` abstract base class is the root of the pw_clock_tree class hierarchy, and
represents a single node in the clock tree.
The public (consumer) API includes two basic methods which apply to all clock tree elements:
* :cpp:func:`Acquire`
* :cpp:func:`Release`
The :cpp:class:`Element` abstract class implements basic reference counting methods
:cpp:func:`IncRef` and :cpp:func:`DecRef`, but requires derived classes to use the reference
counting methods to properly acquire and release references to clock tree elements.
Three derived abstract classes are defined for :cpp:class:`Element`:
.. cpp:namespace-pop::
.. cpp:namespace-push:: pw::clock_tree
* :cpp:class:`ElementBlocking` for clock tree elements that might block when acquired or released.
Acquiring or releasing such a clock tree element might fail.
* :cpp:class:`ElementNonBlockingCannotFail` for clock tree elements that will not block when
acquired or released. Acquiring or releasing such a clock tree element will always succeed.
* :cpp:class:`ElementNonBlockingMightFail` for clock tree elements that will not block when
acquired or released. Acquiring or releasing such a clock tree element might fail.
:cpp:class:`ElementNonBlockingCannotFail` and :cpp:class:`ElementsNonBlockingMightFail` elements can
be acquired from an interrupt context.
All classes representing a clock tree element should be implemented as a template and accept
:cpp:class:`ElementBlocking`, :cpp:class:`ElementNonBlockingCannotFail` or
:cpp:class:`ElementNonBlockingMightFail` as a template argument. Only if it is known at compile time
that a clock tree element can only be either blocking or non-blocking, one can directly derive the
class from :cpp:class:`ElementBlocking` or :cpp:class:`ElementNonBlockingCannotFail` /
:cpp:class:`ElementNonBlockingMightFail`, respectively.
.. cpp:namespace-pop::
.. cpp:namespace-push:: pw::clock_tree::OptionalElement
For convenience, :cpp:class:`OptionalElement` represents a null-safe pointer to an
::cpp:class:`Element`. This allows drivers to easily support an optional :cpp:class:`Element`
pointer argument.
If it does not point to an `Element`, then its :cpp:func:`Acquire` and :cpp:func:`Release` methods
do nothing and return ``pw::OkStatus()``.
.. cpp:namespace-pop::
---------------
Synchronization
---------------
.. cpp:namespace-push:: pw::clock_tree
:cpp:class:`Element` objects are individually internally synchronized.
* :cpp:class:`ElementBlocking` objects use a `Mutex`.
* :cpp:class:`ElementNonBlockingCannotFail` and :cpp:class:`ElementNonBlockingMightFail` objects use
an `InterruptSpinLock`.
.. cpp:namespace-pop::
----------------------
Dependency enforcement
----------------------
.. cpp:namespace-push:: pw::clock_tree
The :cpp:class:`DependentElement` class enforces the dependency rules
between the :cpp:class:`ElementBlocking`,
:cpp:class:`ElementNonBlockingCannotFail`,
:cpp:class:`ElementNonBlockingMightFail` and generic
:cpp:class:`Element` classes.
:cpp:class:`ElementBlocking` can depend on an object from any class,
while :cpp:class:`ElementNonBlockingMightFail` can only depend on
objects of classes :cpp:class:`ElementNonBlockingMightFail` and
:cpp:class:`ElementNonBlockingCannotFail`.
:cpp:class:`ElementNonBlockingCannotFail` can only depend on objects of
class :cpp:class:`ElementNonBlockingCannotFail`.
When one wants to pass a specific object as a source object of class
:cpp:class:`Element`, the dependent object must be of class
:cpp:class:`ElementBlocking` to satisfy the dependency rules.
.. cpp:namespace-pop::
.. toctree::
:hidden:
:maxdepth: 1
examples
implementations