Contiki 2.6

rtimer-arch.c

Go to the documentation of this file.
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