Contiki 2.6

clock.c

00001 /*
00002  * Copyright (c) 2009, University of Colombo School of Computing
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 
00034 #include "sys/clock.h"
00035 #include "sys/etimer.h"
00036 
00037 #include <avr/io.h>
00038 #include <avr/interrupt.h>
00039 
00040 static volatile clock_time_t count, scount;
00041 static volatile unsigned long seconds;
00042 
00043 /*---------------------------------------------------------------------------*/
00044 ISR(TIMER0_COMP_vect)
00045 {
00046   count++;
00047   if(++scount == CLOCK_SECOND) {
00048     scount = 0;
00049     seconds++;
00050   }
00051   if(etimer_pending()) {
00052     etimer_request_poll();
00053   }
00054 }
00055 
00056 /*---------------------------------------------------------------------------*/
00057 void 
00058 clock_init(void)
00059 {
00060   /* Disable interrupts*/
00061   cli();
00062 
00063   /* Disable compare match interrupts and overflow interrupts. */
00064   TIMSK &= ~( _BV(TOIE0) | _BV(OCIE0) );
00065 
00066   /** 
00067    * set Timer/Counter0 to be asynchronous 
00068    * from the CPU clock with a second external 
00069    * clock(32,768kHz) driving it.
00070    */
00071   ASSR |= _BV(AS0);
00072 
00073   /*
00074    * Set timer control register:
00075    * - prescale: 32 (CS00 and CS01)
00076    * - counter reset via comparison register (WGM01)
00077    */
00078   TCCR0 = _BV(CS00) | _BV(CS01) | _BV(WGM01);
00079 
00080   /* Set counter to zero */
00081   TCNT0 = 0;
00082 
00083   /*
00084    * 128 clock ticks per second.
00085    * 32,768 = 32 * 8 * 128
00086    */
00087   OCR0 = 8;
00088 
00089   /* Clear interrupt flag register */
00090   TIFR = 0x00;
00091 
00092   /**
00093    * Wait for TCN0UB, OCR0UB, and TCR0UB.
00094    *
00095    */
00096   while(ASSR & 0x07);
00097 
00098   /* Raise interrupt when value in OCR0 is reached. */
00099   TIMSK |= _BV(OCIE0);
00100 
00101   count = 0;
00102 
00103   /* enable all interrupts*/
00104   sei();
00105 
00106 }
00107 /*---------------------------------------------------------------------------*/
00108 clock_time_t
00109 clock_time(void)
00110 {
00111   clock_time_t tmp;
00112   do {
00113     tmp = count;
00114   } while(tmp != count);
00115   return tmp;
00116 }
00117 /*---------------------------------------------------------------------------*/
00118 /**
00119  * Delay the CPU for a multiple of TODO
00120  */
00121 void
00122 clock_delay(unsigned int i)
00123 {
00124   for (; i > 0; i--) {          /* Needs fixing XXX */
00125     unsigned j;
00126     for (j = 50; j > 0; j--)
00127       asm volatile("nop");
00128   }
00129 }
00130 
00131 /*---------------------------------------------------------------------------*/
00132 /**
00133  * Wait for a multiple of 1 / 128 sec = 7.8125 ms.
00134  *
00135  */
00136 void
00137 clock_wait(clock_time_t i)
00138 {
00139   clock_time_t start;
00140 
00141   start = clock_time();
00142   while(clock_time() - start < i);
00143 }
00144 /*---------------------------------------------------------------------------*/
00145 void
00146 clock_set_seconds(unsigned long sec)
00147 {
00148     // TODO
00149 }
00150 /*---------------------------------------------------------------------------*/
00151 unsigned long
00152 clock_seconds(void)
00153 {
00154   unsigned long tmp;
00155   do {
00156     tmp = seconds;
00157   } while(tmp != seconds);
00158   return tmp;
00159 }
00160 /*---------------------------------------------------------------------------*/