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