pw_clock_tree#
Clock tree management for embedded devices
Unstable C++17
Constinit compatible: Clock tree elements can be declared as
constinitPlatform 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:
1#include "pw_clock_tree/clock_tree.h"
2
3class UartStreamMcuxpresso {
4 public:
It could be initialized and used like this:
1 // Declare the uart clock source
2 ClockSourceUart uart_clock_source;
3 UartStreamMcuxpresso uart(&uart_clock_source);
4
5 // Initialize the uart which enables the uart clock source.
6 PW_TRY(uart.Init());
7 PW_CHECK(uart_clock_source.ref_count() > 0);
8
9 // Do something with uart
10
11 // Deinitialize the uart which disable the uart clock source.
12 uart.Deinit();
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.
The 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:
Acquire()Release()
The Element abstract class implements basic reference counting methods
IncRef() and 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 Element:
ElementBlockingfor clock tree elements that might block when acquired or released. Acquiring or releasing such a clock tree element might fail.ElementNonBlockingCannotFailfor clock tree elements that will not block when acquired or released. Acquiring or releasing such a clock tree element will always succeed.ElementNonBlockingMightFailfor clock tree elements that will not block when acquired or released. Acquiring or releasing such a clock tree element might fail.
ElementNonBlockingCannotFail and ElementsNonBlockingMightFail elements can
be acquired from an interrupt context.
All classes representing a clock tree element should be implemented as a template and accept
ElementBlocking, ElementNonBlockingCannotFail or
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 ElementBlocking or ElementNonBlockingCannotFail /
ElementNonBlockingMightFail, respectively.
For convenience, OptionalElement represents a null-safe pointer to an
:Element. This allows drivers to easily support an optional Element
pointer argument.
If it does not point to an Element, then its Acquire() and Release() methods
do nothing and return pw::OkStatus().
Synchronization#
Element objects are individually internally synchronized.
ElementBlockingobjects use a Mutex.ElementNonBlockingCannotFailandElementNonBlockingMightFailobjects use an InterruptSpinLock.