📄 measureclockc.nc
字号:
/* * Copyright (c) 2006 Intel Corporation * All rights reserved. * * This file is distributed under the terms in the attached INTEL-LICENSE * file. If you do not find these files, copies can be found by writing to * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, * 94704. Attention: Intel License Inquiry. *//* * Copyright (c) 2007, Vanderbilt University * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. * * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * */#include <MicaTimer.h>#include <scale.h>/** * Measure cpu clock frequency at boot time. Provides an Atm128Calibrate * interface so that other components can adjust their calibration as * needed. * * @author David Gay * @author Janos Sallai */module MeasureClockC { provides { /** * This code MUST be called from PlatformP only, hence the exactlyonce. */ interface Init @exactlyonce(); interface Atm128Calibrate; }}implementation { enum { /* This is expected number of cycles per jiffy at the platform's specified MHz. Assumes PLATFORM_MHZ == 1, 2, 4, 8 or 16. */ MAGIC = 488 / (16 / PLATFORM_MHZ) }; uint16_t cycles; command error_t Init.init() { /* Measure clock cycles per Jiffy (1/32768s) */ /* This code doesn't use the HPL to avoid timing issues when compiling with debugging on */ atomic { uint8_t now, wraps; uint16_t start; /* Setup timer2 to count 32 jiffies, and timer1 cpu cycles */ TCCR1B = 1 << CS10; ASSR = 1 << AS2; TCCR2B = 1 << CS21 | 1 << CS20; /* Wait for 1s for counter to stablilize after power-up (yes, it really does take that long). That's 122 wrap arounds of timer 1 at 8MHz. */ start = TCNT1; for (wraps = MAGIC / 2; wraps; ) { uint16_t next = TCNT1; if (next < start) wraps--; start = next; } /* Wait for a TCNT0 change */ now = TCNT2; while (TCNT2 == now) ; /* Read cpu cycles and wait for next TCNT2 change */ start = TCNT1; now = TCNT2; while (TCNT2 == now) ; cycles = TCNT1; cycles = (cycles - start + 16) >> 5; /* Reset to boot state */ ASSR = TCCR1B = TCCR2B = 0; TCNT2 = 0; TCNT1 = 0; TIFR1 = TIFR2 = 0xff; while (ASSR & (1 << TCN2UB | 1 << OCR2BUB | 1 << TCR2BUB)) ; } return SUCCESS; } async command uint16_t Atm128Calibrate.cyclesPerJiffy() { return cycles; } async command uint32_t Atm128Calibrate.calibrateMicro(uint32_t n) { return scale32(n + MAGIC / 2, cycles, MAGIC); } async command uint32_t Atm128Calibrate.actualMicro(uint32_t n) { return scale32(n + (cycles >> 1), MAGIC, cycles); } async command uint8_t Atm128Calibrate.adcPrescaler() { /* This is also log2(cycles/3.05). But that's a pain to compute */ if (cycles >= 390) return ATM128_ADC_PRESCALE_128; if (cycles >= 195) return ATM128_ADC_PRESCALE_64; if (cycles >= 97) return ATM128_ADC_PRESCALE_32; if (cycles >= 48) return ATM128_ADC_PRESCALE_16; if (cycles >= 24) return ATM128_ADC_PRESCALE_8; if (cycles >= 12) return ATM128_ADC_PRESCALE_4; return ATM128_ADC_PRESCALE_2; } async command uint16_t Atm128Calibrate.baudrateRegister(uint32_t baudrate) { // value is (cycles*32768) / (8*baudrate) - 1 return ((uint32_t)cycles << 12) / baudrate - 1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -