Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2005, 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 #include "contiki.h" 00033 #include "sys/energest.h" 00034 #include "sys/clock.h" 00035 #include "sys/etimer.h" 00036 #include "rtimer-arch.h" 00037 #include "dev/watchdog.h" 00038 #include "isr_compat.h" 00039 00040 #define INTERVAL (RTIMER_ARCH_SECOND / CLOCK_SECOND) 00041 00042 #define MAX_TICKS (~((clock_time_t)0) / 2) 00043 00044 static volatile unsigned long seconds; 00045 00046 static volatile clock_time_t count = 0; 00047 /* last_tar is used for calculating clock_fine */ 00048 static volatile uint16_t last_tar = 0; 00049 /*---------------------------------------------------------------------------*/ 00050 ISR(TIMERA1, timera1) 00051 { 00052 ENERGEST_ON(ENERGEST_TYPE_IRQ); 00053 00054 watchdog_start(); 00055 00056 if(TAIV == 2) { 00057 00058 /* HW timer bug fix: Interrupt handler called before TR==CCR. 00059 * Occurs when timer state is toggled between STOP and CONT. */ 00060 while(TACTL & MC1 && TACCR1 - TAR == 1); 00061 00062 /* Make sure interrupt time is future */ 00063 do { 00064 TACCR1 += INTERVAL; 00065 ++count; 00066 00067 /* Make sure the CLOCK_CONF_SECOND is a power of two, to ensure 00068 that the modulo operation below becomes a logical and and not 00069 an expensive divide. Algorithm from Wikipedia: 00070 http://en.wikipedia.org/wiki/Power_of_two */ 00071 #if (CLOCK_CONF_SECOND & (CLOCK_CONF_SECOND - 1)) != 0 00072 #error CLOCK_CONF_SECOND must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...). 00073 #error Change CLOCK_CONF_SECOND in contiki-conf.h. 00074 #endif 00075 if(count % CLOCK_CONF_SECOND == 0) { 00076 ++seconds; 00077 energest_flush(); 00078 } 00079 } while((TACCR1 - TAR) > INTERVAL); 00080 00081 last_tar = TAR; 00082 00083 if(etimer_pending() && 00084 (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { 00085 etimer_request_poll(); 00086 LPM4_EXIT; 00087 } 00088 00089 } 00090 /* if(process_nevents() >= 0) { 00091 LPM4_EXIT; 00092 }*/ 00093 00094 watchdog_stop(); 00095 00096 ENERGEST_OFF(ENERGEST_TYPE_IRQ); 00097 } 00098 /*---------------------------------------------------------------------------*/ 00099 clock_time_t 00100 clock_time(void) 00101 { 00102 clock_time_t t1, t2; 00103 do { 00104 t1 = count; 00105 t2 = count; 00106 } while(t1 != t2); 00107 return t1; 00108 } 00109 /*---------------------------------------------------------------------------*/ 00110 void 00111 clock_set(clock_time_t clock, clock_time_t fclock) 00112 { 00113 TAR = fclock; 00114 TACCR1 = fclock + INTERVAL; 00115 count = clock; 00116 } 00117 /*---------------------------------------------------------------------------*/ 00118 int 00119 clock_fine_max(void) 00120 { 00121 return INTERVAL; 00122 } 00123 /*---------------------------------------------------------------------------*/ 00124 unsigned short 00125 clock_fine(void) 00126 { 00127 unsigned short t; 00128 /* Assign last_tar to local varible that can not be changed by interrupt */ 00129 t = last_tar; 00130 /* perform calc based on t, TAR will not be changed during interrupt */ 00131 return (unsigned short) (TAR - t); 00132 } 00133 /*---------------------------------------------------------------------------*/ 00134 void 00135 clock_init(void) 00136 { 00137 dint(); 00138 00139 /* Select SMCLK (2.4576MHz), clear TAR */ 00140 /* TACTL = TASSEL1 | TACLR | ID_3; */ 00141 00142 /* Select ACLK 32768Hz clock, divide by 2 */ 00143 /* TACTL = TASSEL0 | TACLR | ID_1;*/ 00144 00145 /* Select ACLK 32768Hz clock */ 00146 /* TACTL = TASSEL0 | TACLR; */ 00147 00148 #if INTERVAL==32768/CLOCK_SECOND 00149 TACTL = TASSEL0 | TACLR; 00150 #elif INTERVAL==16384/CLOCK_SECOND 00151 TACTL = TASSEL0 | TACLR | ID_1; 00152 #else 00153 #error NEED TO UPDATE clock.c to match interval! 00154 #endif 00155 00156 /* Initialize ccr1 to create the X ms interval. */ 00157 /* CCR1 interrupt enabled, interrupt occurs when timer equals CCR. */ 00158 TACCTL1 = CCIE; 00159 00160 /* Interrupt after X ms. */ 00161 TACCR1 = INTERVAL; 00162 00163 /* Start Timer_A in continuous mode. */ 00164 TACTL |= MC1; 00165 00166 count = 0; 00167 00168 /* Enable interrupts. */ 00169 eint(); 00170 00171 } 00172 /*---------------------------------------------------------------------------*/ 00173 /** 00174 * Delay the CPU for a multiple of 2.83 us. 00175 */ 00176 void 00177 clock_delay(unsigned int i) 00178 { 00179 while(i--) { 00180 _NOP(); 00181 } 00182 } 00183 /*---------------------------------------------------------------------------*/ 00184 /** 00185 * Wait for a multiple of 10 ms. 00186 * 00187 */ 00188 void 00189 clock_wait(clock_time_t i) 00190 { 00191 clock_time_t start; 00192 00193 start = clock_time(); 00194 while(clock_time() - start < (clock_time_t)i); 00195 } 00196 /*---------------------------------------------------------------------------*/ 00197 void 00198 clock_set_seconds(unsigned long sec) 00199 { 00200 int s; 00201 s = splhigh(); 00202 seconds = sec; 00203 splx(s); 00204 } 00205 /*---------------------------------------------------------------------------*/ 00206 unsigned long 00207 clock_seconds(void) 00208 { 00209 unsigned long t1, t2; 00210 do { 00211 t1 = seconds; 00212 t2 = seconds; 00213 } while(t1 != t2); 00214 return t1; 00215 } 00216 /*---------------------------------------------------------------------------*/ 00217 rtimer_clock_t 00218 clock_counter(void) 00219 { 00220 rtimer_clock_t t1, t2; 00221 do { 00222 t1 = TAR; 00223 t2 = TAR; 00224 } while(t1 != t2); 00225 return t1; 00226 } 00227 /*---------------------------------------------------------------------------*/