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