Mbed OS Reference
Loading...
Searching...
No Matches
SysTimer.h
1/* mbed Microcontroller Library
2 * Copyright (c) 2006-2019 ARM Limited
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#ifndef MBED_SYS_TIMER_H
18#define MBED_SYS_TIMER_H
19
20#include "platform/NonCopyable.h"
21#include "platform/mbed_atomic.h"
22#include "drivers/TimerEvent.h"
23#include <chrono>
24#include "cmsis.h"
25
26extern "C" {
27#if defined(TARGET_CORTEX_A)
28#include "irq_ctrl.h"
29#endif
30}
31
32namespace mbed {
33namespace internal {
34
35/**
36 * \defgroup mbed_SysTimer SysTimer class
37 * \ingroup platform-internal-api
38 * @{
39 */
40
41/**
42 * The SysTimer class is used to provide timing for system suspension, and
43 * the idle loop in TICKLESS mode.
44 *
45 * Template for speed for testing - only one instance will be used normally.
46 *
47 * @note SysTimer is not the part of Mbed API.
48 */
49template <class Period, bool IRQ = true>
50class SysTimer: private mbed::TimerEvent, private mbed::NonCopyable<SysTimer<Period, IRQ> > {
51public:
52
53 /* pseudo-Clock for our ticks - see TickerDataClock for more discussion */
54 using rep = uint64_t;
55 using period = Period;
56 using duration = std::chrono::duration<uint64_t, period>;
57 using time_point = std::chrono::time_point<SysTimer>;
58 static const bool is_steady = false;
59
60 /** duration type used for underlying high-res timer */
61 using highres_duration = TickerDataClock::duration;
62 /** time_point type used for underlying high-res timer */
63 using highres_time_point = TickerDataClock::time_point;
64 /** period of underlying high-res timer */
65 using highres_period = TickerDataClock::period;
66
67 static_assert(std::ratio_divide<period, highres_period>::den == 1, "Tick period must be an exact multiple of highres time period");
68
69 /**
70 * Default constructor uses LPTICKER if available (so the timer will
71 * continue to run in deep sleep), else USTICKER.
72 */
74
75 SysTimer(const ticker_data_t *data);
76
77protected:
78 ~SysTimer();
79
80public:
81
82#if TARGET_CORTEX_A
83 /**
84 * Get the interrupt number for the tick
85 *
86 * @return interrupt number
87 */
88 static IRQn_ID_t get_irq_number();
89#elif TARGET_CORTEX_M
90 /**
91 * Get the interrupt number for the tick
92 *
93 * @return interrupt number
94 */
95 static IRQn_Type get_irq_number();
96#endif
97
98 /**
99 * Set the wake time
100 *
101 * Schedules an interrupt to cause wake-up in time for the event. Interrupt
102 * may be arranged early to account for latency. If the time has already
103 * passed, no interrupt will be scheduled.
104 *
105 * This is called from outside a critical section, as it is known to be
106 * a slow operation.
107 *
108 * If the wake time is already set, this is a no-op. But that check is racy,
109 * which means wake_time_set() should be rechecked after taking a critical
110 * section.
111 *
112 * As a side-effect, this clears the unacknowledged tick count - the caller
113 * is expected to use update_and_get_tick() after the suspend operation.
114 *
115 * @param at Wake up tick
116 * @warning If the ticker tick is already scheduled it needs to be cancelled first!
117 */
118 void set_wake_time(time_point at);
119
120 /**
121 * Check whether the wake time has passed
122 *
123 * This is a fast operation, based on checking whether the wake interrupt
124 * has run.
125 *
126 * @return true if the specified wake tick has passed
127 */
128 bool wake_time_passed() const
129 {
130 return core_util_atomic_load_bool(&_wake_time_passed);
131 }
132
133 /**
134 * Check whether wake timer is active
135 *
136 * @return true if the wake timer is active.
137 */
138 bool wake_time_set() const
139 {
140 return core_util_atomic_load_bool(&_wake_time_set);
141 }
142
143 /**
144 * Cancel any pending wake
145 */
147
148 /**
149 * Schedule an os tick to fire
150 *
151 * Ticks will be rescheduled automatically every tick until cancel_tick is called.
152 *
153 * A tick will be fired immediately if there are any unacknowledged ticks.
154 *
155 * @warning If a tick is already scheduled it needs to be cancelled first!
156 */
158
159 /**
160 * Acknowledge an os tick
161 *
162 * This will queue another os tick immediately if the os is running slow
163 */
165
166 /**
167 * Prevent any more scheduled ticks from triggering
168 *
169 * If called from OS tick context, there may be remaining unacknowledged ticks.
170 */
172
173 /**
174 * Check whether ticker is active
175 *
176 * Each time the tick interrupt fires, it is automatically rescheduled,
177 * so this will remain true once the tick is started, except during
178 * processing.
179 *
180 * @return true if the ticker is active.
181 */
182 bool ticking() const
183 {
184 return core_util_atomic_load_bool(&_ticking);
185 }
186
187 /**
188 * Check unacknowledged ticks
189 *
190 * Returns the count of how many times the OS timer has been queued minus
191 * the number of times is has been acknowledged.
192 *
193 * get_tick() - unacknowledged_ticks() should equal the OS's tick count,
194 * although such a calculation is not atomic if the ticker is currently running.
195 *
196 * @return number of unacknowledged ticks
197 */
198 std::chrono::duration<int, period> unacknowledged_ticks() const
199 {
200 return std::chrono::duration<int, period>(core_util_atomic_load_u32(&_unacknowledged_ticks));
201 }
202
203 /** Get the current tick count
204 *
205 * This count is updated by the ticker interrupt, if the ticker interrupt
206 * is running. It the ticker interrupt is not running, update_and_get_tick()
207 * should be used instead.
208 *
209 * This indicates how many ticks have been generated by the tick interrupt.
210 * The os_timer should equal this number minus the number of unacknowledged ticks.
211 *
212 * @return The number of ticks since timer creation.
213 */
214 time_point get_tick() const;
215
216 /** Update and get the current tick count
217 *
218 * This is a slow operation that reads the timer and adjusts for elapsed time.
219 * Can only be used when the ticker is not running, as there is no IRQ
220 * synchronization.
221 *
222 * This clears the unacknowledged tick counter - the caller is assumed to update
223 * their timer based on this return.
224 *
225 * @return The number of ticks since timer creation.
226 */
228
229 /**
230 * Returns time since last tick
231 *
232 * @return Relative time in microseconds
233 */
235
236 /**
237 * Get the time
238 *
239 * Returns the instantaneous precision time from underlying timer.
240 * This is a slow operation so should not be called from critical sections.
241 *
242 * @return Current time in microseconds
243 */
245
246protected:
247 using highres_duration_u32 = std::chrono::duration<uint32_t, highres_period>;
248 void handler() override;
249 void _increment_tick();
250 void _schedule_tick();
251 duration _elapsed_ticks() const;
252 static void _set_irq_pending();
253 static void _clear_irq_pending();
254 const highres_time_point _epoch;
255 highres_time_point _time;
256 uint64_t _tick;
257 uint32_t _unacknowledged_ticks;
258 bool _wake_time_set;
259 bool _wake_time_passed;
260 bool _wake_early;
261 bool _ticking;
262 bool _deep_sleep_locked;
263};
264
265/** @} */
266
267}
268}
269
270#endif
Prevents generation of copy constructor and copy assignment operator in derived classes.
Definition: NonCopyable.h:162
Base abstraction for timer interrupts.
Definition: TimerEvent.h:37
The SysTimer class is used to provide timing for system suspension, and the idle loop in TICKLESS mod...
Definition: SysTimer.h:50
bool wake_time_set() const
Check whether wake timer is active.
Definition: SysTimer.h:138
bool wake_time_passed() const
Check whether the wake time has passed.
Definition: SysTimer.h:128
SysTimer()
Default constructor uses LPTICKER if available (so the timer will continue to run in deep sleep),...
void acknowledge_tick()
Acknowledge an os tick.
void set_wake_time(time_point at)
Set the wake time.
highres_duration get_time_since_tick() const
Returns time since last tick.
bool ticking() const
Check whether ticker is active.
Definition: SysTimer.h:182
highres_time_point get_time() const
Get the time.
time_point get_tick() const
Get the current tick count.
std::chrono::duration< int, period > unacknowledged_ticks() const
Check unacknowledged ticks.
Definition: SysTimer.h:198
void cancel_tick()
Prevent any more scheduled ticks from triggering.
TickerDataClock::duration highres_duration
duration type used for underlying high-res timer
Definition: SysTimer.h:61
void cancel_wake()
Cancel any pending wake.
time_point update_and_get_tick()
Update and get the current tick count.
TickerDataClock::period highres_period
period of underlying high-res timer
Definition: SysTimer.h:65
TickerDataClock::time_point highres_time_point
time_point type used for underlying high-res timer
Definition: SysTimer.h:63
void start_tick()
Schedule an os tick to fire.
Ticker's data structure.
Definition: ticker_api.h:144