Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2011, 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, last_ccr might be better? */ 00048 static volatile uint16_t last_tar = 0; 00049 /*---------------------------------------------------------------------------*/ 00050 ISR(TIMER1_A1, timera1) 00051 { 00052 ENERGEST_ON(ENERGEST_TYPE_IRQ); 00053 00054 /* watchdog_start(); */ 00055 00056 if(TA1IV == 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(TA1CTL & MC1 && TA1CCR1 - TA1R == 1); 00061 00062 /* Make sure interrupt time is future */ 00063 do { 00064 TA1CCR1 += 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((TA1CCR1 - TA1R) > INTERVAL); 00080 00081 last_tar = TA1R; 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 TA1R = fclock; 00114 TA1CCR1 = 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) (TA1R - 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 /* TA1CTL = TASSEL0 | TACLR | ID_1; */ 00144 00145 #if INTERVAL==32768/CLOCK_SECOND 00146 TA1CTL = TASSEL0 | TACLR; 00147 #elif INTERVAL==16384/CLOCK_SECOND 00148 TA1CTL = TASSEL0 | TACLR | ID_1; 00149 #else 00150 #error NEED TO UPDATE clock.c to match interval! 00151 #endif 00152 00153 /* Initialize ccr1 to create the X ms interval. */ 00154 /* CCR1 interrupt enabled, interrupt occurs when timer equals CCR1. */ 00155 TA1CCTL1 = CCIE; 00156 00157 /* Interrupt after X ms. */ 00158 TA1CCR1 = INTERVAL; 00159 00160 /* Start Timer_A in continuous mode. */ 00161 TA1CTL |= MC1; 00162 00163 count = 0; 00164 00165 /* Enable interrupts. */ 00166 eint(); 00167 00168 } 00169 /*---------------------------------------------------------------------------*/ 00170 /** 00171 * Delay the CPU for a multiple of 2.83 us. 00172 */ 00173 void 00174 clock_delay(unsigned int i) 00175 { 00176 while(i--) { 00177 _NOP(); 00178 } 00179 } 00180 /*---------------------------------------------------------------------------*/ 00181 /** 00182 * Wait for a multiple of 10 ms. 00183 * 00184 */ 00185 void 00186 clock_wait(clock_time_t i) 00187 { 00188 clock_time_t start; 00189 00190 start = clock_time(); 00191 while(clock_time() - start < (clock_time_t)i); 00192 } 00193 /*---------------------------------------------------------------------------*/ 00194 void 00195 clock_set_seconds(unsigned long sec) 00196 { 00197 int s; 00198 s = splhigh(); 00199 seconds = sec; 00200 splx(s); 00201 } 00202 /*---------------------------------------------------------------------------*/ 00203 unsigned long 00204 clock_seconds(void) 00205 { 00206 unsigned long t1, t2; 00207 do { 00208 t1 = seconds; 00209 t2 = seconds; 00210 } while(t1 != t2); 00211 return t1; 00212 } 00213 /*---------------------------------------------------------------------------*/ 00214 rtimer_clock_t 00215 clock_counter(void) 00216 { 00217 rtimer_clock_t t1, t2; 00218 do { 00219 t1 = TA1R; 00220 t2 = TA1R; 00221 } while(t1 != t2); 00222 return t1; 00223 } 00224 /*---------------------------------------------------------------------------*/