@@ -42,25 +42,61 @@ extern OsTimer *os_timer;
42
42
OsTimer *init_os_timer ();
43
43
44
44
/* * A C++11 chrono TrivialClock for os_timer
45
+ *
46
+ * Due to the nature of OsTimer/SysTimer, this does not have a single `now` method, but has
47
+ * multiple ways to report the current state:
48
+ *
49
+ * High-res timeline -------------------------------------------------------------
50
+ * Ticks | a | b | b | b | c | c | c | c | c | d ^
51
+ * ^ ^ ^ os_timer->get_time()
52
+ * acknowledged_ticks() reported_ticks() now()
53
+ *
54
+ * (a) is time read from hardware by OsTimer, reported to the user of OsTimer, and acknowledged by that user.
55
+ * (b) is time read from hardware by OsTimer, reported to the user of OsTimer, but not yet acknowledged.
56
+ * (c) is time already elapsed in the hardware but yet to be read and processed as ticks by OsTimer.
57
+ * (d) is time already elapsed in the hardware that doesn't yet form a tick.
58
+ *
59
+ * Time is "reported" either by:
60
+ * * calls to the OsTimer's handler following start_tick - these must be acknowledged
61
+ * * the result of OsTimer::update_and_get_tick() / OsClock::now() - calling this implies acknowledgment.
62
+ *
63
+ * As such `now()` is used when the ticker is not in use - it processes ticks that would have been
64
+ * processed by the tick handler. If the ticker is in uses `reported_ticks` or `acknowleged_ticks` must be used.
45
65
*
46
66
* @note To fit better into the chrono framework, OsClock uses
47
67
* chrono::milliseconds as its representation, which makes it signed
48
- * and at least 45 bits (so it will be int64_t or equivalent).
68
+ * and at least 45 bits, so it will be int64_t or equivalent, unlike
69
+ * OsTimer which uses uint64_t rep.
49
70
*/
50
71
struct OsClock {
51
72
/* Standard TrivialClock fields */
52
- using duration = std::chrono::milliseconds ;
53
- using rep = duration ::rep;
54
- using period = duration:: period;
73
+ using period = OsTimer::period ;
74
+ using rep = std::chrono::milliseconds ::rep;
75
+ using duration = std::chrono::duration<rep, period>; // == std::chrono::milliseconds, if period is std::milli
55
76
using time_point = std::chrono::time_point<OsClock, duration>;
56
77
static constexpr bool is_steady = true ;
78
+ // Read the hardware, and return the updated time_point.
79
+ // Initialize the timing system if necessary - this could be the first call.
80
+ // See SysTimer::update_and_get_tick for more details.
57
81
static time_point now ()
58
82
{
59
83
// We are a real Clock with a well-defined epoch. As such we distinguish ourselves
60
84
// from the less-well-defined SysTimer pseudo-Clock. This means our time_points
61
85
// are not convertible, so need to fiddle here.
62
86
return time_point (init_os_timer ()->update_and_get_tick ().time_since_epoch ());
63
87
}
88
+ // Return the current reported tick count, without update.
89
+ // Assumes timer has already been initialized, as ticker should have been in use to
90
+ // keep that tick count up-to-date. See SysTimer::get_tick for more details.
91
+ static time_point reported_ticks ()
92
+ {
93
+ return time_point (os_timer->get_tick ().time_since_epoch ());
94
+ }
95
+ // Return the acknowledged tick count.
96
+ static time_point acknowledged_ticks ()
97
+ {
98
+ return reported_ticks () - os_timer->unacknowledged_ticks ();
99
+ }
64
100
// Slightly-optimised variant of OsClock::now() that assumes os_timer is initialised.
65
101
static time_point now_with_init_done ()
66
102
{
@@ -81,7 +117,7 @@ OsClock::time_point do_timed_sleep_absolute(OsClock::time_point wake_time, bool
81
117
#if MBED_CONF_RTOS_PRESENT
82
118
/* Maximum sleep time is 2^32-1 ticks; timer is always set to achieve this */
83
119
/* Assumes that ticker has been in use prior to call, so restricted to RTOS use */
84
- OsClock::duration_u32 do_timed_sleep_relative (OsClock::duration_u32 wake_delay, bool (*wake_predicate)(void *) = NULL, void *wake_predicate_handle = NULL);
120
+ OsClock::duration_u32 do_timed_sleep_relative_to_acknowledged_ticks (OsClock::duration_u32 wake_delay, bool (*wake_predicate)(void *) = NULL, void *wake_predicate_handle = NULL);
85
121
#else
86
122
87
123
void do_untimed_sleep (bool (*wake_predicate)(void *), void *wake_predicate_handle = NULL);
0 commit comments