Line data Source code
1 1 : /* 2 : * Copyright (c) 2014-2015 Wind River Systems, Inc. 3 : * 4 : * SPDX-License-Identifier: Apache-2.0 5 : */ 6 : 7 : /** 8 : * @file 9 : * @brief Variables needed for system clock 10 : * 11 : * 12 : * Declare variables used by both system timer device driver and kernel 13 : * components that use timer functionality. 14 : */ 15 : 16 : #ifndef ZEPHYR_INCLUDE_SYS_CLOCK_H_ 17 : #define ZEPHYR_INCLUDE_SYS_CLOCK_H_ 18 : 19 : #include <zephyr/sys/util.h> 20 : #include <zephyr/sys/dlist.h> 21 : 22 : #include <zephyr/toolchain.h> 23 : #include <zephyr/types.h> 24 : 25 : #include <zephyr/sys/time_units.h> 26 : 27 : #ifdef __cplusplus 28 : extern "C" { 29 : #endif 30 : 31 : /** 32 : * @addtogroup clock_apis 33 : * @{ 34 : */ 35 : 36 : /** 37 : * @brief Tick precision used in timeout APIs 38 : * 39 : * This type defines the word size of the timeout values used in 40 : * k_timeout_t objects, and thus defines an upper bound on maximum 41 : * timeout length (or equivalently minimum tick duration). Note that 42 : * this does not affect the size of the system uptime counter, which 43 : * is always a 64 bit count of ticks. 44 : */ 45 : #ifdef CONFIG_TIMEOUT_64BIT 46 : typedef int64_t k_ticks_t; 47 : #else 48 1 : typedef uint32_t k_ticks_t; 49 : #endif 50 : 51 0 : #define K_TICKS_FOREVER ((k_ticks_t) -1) 52 : 53 : /** 54 : * @brief Kernel timeout type 55 : * 56 : * Timeout arguments presented to kernel APIs are stored in this 57 : * opaque type, which is capable of representing times in various 58 : * formats and units. It should be constructed from application data 59 : * using one of the macros defined for this purpose (e.g. `K_MSEC()`, 60 : * `K_TIMEOUT_ABS_TICKS()`, etc...), or be one of the two constants 61 : * K_NO_WAIT or K_FOREVER. Applications should not inspect the 62 : * internal data once constructed. Timeout values may be compared for 63 : * equality with the `K_TIMEOUT_EQ()` macro. 64 : */ 65 1 : typedef struct { 66 0 : k_ticks_t ticks; 67 : } k_timeout_t; 68 : 69 : /** 70 : * @brief Compare timeouts for equality 71 : * 72 : * The k_timeout_t object is an opaque struct that should not be 73 : * inspected by application code. This macro exists so that users can 74 : * test timeout objects for equality with known constants 75 : * (e.g. K_NO_WAIT and K_FOREVER) when implementing their own APIs in 76 : * terms of Zephyr timeout constants. 77 : * 78 : * @return True if the timeout objects are identical 79 : */ 80 1 : #define K_TIMEOUT_EQ(a, b) ((a).ticks == (b).ticks) 81 : 82 : /** number of nanoseconds per micorsecond */ 83 1 : #define NSEC_PER_USEC 1000U 84 : 85 : /** number of nanoseconds per millisecond */ 86 1 : #define NSEC_PER_MSEC 1000000U 87 : 88 : /** number of microseconds per millisecond */ 89 1 : #define USEC_PER_MSEC 1000U 90 : 91 : /** number of milliseconds per second */ 92 1 : #define MSEC_PER_SEC 1000U 93 : 94 : /** number of seconds per minute */ 95 1 : #define SEC_PER_MIN 60U 96 : 97 : /** number of seconds per hour */ 98 1 : #define SEC_PER_HOUR 3600U 99 : 100 : /** number of seconds per day */ 101 1 : #define SEC_PER_DAY 86400U 102 : 103 : /** number of minutes per hour */ 104 1 : #define MIN_PER_HOUR 60U 105 : 106 : /** number of hours per day */ 107 1 : #define HOUR_PER_DAY 24U 108 : 109 : /** number of microseconds per second */ 110 1 : #define USEC_PER_SEC ((USEC_PER_MSEC) * (MSEC_PER_SEC)) 111 : 112 : /** number of nanoseconds per second */ 113 1 : #define NSEC_PER_SEC ((NSEC_PER_USEC) * (USEC_PER_MSEC) * (MSEC_PER_SEC)) 114 : 115 : /** @} */ 116 : 117 : /** @cond INTERNAL_HIDDEN */ 118 : #define Z_TIMEOUT_NO_WAIT ((k_timeout_t) {0}) 119 : #if defined(__cplusplus) && ((__cplusplus - 0) < 202002L) 120 : #define Z_TIMEOUT_TICKS(t) ((k_timeout_t) { (t) }) 121 : #else 122 : #define Z_TIMEOUT_TICKS(t) ((k_timeout_t) { .ticks = (t) }) 123 : #endif 124 : #define Z_FOREVER Z_TIMEOUT_TICKS(K_TICKS_FOREVER) 125 : 126 : #ifdef CONFIG_TIMEOUT_64BIT 127 : # define Z_TIMEOUT_MS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ms_to_ticks_ceil64(MAX(t, 0))) 128 : # define Z_TIMEOUT_US(t) Z_TIMEOUT_TICKS((k_ticks_t)k_us_to_ticks_ceil64(MAX(t, 0))) 129 : # define Z_TIMEOUT_NS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ns_to_ticks_ceil64(MAX(t, 0))) 130 : # define Z_TIMEOUT_CYC(t) Z_TIMEOUT_TICKS((k_ticks_t)k_cyc_to_ticks_ceil64(MAX(t, 0))) 131 : # define Z_TIMEOUT_MS_TICKS(t) ((k_ticks_t)k_ms_to_ticks_ceil64(MAX(t, 0))) 132 : #else 133 : # define Z_TIMEOUT_MS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ms_to_ticks_ceil32(MAX(t, 0))) 134 : # define Z_TIMEOUT_US(t) Z_TIMEOUT_TICKS((k_ticks_t)k_us_to_ticks_ceil32(MAX(t, 0))) 135 : # define Z_TIMEOUT_NS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ns_to_ticks_ceil32(MAX(t, 0))) 136 : # define Z_TIMEOUT_CYC(t) Z_TIMEOUT_TICKS((k_ticks_t)k_cyc_to_ticks_ceil32(MAX(t, 0))) 137 : # define Z_TIMEOUT_MS_TICKS(t) ((k_ticks_t)k_ms_to_ticks_ceil32(MAX(t, 0))) 138 : #endif 139 : 140 : /* Converts between absolute timeout expiration values (packed into 141 : * the negative space below K_TICKS_FOREVER) and (non-negative) delta 142 : * timeout values. If the result of Z_TICK_ABS(t) is >= 0, then the 143 : * value was an absolute timeout with the returned expiration time. 144 : * Note that this macro is bidirectional: Z_TICK_ABS(Z_TICK_ABS(t)) == 145 : * t for all inputs, and that the representation of K_TICKS_FOREVER is 146 : * the same value in both spaces! Clever, huh? 147 : */ 148 : #define Z_TICK_ABS(t) (K_TICKS_FOREVER - 1 - (t)) 149 : 150 : /* added tick needed to account for tick in progress */ 151 : #define _TICK_ALIGN 1 152 : 153 : /** @endcond */ 154 : 155 : #if defined(CONFIG_SYS_CLOCK_EXISTS) && \ 156 : (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 0) 157 : #error "SYS_CLOCK_HW_CYCLES_PER_SEC must be non-zero!" 158 : #endif 159 : 160 : 161 : /* kernel clocks */ 162 : 163 : /* 164 : * We default to using 64-bit intermediates in timescale conversions, 165 : * but if the HW timer cycles/sec, ticks/sec and ms/sec are all known 166 : * to be nicely related, then we can cheat with 32 bits instead. 167 : */ 168 : /** 169 : * @addtogroup clock_apis 170 : * @{ 171 : */ 172 : 173 : #ifdef CONFIG_SYS_CLOCK_EXISTS 174 : 175 : #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) || \ 176 : (MSEC_PER_SEC % CONFIG_SYS_CLOCK_TICKS_PER_SEC) || \ 177 : (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC % CONFIG_SYS_CLOCK_TICKS_PER_SEC) 178 : #define _NEED_PRECISE_TICK_MS_CONVERSION 179 : #endif 180 : 181 : #endif 182 : 183 : /** 184 : * SYS_CLOCK_HW_CYCLES_TO_NS_AVG converts CPU clock cycles to nanoseconds 185 : * and calculates the average cycle time 186 : */ 187 1 : #define SYS_CLOCK_HW_CYCLES_TO_NS_AVG(X, NCYCLES) \ 188 : (uint32_t)(k_cyc_to_ns_floor64(X) / NCYCLES) 189 : 190 : /** 191 : * 192 : * @brief Return the lower part of the current system tick count 193 : * 194 : * @return the current system tick count 195 : * 196 : */ 197 1 : uint32_t sys_clock_tick_get_32(void); 198 : 199 : /** 200 : * 201 : * @brief Return the current system tick count 202 : * 203 : * @return the current system tick count 204 : * 205 : */ 206 1 : int64_t sys_clock_tick_get(void); 207 : 208 : #ifndef CONFIG_SYS_CLOCK_EXISTS 209 : #define sys_clock_tick_get() (0) 210 : #define sys_clock_tick_get_32() (0) 211 : #endif 212 : 213 : #ifdef CONFIG_SYS_CLOCK_EXISTS 214 : 215 : /** 216 : * @brief Kernel timepoint type 217 : * 218 : * Absolute timepoints are stored in this opaque type. 219 : * It is best not to inspect its content directly. 220 : * 221 : * @see sys_timepoint_calc() 222 : * @see sys_timepoint_timeout() 223 : * @see sys_timepoint_expired() 224 : */ 225 0 : typedef struct { uint64_t tick; } k_timepoint_t; 226 : 227 : /** 228 : * @brief Calculate a timepoint value 229 : * 230 : * Returns a timepoint corresponding to the expiration (relative to an 231 : * unlocked "now"!) of a timeout object. When used correctly, this should 232 : * be called once, synchronously with the user passing a new timeout value. 233 : * It should not be used iteratively to adjust a timeout (see 234 : * `sys_timepoint_timeout()` for that purpose). 235 : * 236 : * @param timeout Timeout value relative to current time (may also be 237 : * `K_FOREVER` or `K_NO_WAIT`). 238 : * @retval Timepoint value corresponding to given timeout 239 : * 240 : * @see sys_timepoint_timeout() 241 : * @see sys_timepoint_expired() 242 : */ 243 1 : k_timepoint_t sys_timepoint_calc(k_timeout_t timeout); 244 : 245 : /** 246 : * @brief Remaining time to given timepoint 247 : * 248 : * Returns the timeout interval between current time and provided timepoint. 249 : * If the timepoint is now in the past or if it was created with `K_NO_WAIT` 250 : * then `K_NO_WAIT` is returned. If it was created with `K_FOREVER` then 251 : * `K_FOREVER` is returned. 252 : * 253 : * @param timepoint Timepoint for which a timeout value is wanted. 254 : * @retval Corresponding timeout value. 255 : * 256 : * @see sys_timepoint_calc() 257 : */ 258 1 : k_timeout_t sys_timepoint_timeout(k_timepoint_t timepoint); 259 : 260 : /** 261 : * @brief Compare two timepoint values. 262 : * 263 : * This function is used to compare two timepoint values. 264 : * 265 : * @param a Timepoint to compare 266 : * @param b Timepoint to compare against. 267 : * @return zero if both timepoints are the same. Negative value if timepoint @a a is before 268 : * timepoint @a b, positive otherwise. 269 : */ 270 1 : static inline int sys_timepoint_cmp(k_timepoint_t a, k_timepoint_t b) 271 : { 272 : if (a.tick == b.tick) { 273 : return 0; 274 : } 275 : return a.tick < b.tick ? -1 : 1; 276 : } 277 : 278 : #else 279 : 280 : /* 281 : * When timers are configured out, timepoints can't relate to anything. 282 : * The best we can do is to preserve whether or not they are derived from 283 : * K_NO_WAIT. Anything else will translate back to K_FOREVER. 284 : */ 285 : typedef struct { bool wait; } k_timepoint_t; 286 : 287 : static inline k_timepoint_t sys_timepoint_calc(k_timeout_t timeout) 288 : { 289 : k_timepoint_t timepoint; 290 : 291 : timepoint.wait = !K_TIMEOUT_EQ(timeout, Z_TIMEOUT_NO_WAIT); 292 : return timepoint; 293 : } 294 : 295 : static inline k_timeout_t sys_timepoint_timeout(k_timepoint_t timepoint) 296 : { 297 : return timepoint.wait ? Z_FOREVER : Z_TIMEOUT_NO_WAIT; 298 : } 299 : 300 : static inline int sys_timepoint_cmp(k_timepoint_t a, k_timepoint_t b) 301 : { 302 : if (a.wait == b.wait) { 303 : return 0; 304 : } 305 : return b.wait ? -1 : 1; 306 : } 307 : 308 : #endif 309 : 310 : /** 311 : * @brief Indicates if timepoint is expired 312 : * 313 : * @param timepoint Timepoint to evaluate 314 : * @retval true if the timepoint is in the past, false otherwise 315 : * 316 : * @see sys_timepoint_calc() 317 : */ 318 1 : static inline bool sys_timepoint_expired(k_timepoint_t timepoint) 319 : { 320 : return K_TIMEOUT_EQ(sys_timepoint_timeout(timepoint), Z_TIMEOUT_NO_WAIT); 321 : } 322 : 323 : /** @} */ 324 : 325 : #ifdef __cplusplus 326 : } 327 : #endif 328 : 329 : #endif /* ZEPHYR_INCLUDE_SYS_CLOCK_H_ */