nrfcxx  0.1.0
C++-17 Framework for Nordic nRF5 Devices
clock.hpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0 */
2 /* Copyright 2015-2019 Peter A. Bigot */
3 
7 #ifndef NRFCXX_CLOCK_HPP
8 #define NRFCXX_CLOCK_HPP
9 #pragma once
10 
11 #include <chrono>
12 #include <functional>
13 
14 #include <nrfcxx/impl.hpp>
15 #include <nrfcxx/periph.hpp>
16 
17 namespace nrfcxx {
18 
20 namespace clock {
21 
31 class hfclk
32 {
33  hfclk () = delete;
34  ~hfclk () = delete;
35  hfclk (const hfclk&) = delete;
36  hfclk& operator= (const hfclk&) = delete;
37  hfclk (hfclk&& ) = delete;
38  hfclk& operator= (hfclk&) = delete;
39 
40 protected:
41 
43  friend class periph::TIMER;
44 
53  static void constlat_request (const periph::TIMER& timer,
54  bool enable);
55 
56 public:
57 
62  constexpr static unsigned int Frequency_Hz = 16'000'000;
63 
68  static bool hfxt_active ()
69  {
70  return ((CLOCK_HFCLKSTAT_SRC_Xtal << CLOCK_HFCLKSTAT_SRC_Pos)
71  == (nrf5::CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_SRC_Msk));
72  }
73 
95  static bool hfxt_configure (int on);
96 };
97 
107 class lfclk
108 {
109  lfclk () = delete;
110  ~lfclk () = delete;
111  lfclk (const lfclk&) = delete;
112  lfclk& operator= (const lfclk&) = delete;
113  lfclk (lfclk&& ) = delete;
114  lfclk& operator= (lfclk&) = delete;
115 
116 public:
117 
119  constexpr static unsigned int Frequency_Hz = 32768U;
120 
126  constexpr static unsigned int DefaultRCOCalInterval_qs = 4 * 4;
127 
129  static bool active ()
130  {
131  return ((CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos)
132  == (nrf5::CLOCK->LFCLKSTAT & CLOCK_LFCLKSTAT_STATE_Msk));
133  }
134 
155  static int configure (int on);
156 
158  static uint32_t source ()
159  {
160  return (nrf5::CLOCK->LFCLKSTAT & CLOCK_LFCLKSTAT_SRC_Msk) >> CLOCK_LFCLKSTAT_SRC_Pos;
161  }
162 
186  static int source_configure (int src,
187  unsigned cal_interval_qs = DefaultRCOCalInterval_qs);
188 };
189 
220 int initialize (bool enable_hfxt = false,
221  int lfclk_src = board::default_lfclk_src(),
222  unsigned int lfrc_cal_interval_qs = lfclk::DefaultRCOCalInterval_qs);
223 
236 bool configure_pcirq (int on);
237 
243 class uptime
244 {
245 public:
247  constexpr static unsigned int Frequency_Hz = 32768;
248 
251  using mutex_type = mutex_irq<static_cast<IRQn_Type>(nrf5::UPTIME_RTC.IRQn)>;
252 
259  using duration_type = std::chrono::duration<int64_t, std::ratio<1, Frequency_Hz>>;
260 
262  using text_type = char[13];
263 
265  using day_text_type = char[18];
266 
275  static const char* as_text (text_type buf,
276  uint64_t dur_utt);
277 
292  static const char* as_day_text (day_text_type buf,
293  uint64_t dur_utt,
294  bool with_msec = false);
295 
300  static unsigned int now24 ()
301  {
302  return nrf5::UPTIME_RTC->COUNTER;
303  }
304 
313  constexpr static unsigned int delta24 (unsigned int a,
314  unsigned int b)
315  {
316  /* This relies on standard semantics for unsigned subtraction to
317  * handle the case where b < a. */
318  return periph::RTC::counter_mask & (b - a);
319  }
320 
331  {
332  protected:
333  unsigned int capture_utt24;
334 
335  public:
336  timestamp24 () :
337  capture_utt24{now24()}
338  { }
339 
341  unsigned int captured () const
342  {
343  return capture_utt24;
344  }
345 
347  void reset ()
348  {
349  capture_utt24 = now24();
350  }
351 
353  unsigned int delta () const
354  {
355  auto now_utt24 = now24();
356  return delta24(capture_utt24, now_utt24);
357  }
358 
360  unsigned int delta (unsigned int tick) const
361  {
362  return delta24(capture_utt24, tick);
363  }
364 
367  unsigned int delta_reset ()
368  {
369  auto now_utt24 = now24();
370  auto rv = delta24(capture_utt24, now_utt24);
371  capture_utt24 = now_utt24;
372  return rv;
373  }
374  };
375 
383  static uint64_t now ();
384 
386  template <typename DurT>
387  constexpr static DurT to_duration (int64_t utt)
388  {
389  return std::chrono::duration_cast<DurT>(duration_type(utt));
390  }
391 
393  template <typename DurT>
394  constexpr static typename duration_type::rep from_duration (DurT dur)
395  {
396  return std::chrono::duration_cast<duration_type>(dur).count();
397  }
398 
401  constexpr static int64_t to_us (int64_t utt)
402  {
403  return to_duration<std::chrono::microseconds>(utt).count();
404  }
405 
408  constexpr static int64_t from_us (int64_t us)
409  {
410  return from_duration(std::chrono::microseconds(us));
411  }
412 
415  constexpr static int64_t to_ms (int64_t utt)
416  {
417  return to_duration<std::chrono::milliseconds>(utt).count();
418  }
419 
422  constexpr static int64_t from_ms (int64_t ms)
423  {
424  return from_duration(std::chrono::milliseconds(ms));
425  }
426 
439  static int sleep (int dur);
440 
451  template <typename DurT,
452  typename DurT::rep = 0>
453  static DurT sleep (DurT dur)
454  {
455  return to_duration<DurT>(sleep(from_duration(dur)));
456  }
457 
464  static void wakeup ();
465 };
466 
471 constexpr uptime::duration_type
472 operator"" _utt (unsigned long long n)
473 {
474  return uptime::duration_type(n);
475 }
476 
498 class alarm
499 {
500 public:
503 
506  {
512 
519 
528 
536 
541  };
542 
544  state_type state () const
545  {
546  return state_;
547  }
548 
553  bool active () const
554  {
555  auto const s = state();
556  return (ST_scheduled <= s) && (s <= ST_in_callback);
557  }
558 
577  using callback_type = std::function<bool(alarm& alarm)>;
578 
579  /* You can't move or copy these. */
580  alarm (const alarm&) = delete;
581  alarm& operator= (const alarm&) = delete;
582  alarm (alarm&&) = delete;
583  alarm& operator= (alarm&&) = delete;
584 
595  alarm (callback_type callback,
596  unsigned int interval = 0,
597  void* md = 0) :
598  callback_{callback},
599  interval_{interval},
600  metadata{md}
601  { }
602 
612  alarm (callback_type callback,
613  void* md) :
614  alarm{callback, 0, md}
615  { }
616 
647  template <event_set::event_type EVT,
648  bool reschedule = false>
649  static alarm for_event (event_set& events)
650  {
651  return {[&events](auto&){
652  events.set(EVT);
653  return reschedule;
654  }};
655  }
656 
665  template <typename DurT,
666  typename DurT::rep = 0>
667  constexpr alarm (callback_type callback,
668  DurT interval,
669  void* md = 0) :
670  alarm(callback, uptime::from_duration(interval), md)
671  { }
672 
675  {
676  cancel();
677  }
678 
690  void schedule ();
691 
712  void schedule_offset (int offset);
713 
717  template <typename DurT>
718  void schedule_offset (DurT offset)
719  {
720  return schedule_offset(uptime::from_duration(offset));
721  }
722 
736  state_type cancel ();
737 
740  unsigned int
741  interval () const
742  {
743  return interval_;
744  }
745 
750  alarm& set_interval (unsigned int interval)
751  {
752  interval_ = interval;
753  return *this;
754  }
755 
757  template <typename DurT,
758  typename DurT::rep = 0>
760  {
762  }
763 
766  unsigned int
767  deadline () const
768  {
769  return deadline_;
770  }
771 
792  alarm& set_deadline (unsigned int deadline)
793  {
794  deadline_ = deadline;
795  return *this;
796  }
797 
798 protected:
800  struct alarm_queue;
801  friend alarm_queue;
802  friend void ::RTC1_IRQHandler();
807  int ordinal_ (unsigned int now) const noexcept
808  {
809  return deadline_ - now;
810  }
811 
812  callback_type const callback_;
813  unsigned int deadline_ = 0;
814  unsigned int interval_;
815  state_type volatile state_ = ST_unscheduled;
816  alarm* next_ = nullptr;
817  static alarm_queue queue_;
818 
819 public:
839  void* const metadata;
840 };
841 
865 {
866 public:
874  using time_type = uint64_t;
875 
880  using diff_type = std::make_signed<time_type>::type;
881 
883  static constexpr unsigned int RATE_DENOM = (1U << 16);
884 
892  void update_sync (time_type now_ctt,
893  time_type now_utt) noexcept;
894 
899  bool synchronized () const noexcept
900  {
901  return (0 != sync_ctt_);
902  }
903 
915  time_type convert_ctt (time_type now_utt) noexcept;
916 
922  unsigned int rate () const noexcept
923  {
924  return rate_;
925  }
926 
929  time_type offset () const noexcept
930  {
931  return sync_ctt_ - sync_utt_;
932  }
933 
934 private:
935  time_type sync_ctt_{};
936  time_type sync_utt_{};
937  unsigned int rate_ = RATE_DENOM;
938 };
939 
940 } // namespace clock
941 } // namespace nrfcxx
942 
943 #endif /* NRFCXX_CLOCK_HPP */
nrfcxx::clock::clock_shift::convert_ctt
time_type convert_ctt(time_type now_utt) noexcept
Best effort conversion from local time to civil time.
nrfcxx::clock::uptime::timestamp24::delta_reset
unsigned int delta_reset()
Return ticks since the captured time and reset captured time to now.
Definition: clock.hpp:367
nrfcxx::clock::alarm::ordinal_
int ordinal_(unsigned int now) const noexcept
Calculate an ordinal for the alarm using the distance from now until its deadline.
Definition: clock.hpp:807
nrfcxx::clock::uptime::from_duration
constexpr static duration_type::rep from_duration(DurT dur)
Generic conversion from a std::chrono::duration type to uptime ticks.
Definition: clock.hpp:394
nrfcxx::clock::alarm::schedule_offset
void schedule_offset(DurT offset)
Schedule an alarm using a std::chrono duration.
Definition: clock.hpp:718
nrfcxx::clock::alarm::set_deadline
alarm & set_deadline(unsigned int deadline)
Set the deadline for the alarm to fire.
Definition: clock.hpp:792
nrfcxx::clock::lfclk::source_configure
static int source_configure(int src, unsigned cal_interval_qs=DefaultRCOCalInterval_qs)
Enable, disable, or query the source of the low-frequency crystal.
nrfcxx::clock::alarm::~alarm
~alarm()
On destruction the alarm is cancelled.
Definition: clock.hpp:674
nrfcxx::clock::alarm::state
state_type state() const
The current state of the alarm.
Definition: clock.hpp:544
nrfcxx::clock::uptime::to_us
constexpr static int64_t to_us(int64_t utt)
Convert uptime ticks to integral microseconds (rounding down).
Definition: clock.hpp:401
nrfcxx::clock::hfclk::Frequency_Hz
constexpr static unsigned int Frequency_Hz
The high-frequency clock always runs at nominal 16 MHz.
Definition: clock.hpp:62
nrfcxx::board::default_lfclk_src
static constexpr unsigned int default_lfclk_src()
Provide the LFCLKSRC value preferred by the board.
Definition: impl.hpp:76
nrfcxx::clock::uptime::Frequency_Hz
constexpr static unsigned int Frequency_Hz
Frequency of the uptime clock as a symbolic constant.
Definition: clock.hpp:247
nrfcxx::clock::clock_shift::offset
time_type offset() const noexcept
The nominal offset between the civil time and local clocks at the time of the last synchronization po...
Definition: clock.hpp:929
nrfcxx::clock::alarm::ST_cancelled
The alarm has been cancelled.
Definition: clock.hpp:540
nrfcxx::clock::hfclk
Functions and data related to the high-frequency clock.
Definition: clock.hpp:31
nrfcxx::clock::alarm::ST_scheduled
Alarm is in the queue to execute at some point in the future.
Definition: clock.hpp:518
nrfcxx::clock::alarm::ST_unscheduled
Alarm has been constructed but has either not yet been scheduled or has completed.
Definition: clock.hpp:511
nrfcxx::clock::clock_shift::diff_type
std::make_signed< time_type >::type diff_type
The signed version of time_type.
Definition: clock.hpp:880
nrfcxx::clock::alarm::alarm
alarm(callback_type callback, unsigned int interval=0, void *md=0)
Standard alarm constructor.
Definition: clock.hpp:595
nrfcxx::periph::RTC::counter_mask
constexpr static uint32_t counter_mask
Mask for the 24-bit RTC counter.
Definition: periph.hpp:241
nrfcxx::event_set::set
void set(event_type events)
Atomically record one or more events.
Definition: core.hpp:603
nrfcxx::clock::uptime::mutex_type
mutex_irq< static_cast< IRQn_Type >(nrf5::UPTIME_RTC.IRQn)> mutex_type
An RAII type for mutex access to state that might be changed during the uptime clock FLIH.
Definition: clock.hpp:251
nrfcxx::mutex_irq
nvic_BlockIRQ as a template type.
Definition: core.hpp:497
nrfcxx::clock::clock_shift
Support for converting between time domains with the same resolution but unstable clocks.
Definition: clock.hpp:864
nrfcxx::clock::uptime
Support for a persistent system clock with 32 KiHz resolution.
Definition: clock.hpp:243
nrfcxx::clock::hfclk::constlat_request
static void constlat_request(const periph::TIMER &timer, bool enable)
Set or clear timer-based requests for constant latency wakeups.
nrfcxx::clock::alarm::callback_type
std::function< bool(alarm &alarm)> callback_type
The signature of an alarm callback function.
Definition: clock.hpp:577
nrfcxx::clock::uptime::wakeup
static void wakeup()
Cancel any in-progress sleep().
nrfcxx::clock::lfclk::active
static bool active()
Return true iff the low-frequency clock is active.
Definition: clock.hpp:129
nrfcxx::periph::TIMER
Wrapper around the nRF5 TIMER peripheral.
Definition: periph.hpp:301
nrfcxx::clock::alarm::schedule
void schedule()
Queue the alarm to execute at its current deadline().
nrfcxx::clock::uptime::sleep
static int sleep(int dur)
Sleep for a given number of uptime ticks.
nrfcxx::clock::alarm::set_interval
alarm & set_interval(DurT interval)
Set the interval() using a given duration.
Definition: clock.hpp:759
nrfcxx::clock::lfclk::Frequency_Hz
constexpr static unsigned int Frequency_Hz
The low-frequency clock always runs at nominal 32 KiHz.
Definition: clock.hpp:119
nrfcxx::clock::clock_shift::update_sync
void update_sync(time_type now_ctt, time_type now_utt) noexcept
Provide a new synchronization pair.
nrfcxx::clock::alarm::metadata
void *const metadata
Pointer to arbitrary data associated with the alarm.
Definition: clock.hpp:839
nrfcxx::clock::alarm::interval
unsigned int interval() const
An offset added to deadline() prior to invoking the callback when the alarm fires.
Definition: clock.hpp:741
nrfcxx::clock::lfclk::configure
static int configure(int on)
Enable, disable, or query the state of the low-frequency clock.
nrfcxx::clock::alarm::ST_ready
Alarm deadline has been reached and the callback will soon be invoked.
Definition: clock.hpp:527
nrfcxx::clock::uptime::sleep
static DurT sleep(DurT dur)
Sleep for a specified duration.
Definition: clock.hpp:453
nrfcxx::clock::alarm::state_type
state_type
Constants identifying the alarm state.
Definition: clock.hpp:505
nrfcxx::clock::configure_pcirq
bool configure_pcirq(int on)
Query or control whether the POWER_CLOCK interrupt handler is enabled.
nrfcxx::clock::uptime::as_text
static const char * as_text(text_type buf, uint64_t dur_utt)
Convert an uptime duration to text format.
nrfcxx::clock::hfclk::hfxt_active
static bool hfxt_active()
Return true iff the high-frequency clock is being driven by a crystal oscillator.
Definition: clock.hpp:68
nrfcxx::clock::clock_shift::RATE_DENOM
static constexpr unsigned int RATE_DENOM
The implicit denominator of rate().
Definition: clock.hpp:883
nrfcxx::clock::clock_shift::rate
unsigned int rate() const noexcept
The differential rate of the civil time clock relative to the local clock.
Definition: clock.hpp:922
nrfcxx::clock::alarm::alarm
alarm(callback_type callback, void *md)
Overload for common case of configuring with static callback.
Definition: clock.hpp:612
nrfcxx::clock::uptime::now24
static unsigned int now24()
Low 24 bits of the uptime counter.
Definition: clock.hpp:300
nrfcxx::clock::initialize
int initialize(bool enable_hfxt=false, int lfclk_src=board::default_lfclk_src(), unsigned int lfrc_cal_interval_qs=lfclk::DefaultRCOCalInterval_qs)
Initialize the clock system.
nrfcxx::clock::uptime::timestamp24::delta
unsigned int delta(unsigned int tick) const
Return ticks between captured time and tick.
Definition: clock.hpp:360
impl.hpp
Primary header for nrfcxx implementation dependencies.
nrfcxx::clock::uptime::duration_type
std::chrono::duration< int64_t, std::ratio< 1, Frequency_Hz > > duration_type
Full precision duration type for uptime clock.
Definition: clock.hpp:259
nrfcxx::clock::uptime::text_type
char[13] text_type
A type containing a NUL-terminated text time representation: HH:MM:SS.mmm
Definition: clock.hpp:262
nrfcxx::clock::uptime::to_duration
constexpr static DurT to_duration(int64_t utt)
Generic conversion from uptime ticks to a std::chrono::duration type.
Definition: clock.hpp:387
nrfcxx::clock::alarm::active
bool active() const
Return true if the alarm state is one of ST_scheduled, ST_ready, or ST_in_callback.
Definition: clock.hpp:553
nrfcxx::clock::lfclk::source
static uint32_t source()
Return the actual source for the low-frequency clock.
Definition: clock.hpp:158
nrfcxx::clock::alarm
Class supporting an alarm with custom callback and repeatability.
Definition: clock.hpp:498
nrfcxx::clock::hfclk::hfxt_configure
static bool hfxt_configure(int on)
Enable, disable, or query the state of application request for the high-frequency crystal.
nrfcxx::clock::lfclk
Functions and data related to the low-frequency clock.
Definition: clock.hpp:107
nrfcxx::clock::uptime::now
static uint64_t now()
Full-range uptime counter.
nrfcxx::clock::uptime::timestamp24::delta
unsigned int delta() const
Return ticks since the captured time.
Definition: clock.hpp:353
nrfcxx::clock::uptime::as_day_text
static const char * as_day_text(day_text_type buf, uint64_t dur_utt, bool with_msec=false)
Convert an uptime duration to text format.
nrfcxx::clock::uptime::day_text_type
char[18] day_text_type
A type encoding a NUL-terminated text day+time representation: DDDD HH:MM:SS.mmm
Definition: clock.hpp:265
nrfcxx::clock::alarm::deadline
unsigned int deadline() const
The value of (the low 32 bits of) uptime::now() at which the alarm should fire.
Definition: clock.hpp:767
nrfcxx::clock::alarm::for_event
static alarm for_event(event_set &events)
Factory producing an alarm with a callback that sets an event.
Definition: clock.hpp:649
nrfcxx::clock::uptime::timestamp24::reset
void reset()
Capture the current time.
Definition: clock.hpp:347
nrfcxx::clock::uptime::from_ms
constexpr static int64_t from_ms(int64_t ms)
Convert integral milliseconds to uptime ticks (rounding down).
Definition: clock.hpp:422
nrfcxx::clock::uptime::from_us
constexpr static int64_t from_us(int64_t us)
Convert integral microseconds to uptime ticks (rounding down).
Definition: clock.hpp:408
nrfcxx::clock::alarm::set_interval
alarm & set_interval(unsigned int interval)
Set the interval() in uptime ticks.
Definition: clock.hpp:750
nrfcxx::event_set::event_type
unsigned int event_type
The type used to represent a (set of) event(s).
Definition: core.hpp:547
nrfcxx::clock::alarm::alarm
constexpr alarm(callback_type callback, DurT interval, void *md=0)
Duration-specified alarm constructor.
Definition: clock.hpp:667
nrfcxx::clock::alarm::cancel
state_type cancel()
Cancel a potentially-scheduled alarm.
nrfcxx::clock::clock_shift::time_type
uint64_t time_type
Type for unsigned 32 KiHz ticks since the epoch of a time system.
Definition: clock.hpp:874
nrfcxx::clock::uptime::timestamp24
Class supporting short-term duration measurements.
Definition: clock.hpp:330
nrfcxx::clock::lfclk::DefaultRCOCalInterval_qs
constexpr static unsigned int DefaultRCOCalInterval_qs
The default RC oscillator calibration interval, in quarter-seconds.
Definition: clock.hpp:126
nrfcxx::clock::alarm::schedule_offset
void schedule_offset(int offset)
Queue the alarm to execute at offset ticks from the current time.
periph.hpp
Abstraction of Nordic device peripherals.
nrfcxx
Primary namespace for nrfcxx functionality.
Definition: clock.hpp:17
nrfcxx::event_set
A record of events that occur asynchonously.
Definition: core.hpp:541
nrfcxx::clock::uptime::to_ms
constexpr static int64_t to_ms(int64_t utt)
Convert uptime ticks to integral milliseconds (rounding down).
Definition: clock.hpp:415
nrfcxx::clock::uptime::timestamp24::captured
unsigned int captured() const
Return the tick corresponding to the captured time.
Definition: clock.hpp:341
nrfcxx::clock::alarm::ST_in_callback
The callback is being invoked.
Definition: clock.hpp:535
nrfcxx::clock::uptime::delta24
constexpr static unsigned int delta24(unsigned int a, unsigned int b)
Calculate the tick-count between two 24-bit counter values.
Definition: clock.hpp:313