@@ -42,25 +42,61 @@ extern OsTimer *os_timer;
4242OsTimer *init_os_timer ();
4343
4444/* * 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.
4565 *
4666 * @note To fit better into the chrono framework, OsClock uses
4767 * 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.
4970 */
5071struct OsClock {
5172 /* 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
5576 using time_point = std::chrono::time_point<OsClock, duration>;
5677 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.
5781 static time_point now ()
5882 {
5983 // We are a real Clock with a well-defined epoch. As such we distinguish ourselves
6084 // from the less-well-defined SysTimer pseudo-Clock. This means our time_points
6185 // are not convertible, so need to fiddle here.
6286 return time_point (init_os_timer ()->update_and_get_tick ().time_since_epoch ());
6387 }
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+ }
64100 // Slightly-optimised variant of OsClock::now() that assumes os_timer is initialised.
65101 static time_point now_with_init_done ()
66102 {
@@ -81,7 +117,7 @@ OsClock::time_point do_timed_sleep_absolute(OsClock::time_point wake_time, bool
81117#if MBED_CONF_RTOS_PRESENT
82118/* Maximum sleep time is 2^32-1 ticks; timer is always set to achieve this */
83119/* 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);
85121#else
86122
87123void do_untimed_sleep (bool (*wake_predicate)(void *), void *wake_predicate_handle = NULL);
0 commit comments