µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
os-clocks.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ distribution.
3 * (https://github.com/micro-os-plus)
4 * Copyright (c) 2016-2023 Liviu Ionescu. All rights reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software
7 * for any purpose is hereby granted, under the terms of the MIT license.
8 *
9 * If a copy of the license was not distributed with this file, it can
10 * be obtained from https://opensource.org/licenses/mit/.
11 */
12
13#if defined(OS_USE_OS_APP_CONFIG_H)
14#include <cmsis-plus/os-app-config.h>
15#endif
16
17#include <cmsis-plus/rtos/os.h>
18
19// ----------------------------------------------------------------------------
20
21#if defined(__clang__)
22#pragma clang diagnostic ignored "-Wc++98-compat"
23#endif
24
25// ----------------------------------------------------------------------------
26
27using namespace os;
28using namespace os::rtos;
29
30// ----------------------------------------------------------------------------
31
36void
38{
39 using namespace os::rtos;
40
41#if defined(OS_USE_RTOS_PORT_SCHEDULER)
42 // Prevent scheduler actions before starting it.
43 if (scheduler::started ())
44 {
46 }
47#endif
48
49#if defined(OS_TRACE_RTOS_SYSCLOCK_TICK)
50 trace::putchar ('.');
51#elif defined(OS_TRACE_RTOS_SYSCLOCK_TICK_BRACES)
52 trace::printf ("{t ");
53#endif
54
55 {
56 // ----- Enter critical section -----------------------------------------
58
59 sysclock.internal_increment_count ();
61 // ----- Exit critical section ------------------------------------------
62 }
63 sysclock.internal_check_timestamps ();
64 hrclock.internal_check_timestamps ();
65
66#if !defined(OS_INCLUDE_RTOS_REALTIME_CLOCK_DRIVER)
67
68 // Simulate an RTC driver.
69 static uint32_t ticks = clock_systick::frequency_hz;
70
71 if (--ticks == 0)
72 {
74
76 }
77
78#endif /* !defined(OS_INCLUDE_RTOS_REALTIME_CLOCK_DRIVER) */
79
80#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
81
83
84#endif /* !defined(OS_USE_RTOS_PORT_SCHEDULER) */
85
86#if defined(OS_TRACE_RTOS_SYSCLOCK_TICK_BRACES)
87 trace::printf (" t}");
88#endif
89}
90
95void
97{
98
99#if defined(OS_USE_RTOS_PORT_SCHEDULER)
100 // Prevent scheduler actions before starting it.
101 if (scheduler::started ())
102 {
104 }
105#endif
106
107#if defined(OS_TRACE_RTOS_RTC_TICK)
108 trace_putchar ('!');
109#endif
110
111 {
112 // ----- Enter critical section -----------------------------------------
114
115 rtclock.internal_increment_count ();
116 // ----- Exit critical section ------------------------------------------
117 }
118
120}
121
122// ----------------------------------------------------------------------------
123
124namespace os
125{
126 namespace rtos
127 {
128
129 // ========================================================================
130
146 {
147 }
148
153 void
155 {
156 }
157
163 {
164 // ----- Enter critical section -----------------------------------------
166
167 // Prevent inconsistent values using the critical section.
168 return steady_count_;
169 // ----- Exit critical section ------------------------------------------
170 }
171
177 {
178 // ----- Enter critical section -----------------------------------------
180
181 // Prevent inconsistent values using the critical section.
182 return steady_count_;
183 // ----- Exit critical section ------------------------------------------
184 }
185
191 {
192#if defined(OS_TRACE_RTOS_CLOCKS)
193
194#pragma GCC diagnostic push
195#if defined(__clang__)
196#elif defined(__GNUC__)
197#pragma GCC diagnostic ignored "-Wuseless-cast"
198#endif
199 trace::printf ("%s(%u) %p %s\n", __func__,
200 static_cast<unsigned int> (duration),
202#pragma GCC diagnostic pop
203
204#endif // defined(OS_TRACE_RTOS_CLOCKS)
205
206 // Don't call this from interrupt handlers.
208 // Don't call this from critical regions.
210
211 clock::timestamp_t timestamp = steady_now () + duration;
212 for (;;)
213 {
214 result_t res;
215 res = internal_wait_until_ (timestamp, steady_list_);
216
217 timestamp_t n = steady_now ();
218 if (n >= timestamp)
219 {
220 return ETIMEDOUT;
221 }
222
223 if (this_thread::thread ().interrupted ())
224 {
225 return EINTR;
226 }
227
228 if (res != result::ok)
229 {
230 return res;
231 }
232 }
233 return ENOTRECOVERABLE;
234 }
235
241 {
242#if defined(OS_TRACE_RTOS_CLOCKS)
243 trace::printf ("%s()\n", __func__);
244#endif
245
246 // Don't call this from interrupt handlers.
248 // Don't call this from critical regions.
250
251 for (;;)
252 {
253 result_t res;
254 res = internal_wait_until_ (timestamp, steady_list_);
255
256 timestamp_t nw = now ();
257 if (nw >= timestamp)
258 {
259 return ETIMEDOUT;
260 }
261
262 if (this_thread::thread ().interrupted ())
263 {
264 return EINTR;
265 }
266
267 if (res != result::ok)
268 {
269 return res;
270 }
271 }
272 return ENOTRECOVERABLE;
273 }
274
280 {
281#if defined(OS_TRACE_RTOS_CLOCKS)
282
283#pragma GCC diagnostic push
284#if defined(__clang__)
285#elif defined(__GNUC__)
286#pragma GCC diagnostic ignored "-Wuseless-cast"
287#endif
288 trace::printf ("%s(%u)\n", __func__, static_cast<unsigned int> (timeout));
289#pragma GCC diagnostic pop
290
291#endif // defined(OS_TRACE_RTOS_CLOCKS)
292
293 // Don't call this from interrupt handlers.
295 // Don't call this from critical regions.
297
298 clock::timestamp_t timestamp = steady_now () + timeout;
299
300 result_t res;
301 res = internal_wait_until_ (timestamp, steady_list_);
302
303 timestamp_t nw = steady_now ();
304 if (nw >= timestamp)
305 {
306 return ETIMEDOUT;
307 }
308
309 if (this_thread::thread ().interrupted ())
310 {
311 return EINTR;
312 }
313
314 return res;
315 }
316
330 {
331 // ----- Enter critical section -----------------------------------------
333
334#pragma GCC diagnostic push
335#if defined(__clang__)
336#pragma clang diagnostic ignored "-Wdeprecated-volatile"
337#elif defined(__GNUC__)
338#pragma GCC diagnostic ignored "-Wvolatile"
339#endif
340 steady_count_ += duration;
341#pragma GCC diagnostic pop
342
343 internal_check_timestamps ();
344 return steady_count_;
345 // ----- Exit critical section ------------------------------------------
346 }
347
353 clock::offset (void)
354 {
355 return 0;
356 }
357
359 clock::offset (offset_t offset __attribute__((unused)))
360 {
361 return 0;
362 }
363
364#pragma GCC diagnostic push
365#if defined(__clang__)
366#elif defined(__GNUC__)
367#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
368#pragma GCC diagnostic ignored "-Wsuggest-final-types"
369#endif
371 clock::internal_wait_until_ (timestamp_t timestamp,
373 {
374 thread& crt_thread = this_thread::thread ();
375
376 // Prepare a list node pointing to the current thread.
377 // Do not worry for being on stack, it is temporarily linked to the
378 // list and guaranteed to be removed before this function returns.
380 { timestamp, crt_thread };
381
382 {
383 // ----- Enter critical section -------------------------------------
385
386 // Remove this thread from the ready list, if there.
388
389 // Add this thread to the clock waiting list.
390 list.link (node);
391 crt_thread.clock_node_ = &node;
392 crt_thread.state_ = thread::state::suspended;
393 // ----- Exit critical section --------------------------------------
394 }
395
397
398 {
399 // ----- Enter critical section -------------------------------------
401
402 // Remove the thread from the clock timeout list,
403 // if not already removed by the timer.
404 crt_thread.clock_node_ = nullptr;
405 node.unlink ();
406 // ----- Exit critical section --------------------------------------
407 }
408
409 return result::ok;
410 }
411#pragma GCC diagnostic pop
412
417 // ========================================================================
422 {
423 }
424
428#pragma GCC diagnostic push
429#if defined(__clang__)
430#elif defined(__GNUC__)
431#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
432#endif
435 {
436 // Prevent inconsistent values.
437 // ----- Enter critical section -----------------------------------------
439
440#pragma GCC diagnostic push
441#if defined(__clang__)
442#pragma clang diagnostic ignored "-Wsign-conversion"
443#elif defined(__GNUC__)
444#pragma GCC diagnostic ignored "-Wsign-conversion"
445#endif
446 return steady_count_ + offset_;
447#pragma GCC diagnostic pop
448 // ----- Exit critical section ------------------------------------------
449 }
450#pragma GCC diagnostic pop
451
457 {
458#if defined(OS_TRACE_RTOS_CLOCKS)
459 trace::printf ("%s()\n", __func__);
460#endif
461
462 // Don't call this from interrupt handlers.
464 // Don't call this from critical regions.
466
467 for (;;)
468 {
469 result_t res;
470 res = internal_wait_until_ (timestamp, adjusted_list_);
471
472 timestamp_t nw = now ();
473 if (nw >= timestamp)
474 {
475 return ETIMEDOUT;
476 }
477
478 if (this_thread::thread ().interrupted ())
479 {
480 return EINTR;
481 }
482
483 if (res != result::ok)
484 {
485 return res;
486 }
487 }
488 return ENOTRECOVERABLE;
489 }
490
496 {
497 return offset_;
498 }
499
505 {
506 // ----- Enter critical section -----------------------------------------
508
509 offset_t tmp;
510 tmp = offset_;
511 offset_ = value;
512
513 return tmp;
514 // ----- Exit critical section ------------------------------------------
515 }
516
517 // ========================================================================
518
556 // ------------------------------------------------------------------------
557#pragma GCC diagnostic push
558#if defined(__clang__)
559#pragma clang diagnostic ignored "-Wglobal-constructors"
560#pragma clang diagnostic ignored "-Wexit-time-destructors"
561#endif
566#pragma GCC diagnostic pop
567
568 // ------------------------------------------------------------------------
569
574 clock
575 { "sysclock" }
576 {
577 }
578
583 {
584 }
585
589 void
591 {
592#if defined(OS_TRACE_RTOS_CLOCKS)
593 trace::printf ("clock_systick::%s()\n", __func__);
594#endif
596 }
597
598 // ------------------------------------------------------------------------
599
600#if defined(OS_USE_RTOS_PORT_CLOCK_SYSTICK_WAIT_FOR)
601
603 clock_systick::internal_wait_until_ (timestamp_t timestamp,
604 internal::clock_timestamps_list& list __attribute__((unused)))
605 {
606 result_t res;
607
608 timestamp_t nw = now ();
609 if (nw >= timestamp)
610 {
611 return result::ok;
612 }
613 duration_t ticks = ((duration_t) (timestamp - nw));
614 res = port::clock_systick::wait_for (ticks);
615 return res;
616 }
617
618#endif /* defined(OS_USE_RTOS_PORT_CLOCK_SYSTICK_WAIT_FOR) */
619
620 // ========================================================================
621
657 // ------------------------------------------------------------------------
658#pragma GCC diagnostic push
659#if defined(__clang__)
660#pragma clang diagnostic ignored "-Wglobal-constructors"
661#pragma clang diagnostic ignored "-Wexit-time-destructors"
662#endif
667#pragma GCC diagnostic pop
668
669 // ------------------------------------------------------------------------
670
676 { "rtclock" }
677 {
678 }
679
684 {
685 }
686
687 // ------------------------------------------------------------------------
688
695 void
697 {
698#if defined(OS_TRACE_RTOS_CLOCKS)
699 trace::printf ("clock_rtc::%s()\n", __func__);
700#endif
701 // Don't call this from interrupt handlers.
702 assert (!interrupts::in_handler_mode ());
703
704 // TODO: Use the RTC driver to initialise the seconds to epoch.
705 }
706
707 // ========================================================================
708
709#pragma GCC diagnostic push
710#if defined(__clang__)
711#pragma clang diagnostic ignored "-Wglobal-constructors"
712#pragma clang diagnostic ignored "-Wexit-time-destructors"
713#endif
718#pragma GCC diagnostic pop
719
720 // ------------------------------------------------------------------------
721
726 clock
727 { "hrclock" }
728 {
729 }
730
735 {
736 }
737
741 void
743 {
744#if defined(OS_TRACE_RTOS_CLOCKS)
745 trace::printf ("clock_highres::%s()\n", __func__);
746#endif
747
749 }
750
753 {
754 // ----- Enter critical section -----------------------------------------
756
757 return steady_count_ + port::clock_highres::cycles_since_tick ();
758 // ----- Exit critical section ------------------------------------------
759 }
760
761 // --------------------------------------------------------------------------
762
763 } /* namespace rtos */
764} /* namespace os */
765
766// ----------------------------------------------------------------------------
Adjustable (non-steady) clock.
Definition os-clocks.h:323
virtual ~adjustable_clock() override
Destruct the clock object instance.
virtual timestamp_t now(void) override
Tell the current time adjusted for epoch.
virtual result_t sleep_until(timestamp_t timestamp) override
Sleep until an absolute timestamp.
virtual offset_t offset(void) override
Get adjustment offset.
void internal_check_timestamps(void)
High Resolution derived clock.
Definition os-clocks.h:706
void internal_increment_count(void)
Definition os-clocks.h:917
virtual ~clock_highres() override
Destruct the SysTick clock object instance.
virtual void start(void) override
clock_highres()
Construct a SysTick clock object instance.
virtual timestamp_t now(void) override
Tell the current time.
Real time clock.
Definition os-clocks.h:591
virtual void start(void) override
Initialise and make the RTC tick.
virtual ~clock_rtc() override
Destruct the real time clock object instance.
clock_rtc()
Construct a real time clock object instance.
SysTick derived clock.
Definition os-clocks.h:461
static constexpr uint32_t frequency_hz
SysTick frequency in Hz.
Definition os-clocks.h:472
virtual ~clock_systick() override
Destruct the SysTick clock object instance.
clock_systick()
Construct a SysTick clock object instance.
virtual void start(void) override
Generic clock.
Definition os-clocks.h:59
result_t wait_for(duration_t timeout)
Timed wait for an event.
virtual result_t sleep_until(timestamp_t timestamp)
Sleep until an absolute timestamp.
timestamp_t update_for_slept_time(duration_t duration)
Increase the internal count after a deep sleep.
timestamp_t steady_now(void)
Tell the current time since startup.
virtual timestamp_t now(void)
Tell the current time, possibly adjusted for epoch.
virtual void start(void)=0
Start the clock.
virtual ~clock()
Destruct the clock object instance.
result_t sleep_for(duration_t duration)
Sleep for a relative duration.
Ordered list of time stamp nodes.
Definition os-lists.h:671
void link(timestamp_node &node)
Add a new thread node to the list.
Definition os-lists.cpp:414
const char * name(void) const
Get object name.
Definition os-decls.h:759
Double linked list node, with time stamp and thread.
Definition os-lists.h:223
Interrupts critical section RAII helper.
Definition os-sched.h:498
static uint32_t cycles_since_tick(void)
static void internal_interrupt_service_routine(void)
RTC implementation hook.
static result_t wait_for(clock::duration_t ticks)
static void internal_interrupt_service_routine(void)
SysTick implementation hook.
Standard thread.
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:60
int putchar(int c)
Write the single character to the trace device.
Definition trace.cpp:121
void os_systick_handler(void)
SysTick interrupt handler.
Definition os-clocks.cpp:37
void os_rtc_handler(void)
RTC interrupt handler.
Definition os-clocks.cpp:96
port::clock::duration_t duration_t
Type of variables holding clock durations.
Definition os-clocks.h:76
clock_highres hrclock
The high resolution clock object instance.
clock_rtc rtclock
The real time clock object instance.
port::clock::timestamp_t timestamp_t
Type of variables holding clock time stamps.
Definition os-clocks.h:85
clock_systick sysclock
The system clock object instance.
port::clock::offset_t offset_t
Type of variables holding clock offsets.
Definition os-clocks.h:95
bool in_handler_mode(void)
Check if the CPU is in handler mode.
Definition os-sched.h:1108
@ ok
Function completed; no errors or events occurred.
Definition os-decls.h:181
bool started(void)
Check if the scheduler was started.
Definition os-sched.h:827
bool locked(void)
Check if the scheduler is locked.
Definition os-sched.h:856
thread & thread(void)
Get the current running thread.
RTOS namespace.
Definition os-flags.h:38
uint32_t result_t
Type of values returned by RTOS functions.
Definition os-decls.h:96
System namespace.
#define os_assert_err(__e, __er)
Assert or return an error.
Definition os-decls.h:1115
Single file µOS++ RTOS definitions.
@ suspended
Not present in the READY list, waiting for an event.
Definition os-thread.h:389
int trace_putchar(int c)