Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2009, Swedish Institute of Computer Science. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 */ 00031 00032 /** 00033 * \file 00034 * Implementation of the clock functions for the cc243x 00035 * \author 00036 * Zach Shelby (zach@sensinode.com) - original 00037 * George Oikonomou - <oikonomou@users.sourceforge.net> 00038 */ 00039 #include "sys/clock.h" 00040 #include "sys/etimer.h" 00041 #include "cc2430_sfr.h" 00042 #include "sys/energest.h" 00043 00044 /* Sleep timer runs on the 32k RC osc. */ 00045 /* One clock tick is 7.8 ms */ 00046 #define TICK_VAL (32768/128) /* 256 */ 00047 /*---------------------------------------------------------------------------*/ 00048 #if CLOCK_CONF_STACK_FRIENDLY 00049 volatile __bit sleep_flag; 00050 #else 00051 #endif 00052 /*---------------------------------------------------------------------------*/ 00053 /* Used in sleep timer interrupt for calculating the next interrupt time */ 00054 static unsigned long timer_value; 00055 static volatile __data clock_time_t count = 0; /* Uptime in ticks */ 00056 static volatile __data clock_time_t seconds = 0; /* Uptime in secs */ 00057 /*---------------------------------------------------------------------------*/ 00058 /** 00059 * Each iteration is ~1.0xy usec, so this function delays for roughly len usec 00060 */ 00061 void 00062 clock_delay_usec(uint16_t len) 00063 { 00064 DISABLE_INTERRUPTS(); 00065 while(len--) { 00066 ASM(nop); ASM(nop); 00067 ASM(nop); ASM(nop); 00068 } 00069 ENABLE_INTERRUPTS(); 00070 } 00071 /*---------------------------------------------------------------------------*/ 00072 /** 00073 * Wait for a multiple of ~8 ms (a tick) 00074 */ 00075 void 00076 clock_wait(clock_time_t i) 00077 { 00078 clock_time_t start; 00079 00080 start = clock_time(); 00081 while(clock_time() - start < (clock_time_t)i); 00082 } 00083 /*---------------------------------------------------------------------------*/ 00084 CCIF clock_time_t 00085 clock_time(void) 00086 { 00087 return count; 00088 } 00089 /*---------------------------------------------------------------------------*/ 00090 CCIF unsigned long 00091 clock_seconds(void) 00092 { 00093 return seconds; 00094 } 00095 /*---------------------------------------------------------------------------*/ 00096 void 00097 clock_init(void) 00098 { 00099 CLKCON = OSC32K | TICKSPD2 | TICKSPD1; /* tickspeed 500 kHz for timers[1-4] */ 00100 00101 /* Initialize tick value */ 00102 timer_value = ST0; /* ST low bits [7:0] */ 00103 timer_value += ((unsigned long int) ST1) << 8; /* middle bits [15:8] */ 00104 timer_value += ((unsigned long int) ST2) << 16; /* high bits [23:16] */ 00105 timer_value += TICK_VAL; /* Init value 256 */ 00106 ST2 = (unsigned char) (timer_value >> 16); 00107 ST1 = (unsigned char) (timer_value >> 8); 00108 ST0 = (unsigned char) timer_value; 00109 00110 IEN0_STIE = 1; /* IEN0.STIE acknowledge Sleep Timer Interrupt */ 00111 } 00112 /*---------------------------------------------------------------------------*/ 00113 void 00114 clock_ISR(void) __interrupt(ST_VECTOR) 00115 { 00116 DISABLE_INTERRUPTS(); 00117 ENERGEST_ON(ENERGEST_TYPE_IRQ); 00118 00119 /* 00120 * If the Sleep timer throws an interrupt while we are powering down to 00121 * PM1, we need to abort the power down. Clear SLEEP.MODE, this will signal 00122 * main() to abort the PM1 transition 00123 */ 00124 SLEEP &= 0xFC; 00125 00126 /* 00127 * Read value of the ST0:ST1:ST2, add TICK_VAL and write it back. 00128 * Next interrupt occurs after the current time + TICK_VAL 00129 */ 00130 timer_value = ST0; 00131 timer_value += ((unsigned long int) ST1) << 8; 00132 timer_value += ((unsigned long int) ST2) << 16; 00133 timer_value += TICK_VAL; 00134 ST2 = (unsigned char) (timer_value >> 16); 00135 ST1 = (unsigned char) (timer_value >> 8); 00136 ST0 = (unsigned char) timer_value; 00137 00138 ++count; 00139 00140 /* Make sure the CLOCK_CONF_SECOND is a power of two, to ensure 00141 that the modulo operation below becomes a logical and and not 00142 an expensive divide. Algorithm from Wikipedia: 00143 http://en.wikipedia.org/wiki/Power_of_two */ 00144 #if (CLOCK_CONF_SECOND & (CLOCK_CONF_SECOND - 1)) != 0 00145 #error CLOCK_CONF_SECOND must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...). 00146 #error Change CLOCK_CONF_SECOND in contiki-conf.h. 00147 #endif 00148 if(count % CLOCK_CONF_SECOND == 0) { 00149 ++seconds; 00150 } 00151 00152 #if CLOCK_CONF_STACK_FRIENDLY 00153 sleep_flag = 1; 00154 #else 00155 if(etimer_pending() 00156 && (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { 00157 etimer_request_poll(); 00158 } 00159 #endif 00160 00161 IRCON_STIF = 0; 00162 ENERGEST_OFF(ENERGEST_TYPE_IRQ); 00163 ENABLE_INTERRUPTS(); 00164 } 00165 /*---------------------------------------------------------------------------*/