µ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 Liviu Ionescu.
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following
13 * conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include <cmsis-plus/rtos/os.h>
29
30// ----------------------------------------------------------------------------
31
32#if defined(__clang__)
33#pragma clang diagnostic ignored "-Wc++98-compat"
34#endif
35
36// ----------------------------------------------------------------------------
37
38using namespace os;
39using namespace os::rtos;
40
41// ----------------------------------------------------------------------------
42
47void
49{
50 using namespace os::rtos;
51
52#if defined(OS_USE_RTOS_PORT_SCHEDULER)
53 // Prevent scheduler actions before starting it.
54 if (scheduler::started ())
55 {
57 }
58#endif
59
60#if defined(OS_TRACE_RTOS_SYSCLOCK_TICK)
61 trace::putchar ('.');
62#endif
63
64 {
65 // ----- Enter critical section -----------------------------------------
67
68 sysclock.internal_increment_count ();
70 // ----- Exit critical section ------------------------------------------
71 }
72 sysclock.internal_check_timestamps ();
73 hrclock.internal_check_timestamps ();
74
75#if !defined(OS_INCLUDE_RTOS_REALTIME_CLOCK_DRIVER)
76
77 // Simulate an RTC driver.
78 static uint32_t ticks = clock_systick::frequency_hz;
79
80 if (--ticks == 0)
81 {
83
85 }
86
87#endif /* !defined(OS_INCLUDE_RTOS_REALTIME_CLOCK_DRIVER) */
88
89#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
90
92
93#endif /* !defined(OS_USE_RTOS_PORT_SCHEDULER) */
94
95#if defined(OS_TRACE_RTOS_SYSCLOCK_TICK)
96 trace::putchar (',');
97#endif
98}
99
104void
106{
107
108#if defined(OS_USE_RTOS_PORT_SCHEDULER)
109 // Prevent scheduler actions before starting it.
110 if (scheduler::started ())
111 {
113 }
114#endif
115
116#if defined(OS_TRACE_RTOS_RTC_TICK)
117 trace_putchar ('!');
118#endif
119
120 {
121 // ----- Enter critical section -----------------------------------------
123
124 rtclock.internal_increment_count ();
125 // ----- Exit critical section ------------------------------------------
126 }
127
129}
130
131// ----------------------------------------------------------------------------
132
133namespace os
134{
135 namespace rtos
136 {
137
138 // ========================================================================
139
155 {
156 ;
157 }
158
163 void
165 {
166 ;
167 }
168
174 {
175 // ----- Enter critical section -----------------------------------------
177
178 // Prevent inconsistent values using the critical section.
179 return steady_count_;
180 // ----- Exit critical section ------------------------------------------
181 }
182
188 {
189 // ----- Enter critical section -----------------------------------------
191
192 // Prevent inconsistent values using the critical section.
193 return steady_count_;
194 // ----- Exit critical section ------------------------------------------
195 }
196
202 {
203#if defined(OS_TRACE_RTOS_CLOCKS)
204 trace::printf ("%s(%u) %p %s\n", __func__,
205 static_cast<unsigned int> (duration),
207#endif
208
209 // Don't call this from interrupt handlers.
211 // Don't call this from critical regions.
213
214 clock::timestamp_t timestamp = steady_now () + duration;
215 for (;;)
216 {
217 result_t res;
218 res = internal_wait_until_ (timestamp, steady_list_);
219
220 timestamp_t n = steady_now ();
221 if (n >= timestamp)
222 {
223 return ETIMEDOUT;
224 }
225
226 if (this_thread::thread ().interrupted ())
227 {
228 return EINTR;
229 }
230
231 if (res != result::ok)
232 {
233 return res;
234 }
235 }
236 return ENOTRECOVERABLE;
237 }
238
244 {
245#if defined(OS_TRACE_RTOS_CLOCKS)
246 trace::printf ("%s()\n", __func__);
247#endif
248
249 // Don't call this from interrupt handlers.
251 // Don't call this from critical regions.
253
254 for (;;)
255 {
256 result_t res;
257 res = internal_wait_until_ (timestamp, steady_list_);
258
259 timestamp_t nw = now ();
260 if (nw >= timestamp)
261 {
262 return ETIMEDOUT;
263 }
264
265 if (this_thread::thread ().interrupted ())
266 {
267 return EINTR;
268 }
269
270 if (res != result::ok)
271 {
272 return res;
273 }
274 }
275 return ENOTRECOVERABLE;
276 }
277
283 {
284#if defined(OS_TRACE_RTOS_CLOCKS)
285 trace::printf ("%s(%u)\n", __func__, static_cast<unsigned int> (timeout));
286#endif
287
288 // Don't call this from interrupt handlers.
290 // Don't call this from critical regions.
292
293 clock::timestamp_t timestamp = steady_now () + timeout;
294
295 result_t res;
296 res = internal_wait_until_ (timestamp, steady_list_);
297
298 timestamp_t nw = steady_now ();
299 if (nw >= timestamp)
300 {
301 return ETIMEDOUT;
302 }
303
304 if (this_thread::thread ().interrupted ())
305 {
306 return EINTR;
307 }
308
309 return res;
310 }
311
325 {
326 // ----- Enter critical section -----------------------------------------
328
329#pragma GCC diagnostic push
330#if defined(__clang__)
331#pragma clang diagnostic ignored "-Wdeprecated-volatile"
332#endif
333 steady_count_ += duration;
334#pragma GCC diagnostic pop
335
336 internal_check_timestamps ();
337 return steady_count_;
338 // ----- Exit critical section ------------------------------------------
339 }
340
346 clock::offset (void)
347 {
348 return 0;
349 }
350
352 clock::offset (offset_t offset __attribute__((unused)))
353 {
354 return 0;
355 }
356
358 clock::internal_wait_until_ (timestamp_t timestamp,
360 {
361 thread& crt_thread = this_thread::thread ();
362
363 // Prepare a list node pointing to the current thread.
364 // Do not worry for being on stack, it is temporarily linked to the
365 // list and guaranteed to be removed before this function returns.
367 { timestamp, crt_thread };
368
369 {
370 // ----- Enter critical section -------------------------------------
372
373 // Remove this thread from the ready list, if there.
375
376 // Add this thread to the clock waiting list.
377 list.link (node);
378 crt_thread.clock_node_ = &node;
379 crt_thread.state_ = thread::state::suspended;
380 // ----- Exit critical section --------------------------------------
381 }
382
384
385 {
386 // ----- Enter critical section -------------------------------------
388
389 // Remove the thread from the clock timeout list,
390 // if not already removed by the timer.
391 crt_thread.clock_node_ = nullptr;
392 node.unlink ();
393 // ----- Exit critical section --------------------------------------
394 }
395
396 return result::ok;
397 }
398
403 // ========================================================================
408 {
409 ;
410 }
411
417 {
418 // Prevent inconsistent values.
419 // ----- Enter critical section -----------------------------------------
421
422#pragma GCC diagnostic push
423#pragma GCC diagnostic ignored "-Wsign-conversion"
424 return steady_count_ + offset_;
425#pragma GCC diagnostic pop
426 // ----- Exit critical section ------------------------------------------
427 }
428
434 {
435#if defined(OS_TRACE_RTOS_CLOCKS)
436 trace::printf ("%s()\n", __func__);
437#endif
438
439 // Don't call this from interrupt handlers.
441 // Don't call this from critical regions.
443
444 for (;;)
445 {
446 result_t res;
447 res = internal_wait_until_ (timestamp, adjusted_list_);
448
449 timestamp_t nw = now ();
450 if (nw >= timestamp)
451 {
452 return ETIMEDOUT;
453 }
454
455 if (this_thread::thread ().interrupted ())
456 {
457 return EINTR;
458 }
459
460 if (res != result::ok)
461 {
462 return res;
463 }
464 }
465 return ENOTRECOVERABLE;
466 }
467
473 {
474 return offset_;
475 }
476
482 {
483 // ----- Enter critical section -----------------------------------------
485
486 offset_t tmp;
487 tmp = offset_;
488 offset_ = value;
489
490 return tmp;
491 // ----- Exit critical section ------------------------------------------
492 }
493
494 // ========================================================================
495
533 // ------------------------------------------------------------------------
534#pragma GCC diagnostic push
535#if defined(__clang__)
536#pragma clang diagnostic ignored "-Wglobal-constructors"
537#pragma clang diagnostic ignored "-Wexit-time-destructors"
538#endif
543#pragma GCC diagnostic pop
544
545 // ------------------------------------------------------------------------
546
551 clock
552 { "sysclock" }
553 {
554 ;
555 }
556
561 {
562 ;
563 }
564
568 void
570 {
571#if defined(OS_TRACE_RTOS_CLOCKS)
572 trace::printf ("clock_systick::%s()\n", __func__);
573#endif
575 }
576
577 // ------------------------------------------------------------------------
578
579#if defined(OS_USE_RTOS_PORT_CLOCK_SYSTICK_WAIT_FOR)
580
582 clock_systick::internal_wait_until_ (timestamp_t timestamp,
583 internal::clock_timestamps_list& list __attribute__((unused)))
584 {
585 result_t res;
586
587 timestamp_t nw = now ();
588 if (nw >= timestamp)
589 {
590 return result::ok;
591 }
592 duration_t ticks = ((duration_t) (timestamp - nw));
593 res = port::clock_systick::wait_for (ticks);
594 return res;
595 }
596
597#endif /* defined(OS_USE_RTOS_PORT_CLOCK_SYSTICK_WAIT_FOR) */
598
599 // ========================================================================
600
636 // ------------------------------------------------------------------------
637#pragma GCC diagnostic push
638#if defined(__clang__)
639#pragma clang diagnostic ignored "-Wglobal-constructors"
640#pragma clang diagnostic ignored "-Wexit-time-destructors"
641#endif
646#pragma GCC diagnostic pop
647
648 // ------------------------------------------------------------------------
649
655 { "rtclock" }
656 {
657 ;
658 }
659
664 {
665 ;
666 }
667
668 // ------------------------------------------------------------------------
669
676 void
678 {
679#if defined(OS_TRACE_RTOS_CLOCKS)
680 trace::printf ("clock_rtc::%s()\n", __func__);
681#endif
682 // Don't call this from interrupt handlers.
683 assert (!interrupts::in_handler_mode ());
684
685 // TODO: Use the RTC driver to initialise the seconds to epoch.
686 }
687
688 // ========================================================================
689
690#pragma GCC diagnostic push
691#if defined(__clang__)
692#pragma clang diagnostic ignored "-Wglobal-constructors"
693#pragma clang diagnostic ignored "-Wexit-time-destructors"
694#endif
699#pragma GCC diagnostic pop
700
701 // ------------------------------------------------------------------------
702
707 clock
708 { "hrclock" }
709 {
710 ;
711 }
712
717 {
718 ;
719 }
720
724 void
726 {
727#if defined(OS_TRACE_RTOS_CLOCKS)
728 trace::printf ("clock_highres::%s()\n", __func__);
729#endif
730
732 }
733
736 {
737 // ----- Enter critical section -----------------------------------------
739
740 return steady_count_ + port::clock_highres::cycles_since_tick ();
741 // ----- Exit critical section ------------------------------------------
742 }
743
744 // --------------------------------------------------------------------------
745
746 } /* namespace rtos */
747} /* namespace os */
748
749// ----------------------------------------------------------------------------
Adjustable (non-steady) clock.
Definition os-clocks.h:331
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:714
void internal_increment_count(void)
Definition os-clocks.h:921
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:599
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:469
static constexpr uint32_t frequency_hz
SysTick frequency in Hz.
Definition os-clocks.h:480
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:66
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:392
const char * name(void) const
Get object name.
Definition os-decls.h:774
Double linked list node, with time stamp and thread.
Definition os-lists.h:227
Interrupts critical section RAII helper.
Definition os-sched.h:524
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:74
int putchar(int c)
Write the single character to the trace device.
Definition trace.cpp:126
void os_systick_handler(void)
SysTick interrupt handler.
Definition os-clocks.cpp:48
void os_rtc_handler(void)
RTC interrupt handler.
port::clock::duration_t duration_t
Type of variables holding clock durations.
Definition os-clocks.h:83
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:92
clock_systick sysclock
The system clock object instance.
port::clock::offset_t offset_t
Type of variables holding clock offsets.
Definition os-clocks.h:102
bool in_handler_mode(void)
Check if the CPU is in handler mode.
Definition os-sched.h:1136
@ ok
Function completed; no errors or events occurred.
Definition os-decls.h:195
bool started(void)
Check if the scheduler was started.
Definition os-sched.h:853
bool locked(void)
Check if the scheduler is locked.
Definition os-sched.h:882
thread & thread(void)
Get the current running thread.
RTOS namespace.
Definition os-flags.h:54
uint32_t result_t
Type of values returned by RTOS functions.
Definition os-decls.h:110
System namespace.
#define os_assert_err(__e, __er)
Assert or return an error.
Definition os-decls.h:1126
Single file µOS++ RTOS definitions.
@ suspended
Not present in the READY list, waiting for an event.
Definition os-thread.h:386
int trace_putchar(int c)