Contiki 2.5
clock.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * $Id: clock.c,v 1.1 2009/09/08 20:07:35 zdshelby Exp $
32  */
33 
34 /**
35  * \file
36  * Implementation of the clock functions for the 8051 CPU
37  * \author
38  * Zach Shelby (zach@sensinode.com)
39  */
40 
41 /**
42  * TODO: Implement clock_fine() and clock_fine_max_ticks() using another timer?
43  */
44 
45 #include <stdio.h> /*for debug printf*/
46 #include "sys/clock.h"
47 #include "sys/etimer.h"
48 #include "cc2430_sfr.h"
49 
50 
51 /*Sleep timer runs on the 32k RC osc. */
52 /* One clock tick is 7.8 ms */
53 #define TICK_VAL (32768/128)
54 
55 #define MAX_TICKS (~((clock_time_t)0) / 2)
56 
57 /* Used in sleep timer interrupt for calculating the next interrupt time */
58 static unsigned long timer_value;
59 /*starts calculating the ticks right after reset*/
60 static volatile clock_time_t count = 0;
61 /*calculates seconds*/
62 static volatile clock_time_t seconds = 0;
63 
64 /*---------------------------------------------------------------------------*/
65 /**
66  * One delay is about 0.6 us, so this function delays for len * 0.6 us
67  */
68 void
69 clock_delay(unsigned int len)
70 {
71  unsigned int i;
72  for(i = 0; i< len; i++) {
73  __asm
74  nop
75  __endasm;
76  }
77 }
78 /*---------------------------------------------------------------------------*/
79 /**
80  * Wait for a multiple of ~8 ms (a tick)
81  */
82 void
83 clock_wait(int i)
84 {
85  clock_time_t start;
86 
87  start = clock_time();
88  while(clock_time() - start < (clock_time_t)i);
89 }
90 /*---------------------------------------------------------------------------*/
91 clock_time_t
93 {
94  return count;
95 }
96 /*---------------------------------------------------------------------------*/
97 CCIF unsigned long
98 clock_seconds(void)
99 {
100  return seconds;
101 }
102 /*---------------------------------------------------------------------------*/
103 void
105 {
106  CLKCON = OSC32K | TICKSPD2|TICKSPD1|TICKSPD0; /*tickspeed 250 kHz*/
107 
108  /*Initialize tick value*/
109  timer_value = ST0; /*sleep timer 0. low bits [7:0]*/
110  timer_value += ((unsigned long int)ST1) << 8; /*middle bits [15:8]*/
111  timer_value += ((unsigned long int)ST2) << 16; /*high bits [23:16]*/
112  timer_value += TICK_VAL; /*init value 256*/
113  ST2 = (unsigned char) (timer_value >> 16);
114  ST1 = (unsigned char) (timer_value >> 8);
115  ST0 = (unsigned char) timer_value;
116 
117  IEN0 |= STIE; /*interrupt enable for sleep timers. STIE=Interrupt mask, CPU. */
118 }
119 /*---------------------------------------------------------------------------*/
120 void
121 cc2430_clock_ISR( void ) __interrupt (ST_VECTOR)
122 {
123  IEN0_EA = 0; /*interrupt disable*/
124  /* When using the cooperative scheduler the timer 2 ISR is only
125  required to increment the RTOS tick count. */
126 
127  /*Read value of the ST0,ST1,ST2 and then add TICK_VAL and write it back.
128  Next interrupt occurs after the current time + TICK_VAL*/
129  timer_value = ST0;
130  timer_value += ((unsigned long int)ST1) << 8;
131  timer_value += ((unsigned long int)ST2) << 16;
132  timer_value += TICK_VAL;
133  ST2 = (unsigned char) (timer_value >> 16);
134  ST1 = (unsigned char) (timer_value >> 8);
135  ST0 = (unsigned char) timer_value;
136 
137  ++count;
138 
139  /* Make sure the CLOCK_CONF_SECOND is a power of two, to ensure
140  that the modulo operation below becomes a logical and and not
141  an expensive divide. Algorithm from Wikipedia:
142  http://en.wikipedia.org/wiki/Power_of_two */
143 #if (CLOCK_CONF_SECOND & (CLOCK_CONF_SECOND - 1)) != 0
144 #error CLOCK_CONF_SECOND must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...).
145 #error Change CLOCK_CONF_SECOND in contiki-conf.h.
146 #endif
147  if(count % CLOCK_CONF_SECOND == 0) {
148  ++seconds;
149  }
150 
151  if(etimer_pending() &&
152  (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { /*core/sys/etimer.c*/
154  }
155 
156  IRCON &= ~STIF; /*IRCON.STIF=Sleep timer interrupt flag. This flag called this interrupt func, now reset it*/
157  IEN0_EA = 1; /*interrupt enable*/
158 }
159 /*---------------------------------------------------------------------------*/