clock.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
7 #include <chip.h>
8 #include "internal.hpp"
9 
10 namespace uavcan_lpc11c24
11 {
12 namespace clock
13 {
14 namespace
15 {
16 
17 bool initialized = false;
18 bool utc_set = false;
19 
20 std::int32_t utc_correction_usec_per_overflow_x16 = 0;
21 std::int64_t prev_adjustment = 0;
22 
23 std::uint64_t time_mono = 0;
24 std::uint64_t time_utc = 0;
25 
30 constexpr std::uint32_t USecPerOverflow = 65536 * 2;
31 constexpr std::int32_t MaxUtcSpeedCorrectionX16 = 100 * 16;
32 
33 }
34 
35 #if __GNUC__
36 __attribute__((noreturn))
37 #endif
38 static void fail()
39 {
40  while (true) { }
41 }
42 
43 void init()
44 {
45  CriticalSectionLocker lock;
46  if (!initialized)
47  {
48  initialized = true;
49 
50  if ((SystemCoreClock % 1000000) != 0) // Core clock frequency validation
51  {
52  fail();
53  }
54 
55  if (SysTick_Config((SystemCoreClock / 1000000) * USecPerOverflow) != 0)
56  {
57  fail();
58  }
59  }
60 }
61 
62 static std::uint64_t sampleFromCriticalSection(const volatile std::uint64_t* const value)
63 {
64  const std::uint32_t reload = SysTick->LOAD + 1; // SysTick counts downwards, hence the value subtracted from reload
65 
66  volatile std::uint64_t time = *value;
67  volatile std::uint32_t cycles = reload - SysTick->VAL;
68 
70  {
71  cycles = reload - SysTick->VAL;
72  time += USecPerOverflow;
73  }
74  const std::uint32_t cycles_per_usec = SystemCoreClock / 1000000;
75  return time + (cycles / cycles_per_usec);
76 }
77 
79 {
80  return utc_set ? sampleFromCriticalSection(&time_utc) : 0;
81 }
82 
84 {
85  if (!initialized)
86  {
87  fail();
88  }
89  std::uint64_t usec = 0;
90  {
91  CriticalSectionLocker locker;
92  usec = sampleFromCriticalSection(&time_mono);
93  }
95 }
96 
98 {
99  if (!initialized)
100  {
101  fail();
102  }
103  std::uint64_t usec = 0;
104  if (utc_set)
105  {
106  CriticalSectionLocker locker;
107  usec = sampleFromCriticalSection(&time_utc);
108  }
109  return uavcan::UtcTime::fromUSec(usec);
110 }
111 
113 {
114  return uavcan::UtcDuration::fromUSec(prev_adjustment);
115 }
116 
118 {
119  const std::int64_t adj_delta = adjustment.toUSec() - prev_adjustment; // This is the P term
120  prev_adjustment = adjustment.toUSec();
121 
122  utc_correction_usec_per_overflow_x16 += adjustment.isPositive() ? 1 : -1; // I
123  utc_correction_usec_per_overflow_x16 += (adj_delta > 0) ? 1 : -1; // P
124 
125  utc_correction_usec_per_overflow_x16 =
126  uavcan::max(utc_correction_usec_per_overflow_x16, -MaxUtcSpeedCorrectionX16);
127  utc_correction_usec_per_overflow_x16 =
128  uavcan::min(utc_correction_usec_per_overflow_x16, MaxUtcSpeedCorrectionX16);
129 
130  if (adjustment.getAbs().toMSec() > 9 || !utc_set)
131  {
132  const std::int64_t adj_usec = adjustment.toUSec();
133  {
134  CriticalSectionLocker locker;
135  if ((adj_usec < 0) && std::uint64_t(-adj_usec) > time_utc)
136  {
137  time_utc = 1;
138  }
139  else
140  {
141  time_utc = std::uint64_t(std::int64_t(time_utc) + adj_usec);
142  }
143  }
144  if (!utc_set)
145  {
146  utc_set = true;
147  utc_correction_usec_per_overflow_x16 = 0;
148  }
149  }
150 }
151 
152 } // namespace clock
153 
154 SystemClock SystemClock::self;
155 
157 {
158  clock::init();
159  return self;
160 }
161 
162 }
163 
164 /*
165  * Timer interrupt handler
166  */
167 extern "C"
168 {
169 
170 void SysTick_Handler();
171 
173 {
174  using namespace uavcan_lpc11c24::clock;
175  if (initialized)
176  {
177  time_mono += USecPerOverflow;
178  if (utc_set)
179  {
180  // Values below 16 are ignored
181  time_utc += std::uint64_t(std::int32_t(USecPerOverflow) + (utc_correction_usec_per_overflow_x16 / 16));
182  }
183  }
184  else
185  {
186  fail();
187  }
188 }
189 
190 }
SCB
#define SCB
Definition: core_cm0.h:459
uavcan_lpc11c24::SystemClock::self
static SystemClock self
Definition: platform_specific_components/lpc11c24/libuavcan/driver/include/uavcan_lpc11c24/clock.hpp:50
SystemCoreClock
uint32_t SystemCoreClock
Current system clock rate, mainly used for sysTick.
Definition: board.cpp:18
uavcan::DurationBase::toMSec
int64_t toMSec() const
Definition: time.hpp:44
uavcan::uint64_t
std::uint64_t uint64_t
Definition: std.hpp:27
templates.hpp
uavcan_lpc11c24::clock::getMonotonic
uavcan::MonotonicTime getMonotonic()
Definition: clock.cpp:83
uavcan::uint32_t
std::uint32_t uint32_t
Definition: std.hpp:26
uavcan_lpc11c24::clock::sampleFromCriticalSection
static std::uint64_t sampleFromCriticalSection(const volatile std::uint64_t *const value)
Definition: clock.cpp:62
uavcan::UtcTime
Implicitly convertible to/from uavcan.Timestamp.
Definition: time.hpp:191
uavcan::UtcDuration
Definition: time.hpp:189
uavcan_lpc11c24::clock
Definition: platform_specific_components/lpc11c24/libuavcan/driver/include/uavcan_lpc11c24/clock.hpp:11
uavcan_lpc11c24::clock::init
void init()
Definition: clock.cpp:43
uavcan_lpc11c24::clock::getUtcUSecFromCanInterrupt
std::uint64_t getUtcUSecFromCanInterrupt()
Definition: clock.cpp:78
uavcan::DurationBase::getAbs
D getAbs() const
Definition: time.hpp:46
uavcan::int64_t
std::int64_t int64_t
Definition: std.hpp:32
uavcan_lpc11c24::clock::getPrevUtcAdjustment
uavcan::UtcDuration getPrevUtcAdjustment()
Definition: clock.cpp:112
uavcan::int32_t
std::int32_t int32_t
Definition: std.hpp:31
uavcan::TimeBase< MonotonicTime, MonotonicDuration >::fromUSec
static MonotonicTime fromUSec(uint64_t us)
Definition: time.hpp:112
uavcan::max
const UAVCAN_EXPORT T & max(const T &a, const T &b)
Definition: templates.hpp:291
uavcan_lpc11c24::clock::fail
static void fail()
Definition: clock.cpp:38
uavcan::DurationBase::isPositive
bool isPositive() const
Definition: time.hpp:48
uavcan::min
const UAVCAN_EXPORT T & min(const T &a, const T &b)
Definition: templates.hpp:281
internal.hpp
clock.hpp
uavcan_lpc11c24::clock::adjustUtc
void adjustUtc(uavcan::UtcDuration adjustment)
Definition: clock.cpp:117
SysTick_Config
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
System Tick Configuration.
Definition: core_cm0.h:641
uavcan_lpc11c24::clock::getUtc
uavcan::UtcTime getUtc()
Definition: clock.cpp:97
__attribute__
__attribute__((gnu_inline)) inline void spi_start(uint8_t data)
Definition: spi.h:74
SCB_ICSR_PENDSTSET_Msk
#define SCB_ICSR_PENDSTSET_Msk
Definition: core_cm0.h:330
uavcan_lpc11c24
Definition: platform_specific_components/lpc11c24/libuavcan/driver/include/uavcan_lpc11c24/can.hpp:9
SysTick
#define SysTick
Definition: core_cm0.h:460
chip.h
uavcan::MonotonicTime
Definition: time.hpp:184
uavcan_lpc11c24::SystemClock::instance
static SystemClock & instance()
Definition: clock.cpp:156
SysTick_Handler
void SysTick_Handler()
Definition: clock.cpp:172
uavcan::DurationBase::toUSec
int64_t toUSec() const
Definition: time.hpp:43
uavcan::DurationBase< UtcDuration >::fromUSec
static UtcDuration fromUSec(int64_t us)
Definition: time.hpp:35
uavcan_lpc11c24::SystemClock
Definition: platform_specific_components/lpc11c24/libuavcan/driver/include/uavcan_lpc11c24/clock.hpp:48


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:02