Examples#
pw_clock_tree: Clock tree management for embedded devices
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.
1#include "pw_clock_tree/clock_tree.h"
2
3class UartStreamMcuxpresso {
4 public:
5 // Device constructor that optionally accepts `clock_tree_element` to manage
6 // clock lifecycle.
7 constexpr UartStreamMcuxpresso(pw::clock_tree::ElementNonBlockingCannotFail*
8 clock_tree_element = nullptr)
9 : clock_tree_element_(clock_tree_element) {}
10
11 pw::Status Init() {
12 // Acquire reference to clock before initializing device.
13 PW_TRY(clock_tree_element_.Acquire());
14 pw::Status status = USART_RTOS_Init();
15 if (!status.ok()) {
16 // Failed to initialize device, release the acquired clock.
17 clock_tree_element_.Release().IgnoreError();
18 }
19 return status;
20 }
21
22 void Deinit() {
23 // Deinitialize the device before we can release the reference
24 // to the clock.
25 USART_RTOS_Deinit();
26 clock_tree_element_.Release().IgnoreError();
27 }
28
29 private:
30 pw::clock_tree::OptionalElement clock_tree_element_;
31};
Definition and use of clock tree elements#
For the example below we define a clock tree with a clock source clock_a
which is an input into divider clock_divider_d
.
Derived ClockSourceExample
class template that overrides
DoEnable()
and DoDisable()
methods.
1/// Class template implementing a clock source.
2///
3/// Template argument `ElementType` can be of class `ElementBlocking`,
4/// `ElementNonBlockingCannotFail` or
5/// `ElementNonBlockingMightFail.`
6template <typename ElementType>
7class ClockSourceExample : public pw::clock_tree::ClockSource<ElementType> {
8 private:
9 pw::Status DoEnable() final { return EnableClock(); }
10
11 pw::Status DoDisable() final { return DisableClock(); }
12};
13using ClockSourceExampleNonBlocking =
14 ClockSourceExample<pw::clock_tree::ElementNonBlockingCannotFail>;
Derived ClockDividerExample
class template that overrides
DoEnable()
method.
1/// Class template implementing a clock divider.
2///
3/// Template argument `ElementType` can be of class `ElementBlocking`,
4/// `ElementNonBlockingCannotFail` or
5/// `ElementNonBlockingMightFail.`
6template <typename ElementType>
7class ClockDividerExample
8 : public pw::clock_tree::ClockDividerElement<ElementType> {
9 public:
10 constexpr ClockDividerExample(ElementType& source,
11 uint32_t divider_name,
12 uint32_t divider)
13 : pw::clock_tree::ClockDividerElement<ElementType>(source, divider),
14 divider_name_(divider_name) {}
15
16 private:
17 pw::Status DoEnable() final {
18 return EnableClockDivider(divider_name_, this->divider());
19 }
20
21 uint32_t divider_name_;
22};
23using ClockDividerExampleNonBlocking =
24 ClockDividerExample<pw::clock_tree::ElementNonBlockingCannotFail>;
Declare the clock tree elements.
clock_divider_d
depends on clock_a
.
1 // Define the clock tree
2 ClockSourceExampleNonBlocking clock_a;
3
4 const uint32_t kDividerId = 12;
5 const uint32_t kDividerValue1 = 42;
6 // clock_divider_d depends on clock_a.
7 ClockDividerExampleNonBlocking clock_divider_d(
8 clock_a, kDividerId, kDividerValue1);
Acquire a reference to clock_divider_d
, 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_divider_d
gets enabled.
1 // Acquire a reference to clock_divider_d, which will enable clock_divider_d
2 // and its dependent clock_a.
3 clock_divider_d.Acquire();
Set the clock divider value while the clock_divider_d
is enabled.
1 // Change the divider value for clock_divider_d.
2 const uint32_t kDividerValue2 = 21;
3 clock_divider_d.SetDivider(kDividerValue2);
Release the reference to the clock_divider_d
, which will disable clock_divider_d
before
it releases its reference to clock_b
that gets disabled afterward. At this point all clock
tree elements are disabled.
1 // Release reference to clock_divider_d, which will disable clock_divider_d,
2 // and clock_a.
3 clock_divider_d.Release();
4 // All clock tree elements are disabled now.