Skip to content

Commit 0cecada

Browse files
committed
Add Chrono support to Ticker et al
1 parent cc14246 commit 0cecada

File tree

7 files changed

+229
-54
lines changed

7 files changed

+229
-54
lines changed

drivers/Ticker.h

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@
1717
#ifndef MBED_TICKER_H
1818
#define MBED_TICKER_H
1919

20+
#include <chrono>
2021
#include <mstd_utility>
22+
#include "drivers/TickerClock.h"
2123
#include "drivers/TimerEvent.h"
2224
#include "platform/Callback.h"
2325
#include "platform/mbed_toolchain.h"
2426
#include "platform/NonCopyable.h"
2527
#include "hal/lp_ticker_api.h"
2628

2729
namespace mbed {
30+
2831
/**
2932
* \defgroup drivers_Ticker Ticker class
3033
* \ingroup drivers-public-api-ticker
@@ -42,6 +45,7 @@ namespace mbed {
4245
* // Toggle the blinking LED after 5 seconds
4346
*
4447
* #include "mbed.h"
48+
* using namespace std::chrono;
4549
*
4650
* Ticker timer;
4751
* DigitalOut led1(LED1);
@@ -54,14 +58,14 @@ namespace mbed {
5458
* }
5559
*
5660
* int main() {
57-
* timer.attach(&attime, 5);
61+
* timer.attach(&attime, 5us);
5862
* while(1) {
5963
* if(flip == 0) {
6064
* led1 = !led1;
6165
* } else {
6266
* led2 = !led2;
6367
* }
64-
* wait(0.2);
68+
* ThisThread::sleep_for(200ms);
6569
* }
6670
* }
6771
* @endcode
@@ -82,15 +86,19 @@ class Ticker : public TimerEvent, private NonCopyable<Ticker> {
8286
* possible given attach_us() expects an integer value for the callback interval.
8387
* @param func pointer to the function to be called
8488
* @param t the time between calls in seconds
89+
* @deprecated Pass a chrono duration, not a float second count. For example use `10ms` rather than `0.01f`.
8590
*/
8691
#if defined(__ICCARM__)
92+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not a float second count. For example use `10ms` rather than `0.01f`.")
8793
MBED_FORCEINLINE template <typename F>
8894
#else
8995
template <typename F> MBED_FORCEINLINE
96+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not a float second count. For example use `10ms` rather than `0.01f`.")
9097
#endif
9198
void attach(F &&func, float t)
9299
{
93-
attach_us(std::forward<F>(func), t * 1000000.0f);
100+
auto float_interval = std::chrono::duration<float>(t);
101+
attach(std::forward<F>(func), std::chrono::duration_cast<std::chrono::microseconds>(float_interval));
94102
}
95103

96104
/** Attach a member function to be called by the Ticker, specifying the interval in seconds
@@ -119,10 +127,24 @@ class Ticker : public TimerEvent, private NonCopyable<Ticker> {
119127
* @note setting @a t to a value shorter than it takes to process the ticker callback
120128
* causes the system to hang. Ticker callback is called constantly with no time
121129
* for threads scheduling.
130+
* @deprecated Pass a chrono duration, not an integer microsecond count. For example use `10ms` rather than `10000`.
122131
*
123132
*/
133+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer microsecond count. For example use `10ms` rather than `10000`.")
124134
void attach_us(Callback<void()> func, us_timestamp_t t);
125135

136+
/** Attach a function to be called by the Ticker, specifying the interval in microseconds
137+
*
138+
* @param func pointer to the function to be called
139+
* @param t the time between calls in micro-seconds
140+
*
141+
* @note setting @a t to a value shorter than it takes to process the ticker callback
142+
* causes the system to hang. Ticker callback is called constantly with no time
143+
* for threads scheduling.
144+
*
145+
*/
146+
void attach(Callback<void()> func, TickerClock::duration t);
147+
126148
/** Attach a member function to be called by the Ticker, specifying the interval in microseconds
127149
*
128150
* @param obj pointer to the object to call the member function on
@@ -152,11 +174,10 @@ class Ticker : public TimerEvent, private NonCopyable<Ticker> {
152174

153175
#if !defined(DOXYGEN_ONLY)
154176
protected:
155-
void setup(us_timestamp_t t);
177+
void setup(TickerClock::duration t);
156178
virtual void handler();
157179

158-
protected:
159-
us_timestamp_t _delay; /**< Time delay (in microseconds) for resetting the multishot callback. */
180+
TickerClock::duration _delay; /**< Time delay (in microseconds) for resetting the multishot callback. */
160181
Callback<void()> _function; /**< Callback. */
161182
bool _lock_deepsleep; /**< Flag which indicates if deep sleep should be disabled. */
162183
#endif

drivers/TickerClock.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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_TICKERCLOCK_H
18+
#define MBED_TICKERCLOCK_H
19+
20+
#include <chrono>
21+
#include "hal/ticker_api.h"
22+
23+
namespace mbed {
24+
/**
25+
* \defgroup drivers_TickerClock TickerClock class
26+
* \ingroup drivers-public-api-ticker
27+
* @{
28+
*/
29+
30+
/**
31+
* A partial implementation of a C++11 Clock representing a HAL ticker.
32+
*
33+
* This class allows us to create chrono time_points for objects like Timer,
34+
* with the limitation that the tickers are not singletons. This means:
35+
*
36+
* * the now() function is not static - this will limit
37+
* use with some algorithms,
38+
* * there is no distinction between time_points for different
39+
* tickers
40+
*
41+
* This "pseudo-Clock" approach has been endorsed by Howard Hinnant
42+
* (designer of Chrono) here:
43+
* https://stackoverflow.com/questions/56400313/why-does-the-c-standard-require-the-clocknow-function-to-be-static
44+
*
45+
* TickerClock::time_point values should only be used with mbed APIs specifically taking
46+
* them, not passed to generic templated chrono algorithms, and it is up to the user to use them
47+
* in conjunction with the correct TickerClock.
48+
*
49+
* operators for `->` and conversion to `ticker_data_t *` are provided allowing
50+
* TickerClock to be easily substituted in place of a `ticker_data_t *`.
51+
*/
52+
struct TickerClock {
53+
/** Construct a TickerClock referring to a ticker_data_t */
54+
constexpr TickerClock(const ticker_data_t *ticker) : _ticker(ticker)
55+
{
56+
}
57+
/* duration is C++11 standard microseconds, so representation will be 64-bit signed integer */
58+
using duration = std::chrono::microseconds;
59+
using rep = duration::rep;
60+
using period = duration::period;
61+
using time_point = std::chrono::time_point<TickerClock>;
62+
static const bool is_steady = false;
63+
time_point now() const
64+
{
65+
return time_point(duration(ticker_read_us(_ticker)));
66+
}
67+
constexpr const ticker_data_t *operator->() const
68+
{
69+
return _ticker;
70+
}
71+
constexpr operator const ticker_data_t *() const
72+
{
73+
return _ticker;
74+
}
75+
private:
76+
const ticker_data_t *_ticker;
77+
};
78+
79+
inline TickerClock::time_point get_time_point(const ticker_event_t &event)
80+
{
81+
return TickerClock::time_point(TickerClock::duration(event.timestamp));
82+
}
83+
84+
/** @}*/
85+
86+
}
87+
#endif /* MBED_TICKERCLOCK_H */

drivers/Timer.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#define MBED_TIMER_H
1919

2020
#include "platform/platform.h"
21-
#include "hal/ticker_api.h"
21+
#include "drivers/TickerClock.h"
2222
#include "platform/NonCopyable.h"
2323

2424
namespace mbed {
@@ -58,6 +58,10 @@ class Timer : private NonCopyable<Timer> {
5858
Timer(const ticker_data_t *data);
5959
~Timer();
6060

61+
using period = TickerClock::period;
62+
using duration = TickerClock::duration;
63+
using rep = TickerClock::rep;
64+
6165
/** Start the timer
6266
*/
6367
void start();
@@ -76,6 +80,7 @@ class Timer : private NonCopyable<Timer> {
7680
*
7781
* @returns Time passed in seconds
7882
*/
83+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Floating point operators should normally be avoided for code size. If really needed, you can use `duration<float>(read_duration()).count()`")
7984
float read();
8085

8186
/** Get the time passed in milliseconds
@@ -92,21 +97,27 @@ class Timer : private NonCopyable<Timer> {
9297

9398
/** An operator shorthand for read()
9499
*/
100+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Floating point operators should normally be avoided for code size. If really needed, you can use `duration<float>(read_duration()).count()`")
95101
operator float();
96102

97103
/** Get in a high resolution type the time passed in microseconds.
98104
* Returns a 64 bit integer.
99105
*/
100106
us_timestamp_t read_high_resolution_us();
101107

108+
/** Get in a high resolution type the time passed in microseconds.
109+
* Returns a 64 bit integer chrono duration.
110+
*/
111+
duration read_duration();
112+
102113
#if !defined(DOXYGEN_ONLY)
103114
protected:
104-
us_timestamp_t slicetime();
105-
int _running; // whether the timer is running
106-
us_timestamp_t _start; // the start time of the latest slice
107-
us_timestamp_t _time; // any accumulated time from previous slices
108-
const ticker_data_t *_ticker_data;
115+
duration slicetime();
116+
TickerClock::time_point _start; // the start time of the latest slice
117+
duration _time; // any accumulated time from previous slices
118+
TickerClock _ticker_data;
109119
bool _lock_deepsleep; // flag that indicates if deep sleep should be disabled
120+
bool _running = false; // whether the timer is running
110121
};
111122
#endif
112123

drivers/TimerEvent.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919

2020
#include "hal/ticker_api.h"
2121
#include "platform/NonCopyable.h"
22+
#include "drivers/TickerClock.h"
2223

2324
namespace mbed {
25+
2426
/**
2527
* \defgroup drivers_TimerEvent TimerEvent class
2628
* \ingroup drivers-public-api-ticker
@@ -62,25 +64,57 @@ class TimerEvent : private NonCopyable<TimerEvent> {
6264
* Ticker's present timestamp is used for reference. For timestamps
6365
* from the past the event is scheduled after ticker's overflow.
6466
* For reference @see convert_timestamp
67+
*
68+
* @deprecated use `insert(TickerClock::duration timestamp)`
6569
*/
70+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer microsecond count. For example use `5ms` rather than `5000`.")
6671
void insert(timestamp_t timestamp);
6772

73+
/** Set relative timestamp of the internal event.
74+
* @param timestamp event's us timestamp
75+
*
76+
* @warning
77+
* Do not insert more than one timestamp.
78+
* The same @a event object is used for every @a insert/insert_absolute call.
79+
*
80+
* @warning
81+
* Ticker's present timestamp is used for reference. For timestamps
82+
* from the past the event is scheduled after ticker's overflow.
83+
* For reference @see convert_timestamp
84+
*/
85+
void insert(TickerClock::duration timestamp);
86+
6887
/** Set absolute timestamp of the internal event.
6988
* @param timestamp event's us timestamp
7089
*
7190
* @warning
7291
* Do not insert more than one timestamp.
7392
* The same @a event object is used for every @a insert/insert_absolute call.
93+
*
94+
* @deprecated use `insert_absolute(TickerClock::time_point timestamp)`
7495
*/
96+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer microsecond count. For example use `_ticker_data.now() + 5ms` rather than `ticker_read_us(_ticker_data) + 5000`.")
7597
void insert_absolute(us_timestamp_t timestamp);
7698

99+
/** Set absolute timestamp of the internal event.
100+
* @param timestamp event's us timestamp
101+
*
102+
* @note despite being an absolute time, this API has to use a chrono duration
103+
* rather than a chrono time_point
104+
*
105+
* @warning
106+
* Do not insert more than one timestamp.
107+
* The same @a event object is used for every @a insert/insert_absolute call.
108+
*/
109+
void insert_absolute(TickerClock::time_point timestamp);
110+
77111
/** Remove timestamp.
78112
*/
79113
void remove();
80114

81115
ticker_event_t event;
82116

83-
const ticker_data_t *_ticker_data;
117+
TickerClock _ticker_data;
84118
#endif
85119
};
86120

0 commit comments

Comments
 (0)