rtmlib
time_compat.h
Go to the documentation of this file.
1 /*
2  * rtmlib is a Real-Time Monitoring Library.
3  *
4  * Copyright (C) 2018-2020 AndrĂ© Pedro
5  *
6  * This file is part of rtmlib.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef _TIME_COMPAT_H_
23 #define _TIME_COMPAT_H_
24 
25 #include "atomic_compat.h"
26 
27 #ifdef __HW__
28 
29 typedef long long timeabs;
30 typedef long timespan;
31 
32 #define clockgettime() 0
33 
34 #elif (__NUTTX__)
35 #include <nuttx/clock.h>
36 
37 /*
38  * We may interpret timestamps as uint8_t, uint16_t, uint24_t, uint32_t, and
39  * uint64_t.
40  *
41  * - uint8_t only contains 255 ticks and is small; It means that we have to
42  * execute the monitors as fast as 255 ticks, inducing a huge overhead.
43  *
44  * - uint16_t can be enough for faster monitors (the Cortex-M is excluded)
45  *
46  * - uint24_t is enough if the monitor has a period no bigger than 100hz
47  *
48  * - uint32_t is enough if the monitor has a period no bigger than 1hz
49  *
50  * - for all the other cases uint64_t is required
51  *
52  * In this note, the timestamps are measured in nanoseconds.
53  */
54 typedef uint64_t timeabs;
55 typedef uint32_t timespan;
56 
57 #define NOP __NOP()
58 
59 // we need to adjust the systick when is triggering the IRQ
60 #define clockgettime() \
61  ({ \
62  ISB timespan ns = SysTick->VAL; \
63  uint64_t ms = g_system_timer; \
64  ISB(ms * 1000000) + ((1000000. / SysTick->LOAD) * (SysTick->LOAD - ns)); \
65  })
66 
67 // get cpu_clock
68 // assuming 168mhz 1000000000/(168000000/167999)
69 // (1000000000/(clock/SysTick->LOAD))/SysTick->LOAD currently ~= 5.5(5)ns
70 
71 #elif defined(__x86__) || defined(__x86_64__)
72 
73 #include <pthread.h>
74 #include <time.h>
75 
76 typedef long long timeabs;
77 typedef long timespan;
78 
79 #define clockgettime() \
80  ({ \
81  struct timespec __n; \
82  clock_gettime(CLOCK_REALTIME, &__n); \
83  uint64_t result = __n.tv_sec; \
84  (result * 1000000000) + (__n.tv_nsec); \
85  })
86 
87 #else
88 
89 #error \
90  "This monitoring library only supports NuttX ARM Cortex-M4 and x86 architecture!"
91 
92 #endif
93 
94 typedef timeabs timespanw;
95 
96 /* Operations on timespecs. */
97 #define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0
98 
99 #define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec)
100 
101 #define timespeccmp(tsp, usp, cmp) \
102  (((tsp)->tv_sec == (usp)->tv_sec) ? ((tsp)->tv_nsec cmp(usp)->tv_nsec) \
103  : ((tsp)->tv_sec cmp(usp)->tv_sec))
104 
105 #define timespecadd(tsp, usp, vsp) \
106  do { \
107  (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \
108  (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \
109  if ((vsp)->tv_nsec >= 1000000000L) { \
110  (vsp)->tv_sec++; \
111  (vsp)->tv_nsec -= 1000000000L; \
112  } \
113  } while (0)
114 
115 #define timespecsub(tsp, usp, vsp) \
116  do { \
117  (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
118  (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
119  if ((vsp)->tv_nsec < 0) { \
120  (vsp)->tv_sec--; \
121  (vsp)->tv_nsec += 1000000000L; \
122  } \
123  } while (0)
124 
125 #define useconds_t2timespec(tsp, vsp) \
126  do { \
127  (vsp)->tv_sec = *tsp / 1000000L; \
128  (vsp)->tv_nsec = (*tsp % 1000000L) * 1000; \
129  } while (0)
130 
131 #endif //_TIME_COMPAT_H_
timeabs timespanw
Definition: time_compat.h:94