Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2007, 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 * $Id: rtimer-arch.c,v 1.10 2010/02/28 21:29:19 dak664 Exp $ 00032 */ 00033 00034 /** 00035 * \file 00036 * AVR-specific rtimer code 00037 * Defaults to Timer3 for those ATMEGAs that have it. 00038 * If Timer3 not present Timer1 will be used. 00039 * \author 00040 * Fredrik Osterlind <fros@sics.se> 00041 * Joakim Eriksson <joakime@sics.se> 00042 */ 00043 00044 /* OBS: 8 seconds maximum time! */ 00045 00046 #include <avr/io.h> 00047 #include <avr/interrupt.h> 00048 #include <stdio.h> 00049 00050 #include "sys/energest.h" 00051 #include "sys/rtimer.h" 00052 #include "rtimer-arch.h" 00053 00054 #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284P__) 00055 #define ETIMSK TIMSK3 00056 #define ETIFR TIFR3 00057 #define TICIE3 ICIE3 00058 00059 //Has no 'C', so we just set it to B. The code doesn't really use C so this 00060 //is safe to do but lets it compile. Probably should enable the warning if 00061 //it is ever used on other platforms. 00062 //#warning no OCIE3C in timer3 architecture, hopefully it won't be needed! 00063 00064 #define OCIE3C OCIE3B 00065 #define OCF3C OCF3B 00066 #endif 00067 00068 #if defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega128RFA1__) 00069 #define ETIMSK TIMSK3 00070 #define ETIFR TIFR3 00071 #define TICIE3 ICIE3 00072 #endif 00073 00074 #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega644__) 00075 #define TIMSK TIMSK1 00076 #define TICIE1 ICIE1 00077 #define TIFR TIFR1 00078 #endif 00079 00080 /* Track flow through rtimer interrupts*/ 00081 #if DEBUGFLOWSIZE&&0 00082 extern uint8_t debugflowsize,debugflow[DEBUGFLOWSIZE]; 00083 #define DEBUGFLOW(c) if (debugflowsize<(DEBUGFLOWSIZE-1)) debugflow[debugflowsize++]=c 00084 #else 00085 #define DEBUGFLOW(c) 00086 #endif 00087 00088 /*---------------------------------------------------------------------------*/ 00089 #if defined(TCNT3) && RTIMER_ARCH_PRESCALER 00090 ISR (TIMER3_COMPA_vect) { 00091 DEBUGFLOW('/'); 00092 ENERGEST_ON(ENERGEST_TYPE_IRQ); 00093 00094 /* Disable rtimer interrupts */ 00095 ETIMSK &= ~((1 << OCIE3A) | (1 << OCIE3B) | (1 << TOIE3) | 00096 (1 << TICIE3) | (1 << OCIE3C)); 00097 00098 #if RTIMER_CONF_NESTED_INTERRUPTS 00099 /* Enable nested interrupts. Allows radio interrupt during rtimer interrupt. */ 00100 /* All interrupts are enabled including recursive rtimer, so use with caution */ 00101 sei(); 00102 #endif 00103 00104 /* Call rtimer callback */ 00105 rtimer_run_next(); 00106 00107 ENERGEST_OFF(ENERGEST_TYPE_IRQ); 00108 DEBUGFLOW('\\'); 00109 } 00110 00111 #elif RTIMER_ARCH_PRESCALER 00112 #warning "No Timer3 in rtimer-arch.c - using Timer1 instead" 00113 ISR (TIMER1_COMPA_vect) { 00114 DEBUGFLOW('/'); 00115 TIMSK &= ~((1<<TICIE1)|(1<<OCIE1A)|(1<<OCIE1B)|(1<<TOIE1)); 00116 00117 rtimer_run_next(); 00118 DEBUGFLOW('\\'); 00119 } 00120 00121 #endif 00122 /*---------------------------------------------------------------------------*/ 00123 void 00124 rtimer_arch_init(void) 00125 { 00126 #if RTIMER_ARCH_PRESCALER 00127 /* Disable interrupts (store old state) */ 00128 uint8_t sreg; 00129 sreg = SREG; 00130 cli (); 00131 00132 #ifdef TCNT3 00133 /* Disable all timer functions */ 00134 ETIMSK &= ~((1 << OCIE3A) | (1 << OCIE3B) | (1 << TOIE3) | 00135 (1 << TICIE3) | (1 << OCIE3C)); 00136 /* Write 1s to clear existing timer function flags */ 00137 ETIFR |= (1 << ICF3) | (1 << OCF3A) | (1 << OCF3B) | (1 << TOV3) | 00138 (1 << OCF3C); 00139 00140 /* Default timer behaviour */ 00141 TCCR3A = 0; 00142 TCCR3B = 0; 00143 TCCR3C = 0; 00144 00145 /* Reset counter */ 00146 TCNT3 = 0; 00147 00148 #if RTIMER_ARCH_PRESCALER==1024 00149 TCCR3B |= 5; 00150 #elif RTIMER_ARCH_PRESCALER==256 00151 TCCR3B |= 4; 00152 #elif RTIMER_ARCH_PRESCALER==64 00153 TCCR3B |= 3; 00154 #elif RTIMER_ARCH_PRESCALER==8 00155 TCCR3B |= 2; 00156 #elif RTIMER_ARCH_PRESCALER==1 00157 TCCR3B |= 1; 00158 #else 00159 #error Timer3 PRESCALER factor not supported. 00160 #endif 00161 00162 #elif RTIMER_ARCH_PRESCALER 00163 /* Leave timer1 alone if PRESCALER set to zero */ 00164 /* Obviously you can not then use rtimers */ 00165 00166 TIMSK &= ~((1<<TICIE1)|(1<<OCIE1A)|(1<<OCIE1B)|(1<<TOIE1)); 00167 TIFR |= (1 << ICF1) | (1 << OCF1A) | (1 << OCF1B) | (1 << TOV1); 00168 00169 /* Default timer behaviour */ 00170 TCCR1A = 0; 00171 TCCR1B = 0; 00172 00173 /* Reset counter */ 00174 TCNT1 = 0; 00175 00176 /* Start clock */ 00177 #if RTIMER_ARCH_PRESCALER==1024 00178 TCCR1B |= 5; 00179 #elif RTIMER_ARCH_PRESCALER==256 00180 TCCR1B |= 4; 00181 #elif RTIMER_ARCH_PRESCALER==64 00182 TCCR1B |= 3; 00183 #elif RTIMER_ARCH_PRESCALER==8 00184 TCCR1B |= 2; 00185 #elif RTIMER_ARCH_PRESCALER==1 00186 TCCR1B |= 1; 00187 #else 00188 #error Timer1 PRESCALER factor not supported. 00189 #endif 00190 00191 #endif /* TCNT3 */ 00192 00193 /* Restore interrupt state */ 00194 SREG = sreg; 00195 #endif /* RTIMER_ARCH_PRESCALER */ 00196 } 00197 /*---------------------------------------------------------------------------*/ 00198 void 00199 rtimer_arch_schedule(rtimer_clock_t t) 00200 { 00201 #if RTIMER_ARCH_PRESCALER 00202 /* Disable interrupts (store old state) */ 00203 uint8_t sreg; 00204 sreg = SREG; 00205 cli (); 00206 DEBUGFLOW(':'); 00207 #ifdef TCNT3 00208 /* Set compare register */ 00209 OCR3A = t; 00210 /* Write 1s to clear all timer function flags */ 00211 ETIFR |= (1 << ICF3) | (1 << OCF3A) | (1 << OCF3B) | (1 << TOV3) | 00212 (1 << OCF3C); 00213 /* Enable interrupt on OCR3A match */ 00214 ETIMSK |= (1 << OCIE3A); 00215 00216 #elif RTIMER_ARCH_PRESCALER 00217 /* Set compare register */ 00218 OCR1A = t; 00219 TIFR |= (1 << ICF1) | (1 << OCF1A) | (1 << OCF1B) | (1 << TOV1); 00220 TIMSK |= (1 << OCIE1A); 00221 00222 #endif 00223 00224 /* Restore interrupt state */ 00225 SREG = sreg; 00226 #endif /* RTIMER_ARCH_PRESCALER */ 00227 } 00228 00229 #if RDC_CONF_MCU_SLEEP 00230 /*---------------------------------------------------------------------------*/ 00231 void 00232 rtimer_arch_sleep(rtimer_clock_t howlong) 00233 { 00234 /* Deep Sleep for howlong rtimer ticks. This will stop all timers except 00235 * for TIMER2 which can be clocked using an external crystal. 00236 * Unfortunately this is an 8 bit timer; a lower prescaler gives higher 00237 * precision but smaller maximum sleep time. 00238 * Here a maximum 128msec (contikimac 8Hz channel check sleep) is assumed. 00239 * The rtimer and system clocks are adjusted to reflect the sleep time. 00240 */ 00241 #include <avr/sleep.h> 00242 #include <dev/watchdog.h> 00243 uint32_t longhowlong; 00244 #if AVR_CONF_USE32KCRYSTAL 00245 /* Save TIMER2 configuration if clock.c is using it */ 00246 uint8_t savedTCNT2=TCNT2, savedTCCR2A=TCCR2A, savedTCCR2B = TCCR2B, savedOCR2A = OCR2A; 00247 #endif 00248 cli(); 00249 watchdog_stop(); 00250 set_sleep_mode(SLEEP_MODE_PWR_SAVE); 00251 00252 /* Set TIMER2 clock asynchronus from external source, CTC mode */ 00253 ASSR |= (1 << AS2); 00254 TCCR2A =(1<<WGM21); 00255 /* Set prescaler and TIMER2 output compare register */ 00256 #if 0 //Prescale by 1024 - 32 ticks/sec, 8 seconds max sleep 00257 TCCR2B =((1<<CS22)|(1<<CS21)|(1<<CS20)); 00258 longhowlong=howlong*32UL; 00259 #elif 0 // Prescale by 256 - 128 ticks/sec, 2 seconds max sleep 00260 TCCR2B =((1<<CS22)|(1<<CS21)|(0<<CS20)); 00261 longhowlong=howlong*128UL; 00262 #elif 0 // Prescale by 128 - 256 ticks/sec, 1 seconds max sleep 00263 TCCR2B =((1<<CS22)|(0<<CS21)|(1<<CS20)); 00264 longhowlong=howlong*256UL; 00265 #elif 0 // Prescale by 64 - 512 ticks/sec, 500 msec max sleep 00266 TCCR2B =((1<<CS22)|(0<<CS21)|(0<<CS20)); 00267 longhowlong=howlong*512UL; 00268 #elif 1 // Prescale by 32 - 1024 ticks/sec, 250 msec max sleep 00269 TCCR2B =((0<<CS22)|(1<<CS21)|(1<<CS20)); 00270 longhowlong=howlong*1024UL; 00271 #elif 0 // Prescale by 8 - 4096 ticks/sec, 62.5 msec max sleep 00272 TCCR2B =((0<<CS22)|(1<<CS21)|(0<<CS20)); 00273 longhowlong=howlong*4096UL; 00274 #else // No Prescale - 32768 ticks/sec, 7.8 msec max sleep 00275 TCCR2B =((0<<CS22)|(0<<CS21)|(1<<CS20)); 00276 longhowlong=howlong*32768UL; 00277 #endif 00278 OCR2A = longhowlong/RTIMER_ARCH_SECOND; 00279 00280 /* Reset timer count, wait for the write (which assures TCCR2x and OCR2A are finished) */ 00281 TCNT2 = 0; 00282 while(ASSR & (1 << TCN2UB)); 00283 00284 /* Enable TIMER2 output compare interrupt, sleep mode and sleep */ 00285 TIMSK2 |= (1 << OCIE2A); 00286 SMCR |= (1 << SE); 00287 sei(); 00288 ENERGEST_OFF(ENERGEST_TYPE_CPU); 00289 if (OCR2A) sleep_mode(); 00290 //...zzZZZzz...Ding!// 00291 00292 /* Disable sleep mode after wakeup, so random code cant trigger sleep */ 00293 SMCR &= ~(1 << SE); 00294 00295 /* Adjust rtimer ticks if rtimer is enabled. TIMER3 is preferred, else TIMER1 */ 00296 #if RTIMER_ARCH_PRESCALER 00297 #ifdef TCNT3 00298 TCNT3 += howlong; 00299 #else 00300 TCNT1 += howlong; 00301 #endif 00302 #endif 00303 ENERGEST_ON(ENERGEST_TYPE_CPU); 00304 00305 #if AVR_CONF_USE32KCRYSTAL 00306 /* Restore clock.c configuration */ 00307 cli(); 00308 TCCR2A = savedTCCR2A; 00309 TCCR2B = savedTCCR2B; 00310 OCR2A = savedOCR2A; 00311 TCNT2 = savedTCNT2; 00312 sei(); 00313 #else 00314 /* Disable TIMER2 interrupt */ 00315 TIMSK2 &= ~(1 << OCIE2A); 00316 #endif 00317 watchdog_start(); 00318 00319 /* Adjust clock.c for the time spent sleeping */ 00320 longhowlong=CLOCK_CONF_SECOND; 00321 longhowlong*=howlong; 00322 clock_adjust_ticks(longhowlong/RTIMER_ARCH_SECOND); 00323 00324 } 00325 #if !AVR_CONF_USE32KCRYSTAL 00326 /*---------------------------------------------------------------------------*/ 00327 /* TIMER2 Interrupt service */ 00328 00329 ISR(TIMER2_COMPA_vect) 00330 { 00331 // TIMSK2 &= ~(1 << OCIE2A); //Just one interrupt needed for waking 00332 } 00333 #endif /* !AVR_CONF_USE32KCRYSTAL */ 00334 #endif /* RDC_CONF_MCU_SLEEP */ 00335