pw_clock_tree#

Clock tree management for embedded devices

Unstable C++17

  • 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:

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();
Quickstart

Examples that show how to integrate a clock tree into a device driver, and how to define and use platform specific clock tree elements.

Reference

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.

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:

  • ElementBlocking for clock tree elements that might block when acquired or released. Acquiring or releasing such a clock tree element might fail.

  • ElementNonBlockingCannotFail for clock tree elements that will not block when acquired or released. Acquiring or releasing such a clock tree element will always succeed.

  • ElementNonBlockingMightFail for 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.

  • ElementBlocking objects use a Mutex.

  • ElementNonBlockingCannotFail and ElementNonBlockingMightFail objects use an InterruptSpinLock.