20#include "pw_assert/assert.h"
21#include "pw_status/status.h"
22#include "pw_status/try.h"
23#include "pw_sync/interrupt_spin_lock.h"
24#include "pw_sync/mutex.h"
26namespace pw::clock_tree {
88 uint32_t
IncRef() {
return ++ref_count_; }
91 uint32_t
DecRef() {
return --ref_count_; }
104 uint32_t ref_count_ = 0;
107 const bool may_block_;
110 template <
typename ElementType>
146template <
typename ElementType>
153 if (this->IncRef() > 1) {
159 Status status = this->DoEnable();
170 if (this->DecRef() > 0) {
176 Status status = this->DoDisable();
207template <
typename ElementType>
230 if (this->ref_count() == 0) {
231 source_ = &new_source;
236 if (!permit_change_if_in_use) {
237 return Status::FailedPrecondition();
240 ElementType* old_source = source_;
243 PW_TRY(new_source.Acquire());
246 if (
Status status = this->DoDisable(); !status.
ok()) {
247 new_source.Release().IgnoreError();
252 Status status = this->DoEnable();
256 old_source->Release().IgnoreError();
260 new_source.Release().IgnoreError();
266 source_ = &new_source;
277 if (this->IncRef() > 1) {
284 if (
Status status = source_->Acquire(); !status.ok()) {
289 Status status = this->DoEnable();
291 source_->Release().IgnoreError();
303 if (this->DecRef() > 0) {
309 if (
Status status = this->DoDisable(); !status.
ok()) {
316 return source_->Release();
321 ElementType* source_;
363template <
typename ElementType>
380 uint32_t old_divider = divider_;
382 if (this->ref_count() == 0) {
386 Status status = this->DoEnable();
389 divider_ = old_divider;
404using ClockDividerBlocking = ClockDividerElement<ElementBlocking>;
408using ClockDividerNonBlockingCannotFail =
409 ClockDividerElement<ElementNonBlockingCannotFail>;
413using ClockDividerNonBlockingMightFail =
414 ClockDividerElement<ElementNonBlockingMightFail>;
435 PW_DASSERT(status.
ok());
448 std::lock_guard lock(
mutex_);
459 std::lock_guard lock(
mutex_);
480 Release(element_with).IgnoreError();
489 PW_DASSERT(status.
ok());
502 std::lock_guard lock(
mutex_);
513 std::lock_guard lock(
mutex_);
523 uint32_t divider_value) {
525 Status status = clock_divider.
Set(divider_value);
526 PW_DASSERT(status.
ok());
532 uint32_t divider_value) {
534 return clock_divider.
Set(divider_value);
540 uint32_t divider_value) {
541 std::lock_guard lock(
mutex_);
542 return clock_divider.
Set(divider_value);
552 std::lock_guard lock(
mutex_);
553 return clock_divider.
Set(divider_value);
556 return clock_divider.
Set(divider_value);
constexpr bool ok() const
Definition: status.h:157
Definition: clock_tree.h:365
Status Set(uint32_t divider) override
Definition: clock_tree.h:379
uint32_t divider() const
Get current divider value.
Definition: clock_tree.h:396
constexpr ClockDividerElement(ElementType &source, uint32_t divider)
Definition: clock_tree.h:369
Definition: clock_tree.h:330
Element & element() const
Return the element implementing this interface.
Definition: clock_tree.h:344
virtual Status Set(uint32_t divider)=0
Definition: clock_tree.h:147
Status Release() final
Definition: clock_tree.h:169
Status Acquire() final
Definition: clock_tree.h:152
Definition: clock_tree.h:187
pw::Status DoEnable() final
Function called when the clock tree element needs to get enabled.
Definition: clock_tree.h:189
pw::Status DoDisable() final
Definition: clock_tree.h:191
Definition: clock_tree.h:428
Status Release(Element &element)
Definition: clock_tree.h:511
void Acquire(ElementNonBlockingCannotFail &element)
Definition: clock_tree.h:432
Status SetDividerValue(ClockDivider &clock_divider, uint32_t divider_value)
Definition: clock_tree.h:550
Status AcquireWith(Element &element, Element &element_with)
Definition: clock_tree.h:477
Status SetDividerValue(ClockDividerNonBlockingMightFail &clock_divider, uint32_t divider_value)
Definition: clock_tree.h:531
Status Acquire(Element &element)
Definition: clock_tree.h:457
Status SetDividerValue(ClockDividerBlocking &clock_divider, uint32_t divider_value)
Definition: clock_tree.h:539
Status Release(ElementNonBlockingMightFail &element)
Definition: clock_tree.h:494
Status Acquire(ElementNonBlockingMightFail &element)
Definition: clock_tree.h:440
Status Acquire(ElementBlocking &element)
Definition: clock_tree.h:447
Status Release(ElementBlocking &element)
Definition: clock_tree.h:501
sync::InterruptSpinLock interrupt_spin_lock_
Definition: clock_tree.h:565
void SetDividerValue(ClockDividerNonBlockingCannotFail &clock_divider, uint32_t divider_value)
Definition: clock_tree.h:522
void Release(ElementNonBlockingCannotFail &element)
Definition: clock_tree.h:486
sync::Mutex mutex_
mutex_ protects ElementBlocking clock tree elements.
Definition: clock_tree.h:561
Definition: clock_tree.h:208
Status Acquire() final
Definition: clock_tree.h:276
constexpr DependentElement(ElementType &source)
Create a dependent clock tree element that depends on source.
Definition: clock_tree.h:211
Status UpdateSource(ElementType &new_source, bool permit_change_if_in_use)
Definition: clock_tree.h:228
Status Release() final
Definition: clock_tree.h:302
Definition: clock_tree.h:117
Definition: clock_tree.h:570
Element * element_
Pointer to optional Element object.
Definition: clock_tree.h:604
Status Acquire()
Definition: clock_tree.h:582
ClockTree * clock_tree_
Pointer to optional ClockTree object.
Definition: clock_tree.h:601
constexpr ElementController(ClockTree *clock_tree=nullptr, Element *element=nullptr)
Definition: clock_tree.h:574
Status Release()
Definition: clock_tree.h:593
Definition: clock_tree.h:39
virtual Status Release()=0
virtual Status Acquire()=0
virtual Status DoEnable()=0
Function called when the clock tree element needs to get enabled.
uint32_t IncRef()
Increment reference count and return incremented value.
Definition: clock_tree.h:88
bool may_block() const
Check whether acquiring or releasing the element may block.
Definition: clock_tree.h:48
uint32_t ref_count() const
Get reference count for this clock tree element.
Definition: clock_tree.h:45
uint32_t DecRef()
Decrement reference count and return decremented value.
Definition: clock_tree.h:91
virtual Status DoDisable()
Definition: clock_tree.h:100
Definition: clock_tree.h:124
Definition: clock_tree.h:128
Definition: interrupt_spin_lock.h:48
constexpr Status OkStatus()
Definition: status.h:234