xref: /nrf52832-nimble/packages/NimBLE-latest/porting/nimble/include/os/os_cputime.h (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20  /**
21   * @addtogroup OSKernel
22   * @{
23   *   @defgroup OSCPUTime High Resolution Timers
24   *   @{
25   */
26 
27 #ifndef H_OS_CPUTIME_
28 #define H_OS_CPUTIME_
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 #include "syscfg/syscfg.h"
35 #include "hal/hal_timer.h"
36 #include "os/os.h"
37 
38 /*
39  * NOTE: these definitions allow one to override the cputime frequency used.
40  * The reason these definitions exist is to make the code more
41  * efficient/smaller when CPUTIME counts at 1 MHz.
42  *
43  * For those who want a different cputime frequency, you can set the config
44  * definition for OS_CPUTIME_FREQ to the desired frequency in your project,
45  * target or bsp.
46  */
47 #if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 1000000)
48 
49 #define OS_CPUTIME_FREQ_1MHZ
50 
51 #elif MYNEWT_VAL(OS_CPUTIME_FREQ) == 256        ||  \
52       MYNEWT_VAL(OS_CPUTIME_FREQ) == 512        ||  \
53       MYNEWT_VAL(OS_CPUTIME_FREQ) == 1024       ||  \
54       MYNEWT_VAL(OS_CPUTIME_FREQ) == 2048       ||  \
55       MYNEWT_VAL(OS_CPUTIME_FREQ) == 4096       ||  \
56       MYNEWT_VAL(OS_CPUTIME_FREQ) == 8192       ||  \
57       MYNEWT_VAL(OS_CPUTIME_FREQ) == 16384      ||  \
58       MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768      ||  \
59       MYNEWT_VAL(OS_CPUTIME_FREQ) == 65536      ||  \
60       MYNEWT_VAL(OS_CPUTIME_FREQ) == 131072     ||  \
61       MYNEWT_VAL(OS_CPUTIME_FREQ) == 262144     ||  \
62       MYNEWT_VAL(OS_CPUTIME_FREQ) == 524288
63 
64 #define OS_CPUTIME_FREQ_PWR2
65 
66 #elif MYNEWT_VAL(OS_CPUTIME_FREQ) > 1000000
67 
68 #define OS_CPUTIME_FREQ_HIGH
69 
70 #else
71 
72 #error "Invalid OS_CPUTIME_FREQ value.  Value must be one of a) a power of 2" \
73        ">= 256Hz, or b) any value >= 1MHz"
74 
75 #endif
76 
77 #if defined(OS_CPUTIME_FREQ_HIGH)
78 /* CPUTIME data. */
79 struct os_cputime_data
80 {
81     uint32_t ticks_per_usec;    /* number of ticks per usec */
82 };
83 extern struct os_cputime_data g_os_cputime;
84 #endif
85 
86 /* Helpful macros to compare cputimes */
87 /** evaluates to true if t1 is before t2 in time */
88 #define CPUTIME_LT(__t1, __t2) ((int32_t)   ((__t1) - (__t2)) < 0)
89 /** evaluates to true if t1 is after t2 in time */
90 #define CPUTIME_GT(__t1, __t2) ((int32_t)   ((__t1) - (__t2)) > 0)
91 /** evaluates to true if t1 is after t2 in time */
92 #define CPUTIME_GEQ(__t1, __t2) ((int32_t)  ((__t1) - (__t2)) >= 0)
93 /** evaluates to true if t1 is on or after t2 in time */
94 #define CPUTIME_LEQ(__t1, __t2) ((int32_t)  ((__t1) - (__t2)) <= 0)
95 
96 /**
97  * Initialize the cputime module. This must be called after os_init is called
98  * and before any other timer API are used. This should be called only once
99  * and should be called before the hardware timer is used.
100  *
101  * @param clock_freq The desired cputime frequency, in hertz (Hz).
102  *
103  * @return int 0 on success; -1 on error.
104  */
105 int os_cputime_init(uint32_t clock_freq);
106 
107 /**
108  * Returns the low 32 bits of cputime.
109  *
110  * @return uint32_t The lower 32 bits of cputime
111  */
112 uint32_t os_cputime_get32(void);
113 
114 #if !defined(OS_CPUTIME_FREQ_PWR2)
115 /**
116  * Converts the given number of nanoseconds into cputime ticks.
117  * Not defined if OS_CPUTIME_FREQ_PWR2 is defined.
118  *
119  * @param usecs The number of nanoseconds to convert to ticks
120  *
121  * @return uint32_t The number of ticks corresponding to 'nsecs'
122  */
123 uint32_t os_cputime_nsecs_to_ticks(uint32_t nsecs);
124 
125 /**
126  * Convert the given number of ticks into nanoseconds.
127  * Not defined if OS_CPUTIME_FREQ_PWR2 is defined.
128  *
129  * @param ticks The number of ticks to convert to nanoseconds.
130  *
131  * @return uint32_t The number of nanoseconds corresponding to 'ticks'
132  */
133 uint32_t os_cputime_ticks_to_nsecs(uint32_t ticks);
134 
135 /**
136  * Wait until 'nsecs' nanoseconds has elapsed. This is a blocking delay.
137  * Not defined if OS_CPUTIME_FREQ_PWR2 is defined.
138  *
139  *
140  * @param nsecs The number of nanoseconds to wait.
141  */
142 void os_cputime_delay_nsecs(uint32_t nsecs);
143 #endif
144 
145 #if defined(OS_CPUTIME_FREQ_1MHZ)
146 #define os_cputime_usecs_to_ticks(x)    (x)
147 #define os_cputime_ticks_to_usecs(x)    (x)
148 #else
149 
150 /**
151  * Converts the given number of microseconds into cputime ticks.
152  *
153  * @param usecs The number of microseconds to convert to ticks
154  *
155  * @return uint32_t The number of ticks corresponding to 'usecs'
156  */
157 uint32_t os_cputime_usecs_to_ticks(uint32_t usecs);
158 
159 /**
160  * Convert the given number of ticks into microseconds.
161  *
162  * @param ticks The number of ticks to convert to microseconds.
163  *
164  * @return uint32_t The number of microseconds corresponding to 'ticks'
165  */
166 uint32_t os_cputime_ticks_to_usecs(uint32_t ticks);
167 #endif
168 
169 /**
170  * Wait until the number of ticks has elapsed. This is a blocking delay.
171  *
172  * @param ticks The number of ticks to wait.
173  */
174 void os_cputime_delay_ticks(uint32_t ticks);
175 
176 /**
177  * Wait until 'usecs' microseconds has elapsed. This is a blocking delay.
178  *
179  * @param usecs The number of usecs to wait.
180  */
181 void os_cputime_delay_usecs(uint32_t usecs);
182 
183 /**
184  * Initialize a CPU timer, using the given HAL timer.
185  *
186  * @param timer The timer to initialize. Cannot be NULL.
187  * @param fp    The timer callback function. Cannot be NULL.
188  * @param arg   Pointer to data object to pass to timer.
189  */
190 void os_cputime_timer_init(struct hal_timer *timer, hal_timer_cb fp,
191         void *arg);
192 
193 /**
194  * Start a cputimer that will expire at 'cputime'. If cputime has already
195  * passed, the timer callback will still be called (at interrupt context).
196  *
197  * NOTE: This must be called when the timer is stopped.
198  *
199  * @param timer     Pointer to timer to start. Cannot be NULL.
200  * @param cputime   The cputime at which the timer should expire.
201  *
202  * @return int 0 on success; EINVAL if timer already started or timer struct
203  *         invalid
204  *
205  */
206 int os_cputime_timer_start(struct hal_timer *timer, uint32_t cputime);
207 
208 /**
209  * Sets a cpu timer that will expire 'usecs' microseconds from the current
210  * cputime.
211  *
212  * NOTE: This must be called when the timer is stopped.
213  *
214  * @param timer Pointer to timer. Cannot be NULL.
215  * @param usecs The number of usecs from now at which the timer will expire.
216  *
217  * @return int 0 on success; EINVAL if timer already started or timer struct
218  *         invalid
219  */
220 int os_cputime_timer_relative(struct hal_timer *timer, uint32_t usecs);
221 
222 /**
223  * Stops a cputimer from running. The timer is removed from the timer queue
224  * and interrupts are disabled if no timers are left on the queue. Can be
225  * called even if timer is not running.
226  *
227  * @param timer Pointer to cputimer to stop. Cannot be NULL.
228  */
229 void os_cputime_timer_stop(struct hal_timer *timer);
230 
231 #ifdef __cplusplus
232 }
233 #endif
234 
235 #endif /* H_OS_CPUTIME_ */
236 
237 /**
238  *   @} OSCPUTime
239  * @} OSKernel
240  */
241