1616#ifndef ZEPHYR_INCLUDE_SYS_CLOCK_H_
1717#define ZEPHYR_INCLUDE_SYS_CLOCK_H_
1818
19+ #include <misc/util.h>
20+ #include <misc/dlist.h>
21+
1922#ifdef __cplusplus
2023extern "C" {
2124#endif
2225
2326#include <toolchain.h>
2427#include <zephyr/types.h>
2528
26- #if defined(CONFIG_SYS_CLOCK_EXISTS ) && \
27- (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 0 )
28- #error "SYS_CLOCK_HW_CYCLES_PER_SEC must be non-zero!"
29- #endif
30-
3129#ifdef CONFIG_TICKLESS_KERNEL
3230#define sys_clock_ticks_per_sec \
3331 (1000000 / (CONFIG_TICKLESS_KERNEL_TIME_UNIT_IN_MICRO_SECS))
@@ -43,21 +41,10 @@ extern int sys_clock_hw_cycles_per_sec;
4341#define sys_clock_hw_cycles_per_sec CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC
4442#endif
4543
46- /*
47- * sys_clock_us_per_tick global variable represents a number
48- * of microseconds in one OS timer tick
49- *
50- * Note: This variable is deprecated and will be removed soon!
51- */
52- __deprecated extern int sys_clock_us_per_tick ;
53-
54- /*
55- * sys_clock_hw_cycles_per_tick global variable represents a number
56- * of platform clock ticks in one OS timer tick.
57- * sys_clock_hw_cycles_per_tick often represents a value of divider
58- * of the board clock frequency
59- */
60- extern int sys_clock_hw_cycles_per_tick ;
44+ #if defined(CONFIG_SYS_CLOCK_EXISTS ) && \
45+ (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 0 )
46+ #error "SYS_CLOCK_HW_CYCLES_PER_SEC must be non-zero!"
47+ #endif
6148
6249/* number of nsec per usec */
6350#define NSEC_PER_USEC 1000
@@ -75,6 +62,97 @@ extern int sys_clock_hw_cycles_per_tick;
7562#define NSEC_PER_SEC ((NSEC_PER_USEC) * (USEC_PER_MSEC) * (MSEC_PER_SEC))
7663
7764
65+ /* kernel clocks */
66+
67+ #ifdef CONFIG_SYS_CLOCK_EXISTS
68+
69+ /*
70+ * If timer frequency is known at compile time, a simple (32-bit)
71+ * tick <-> ms conversion could be used for some combinations of
72+ * hardware timer frequency and tick rate. Otherwise precise
73+ * (64-bit) calculations are used.
74+ */
75+
76+ #if !defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME )
77+ #if (sys_clock_hw_cycles_per_sec % sys_clock_ticks_per_sec ) != 0
78+ #define _NEED_PRECISE_TICK_MS_CONVERSION
79+ #elif (MSEC_PER_SEC % sys_clock_ticks_per_sec ) != 0
80+ #define _NON_OPTIMIZED_TICKS_PER_SEC
81+ #endif
82+ #endif
83+
84+ #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME ) || \
85+ defined(_NON_OPTIMIZED_TICKS_PER_SEC )
86+ #define _NEED_PRECISE_TICK_MS_CONVERSION
87+ #endif
88+ #endif
89+
90+ static ALWAYS_INLINE s32_t _ms_to_ticks (s32_t ms )
91+ {
92+ #ifdef CONFIG_SYS_CLOCK_EXISTS
93+
94+ #ifdef _NEED_PRECISE_TICK_MS_CONVERSION
95+ /* use 64-bit math to keep precision */
96+ return (s32_t )ceiling_fraction (
97+ (s64_t )ms * sys_clock_hw_cycles_per_sec ,
98+ ((s64_t )MSEC_PER_SEC * sys_clock_hw_cycles_per_sec ) /
99+ sys_clock_ticks_per_sec );
100+ #else
101+ /* simple division keeps precision */
102+ s32_t ms_per_tick = MSEC_PER_SEC / sys_clock_ticks_per_sec ;
103+
104+ return (s32_t )ceiling_fraction (ms , ms_per_tick );
105+ #endif
106+
107+ #else
108+ __ASSERT (ms == 0 , "ms not zero" );
109+ return 0 ;
110+ #endif
111+ }
112+
113+ static inline s64_t __ticks_to_ms (s64_t ticks )
114+ {
115+ #ifdef CONFIG_SYS_CLOCK_EXISTS
116+
117+ #ifdef _NEED_PRECISE_TICK_MS_CONVERSION
118+ /* use 64-bit math to keep precision */
119+ return (u64_t )ticks * MSEC_PER_SEC / sys_clock_ticks_per_sec ;
120+ #else
121+ /* simple multiplication keeps precision */
122+ u32_t ms_per_tick = MSEC_PER_SEC / sys_clock_ticks_per_sec ;
123+
124+ return (u64_t )ticks * ms_per_tick ;
125+ #endif
126+
127+ #else
128+ __ASSERT (ticks == 0 , "ticks not zero" );
129+ return 0 ;
130+ #endif
131+ }
132+
133+ /* added tick needed to account for tick in progress */
134+ #ifdef CONFIG_TICKLESS_KERNEL
135+ #define _TICK_ALIGN 0
136+ #else
137+ #define _TICK_ALIGN 1
138+ #endif
139+
140+ /*
141+ * sys_clock_us_per_tick global variable represents a number
142+ * of microseconds in one OS timer tick
143+ *
144+ * Note: This variable is deprecated and will be removed soon!
145+ */
146+ __deprecated extern int sys_clock_us_per_tick ;
147+
148+ /*
149+ * sys_clock_hw_cycles_per_tick global variable represents a number
150+ * of platform clock ticks in one OS timer tick.
151+ * sys_clock_hw_cycles_per_tick often represents a value of divider
152+ * of the board clock frequency
153+ */
154+ extern int sys_clock_hw_cycles_per_tick ;
155+
78156/* SYS_CLOCK_HW_CYCLES_TO_NS64 converts CPU clock cycles to nanoseconds */
79157#define SYS_CLOCK_HW_CYCLES_TO_NS64 (X ) \
80158 (((u64_t)(X) * NSEC_PER_SEC) / sys_clock_hw_cycles_per_sec)
@@ -110,6 +188,21 @@ extern int sys_clock_hw_cycles_per_tick;
110188
111189extern volatile u64_t _sys_clock_tick_count ;
112190
191+ /* timeouts */
192+
193+ struct _timeout ;
194+ typedef void (* _timeout_func_t )(struct _timeout * t );
195+
196+ struct _timeout {
197+ sys_dnode_t node ;
198+ struct k_thread * thread ;
199+ sys_dlist_t * wait_q ;
200+ s32_t delta_ticks_from_prev ;
201+ _timeout_func_t func ;
202+ };
203+
204+ extern s32_t _timeout_remaining_get (struct _timeout * timeout );
205+
113206/*
114207 * Number of ticks for x seconds. NOTE: With MSEC() or USEC(),
115208 * since it does an integer division, x must be greater or equal to
0 commit comments