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*042d53a7SEvalZeroos_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*042d53a7SEvalZeroos_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