xref: /nrf52832-nimble/packages/NimBLE-latest/porting/nimble/src/os_cputime_pwr2.c (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 #include "os/os_cputime.h"
21*042d53a7SEvalZero 
22*042d53a7SEvalZero /**
23*042d53a7SEvalZero  * This module implements cputime functionality for timers for which:
24*042d53a7SEvalZero  *     a. freq is a power of 2 Hz, and
25*042d53a7SEvalZero  *     b. 256 Hz <= freq < 1 MHz
26*042d53a7SEvalZero  */
27*042d53a7SEvalZero 
28*042d53a7SEvalZero #if defined(OS_CPUTIME_FREQ_PWR2)
29*042d53a7SEvalZero 
30*042d53a7SEvalZero /**
31*042d53a7SEvalZero  * @addtogroup OSKernel Operating System Kernel
32*042d53a7SEvalZero  * @{
33*042d53a7SEvalZero  *   @defgroup OSCPUTime High Resolution Timers
34*042d53a7SEvalZero  *   @{
35*042d53a7SEvalZero  */
36*042d53a7SEvalZero 
37*042d53a7SEvalZero /**
38*042d53a7SEvalZero  * os cputime usecs to ticks
39*042d53a7SEvalZero  *
40*042d53a7SEvalZero  * Converts the given number of microseconds into cputime ticks.
41*042d53a7SEvalZero  *
42*042d53a7SEvalZero  * @param usecs The number of microseconds to convert to ticks
43*042d53a7SEvalZero  *
44*042d53a7SEvalZero  * @return uint32_t The number of ticks corresponding to 'usecs'
45*042d53a7SEvalZero  */
46*042d53a7SEvalZero uint32_t
os_cputime_usecs_to_ticks(uint32_t usecs)47*042d53a7SEvalZero os_cputime_usecs_to_ticks(uint32_t usecs)
48*042d53a7SEvalZero {
49*042d53a7SEvalZero     uint64_t ticks;
50*042d53a7SEvalZero 
51*042d53a7SEvalZero     /*
52*042d53a7SEvalZero      * Faster calculation but could be off 1 full tick since we do not
53*042d53a7SEvalZero      * add residual back. Adding back the residual is commented out below, but
54*042d53a7SEvalZero      * shown.
55*042d53a7SEvalZero      */
56*042d53a7SEvalZero     ticks = (1ULL << 32) * MYNEWT_VAL(OS_CPUTIME_FREQ) / 1000000 * usecs;
57*042d53a7SEvalZero 
58*042d53a7SEvalZero     /* Residual for 32768 Hz. */
59*042d53a7SEvalZero     //ticks += ((uint64_t)usecs * (1526122139+1)) >> 32;
60*042d53a7SEvalZero 
61*042d53a7SEvalZero     return ticks >> 32;
62*042d53a7SEvalZero }
63*042d53a7SEvalZero 
64*042d53a7SEvalZero /**
65*042d53a7SEvalZero  * cputime ticks to usecs
66*042d53a7SEvalZero  *
67*042d53a7SEvalZero  * Convert the given number of ticks into microseconds.
68*042d53a7SEvalZero  *
69*042d53a7SEvalZero  * @param ticks The number of ticks to convert to microseconds.
70*042d53a7SEvalZero  *
71*042d53a7SEvalZero  * @return uint32_t The number of microseconds corresponding to 'ticks'
72*042d53a7SEvalZero  *
73*042d53a7SEvalZero  * NOTE: This calculation will overflow if the value for ticks is greater
74*042d53a7SEvalZero  * than 140737488. I am not going to check that here because that many ticks
75*042d53a7SEvalZero  * is about 4222 seconds, way more than what this routine should be used for.
76*042d53a7SEvalZero  */
77*042d53a7SEvalZero uint32_t
os_cputime_ticks_to_usecs(uint32_t ticks)78*042d53a7SEvalZero os_cputime_ticks_to_usecs(uint32_t ticks)
79*042d53a7SEvalZero {
80*042d53a7SEvalZero     uint32_t usecs;
81*042d53a7SEvalZero     uint32_t shift;
82*042d53a7SEvalZero     uint32_t freq;
83*042d53a7SEvalZero 
84*042d53a7SEvalZero     /* Given: `freq = 2^n`, calculate `n`. */
85*042d53a7SEvalZero     /* Note: this looks like a lot of work, but gcc can optimize it away since
86*042d53a7SEvalZero      * `freq` is known at compile time.
87*042d53a7SEvalZero      */
88*042d53a7SEvalZero     freq = MYNEWT_VAL(OS_CPUTIME_FREQ);
89*042d53a7SEvalZero     shift = 0;
90*042d53a7SEvalZero     while (freq != 0) {
91*042d53a7SEvalZero         freq >>= 1;
92*042d53a7SEvalZero         shift++;
93*042d53a7SEvalZero     }
94*042d53a7SEvalZero 
95*042d53a7SEvalZero     if (shift <= 7) {
96*042d53a7SEvalZero         return 0;
97*042d53a7SEvalZero     }
98*042d53a7SEvalZero     shift -= 7;
99*042d53a7SEvalZero 
100*042d53a7SEvalZero     usecs = ((ticks >> shift) * 15625) + (((ticks & 0x1ff) * 15625) >> shift);
101*042d53a7SEvalZero     return usecs;
102*042d53a7SEvalZero }
103*042d53a7SEvalZero 
104*042d53a7SEvalZero /**
105*042d53a7SEvalZero  *   @} OSCPUTime
106*042d53a7SEvalZero  * @} OSKernel
107*042d53a7SEvalZero  */
108*042d53a7SEvalZero 
109*042d53a7SEvalZero #endif
110