Contiki 3.x
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 
32 /**
33  * \file
34  * Implementation of the clock functions for the cc253x.
35  * Ported over from the cc243x original.
36  * \author
37  * Zach Shelby (zach@sensinode.com) - original (cc243x)
38  * George Oikonomou - <oikonomou@users.sourceforge.net> - cc2530 port
39  */
40 #include "sfr-bits.h"
41 #include "sys/clock.h"
42 #include "sys/etimer.h"
43 #include "cc253x.h"
44 #include "sys/energest.h"
45 
46 /* Sleep timer runs on the 32k RC osc. */
47 /* One clock tick is 7.8 ms */
48 #define TICK_VAL (32768/128) /* 256 */
49 /*---------------------------------------------------------------------------*/
50 #if CLOCK_CONF_STACK_FRIENDLY
51 volatile uint8_t sleep_flag;
52 #endif
53 /*---------------------------------------------------------------------------*/
54 /* Do NOT remove the absolute address and do NOT remove the initialiser here */
55 __xdata __at(0x0000) static unsigned long timer_value = 0;
56 
57 static volatile CC_AT_DATA clock_time_t count = 0; /* Uptime in ticks */
58 static volatile CC_AT_DATA clock_time_t seconds = 0; /* Uptime in secs */
59 /*---------------------------------------------------------------------------*/
60 /**
61  * Each iteration is ~1.0xy usec, so this function delays for roughly len usec
62  */
63 void
64 clock_delay_usec(uint16_t len)
65 {
67  while(len--) {
68  ASM(nop);
69  }
70  ENABLE_INTERRUPTS();
71 }
72 /*---------------------------------------------------------------------------*/
73 /**
74  * Wait for a multiple of ~8 ms (a tick)
75  */
76 void
77 clock_wait(clock_time_t i)
78 {
79  clock_time_t start;
80 
81  start = clock_time();
82  while(clock_time() - start < (clock_time_t)i);
83 }
84 /*---------------------------------------------------------------------------*/
85 CCIF clock_time_t
87 {
88  return count;
89 }
90 /*---------------------------------------------------------------------------*/
91 CCIF unsigned long
93 {
94  return seconds;
95 }
96 /*---------------------------------------------------------------------------*/
97 /*
98  * There is some ambiguity between TI cc2530 software examples and information
99  * in the datasheet.
100  *
101  * TI examples appear to be writing to SLEEPCMD, initialising hardware in a
102  * fashion semi-similar to cc2430
103  *
104  * However, the datasheet claims that those bits in SLEEPCMD are reserved
105  *
106  * The code here goes by the datasheet (ignore TI examples) and seems to work.
107  */
108 void
110 {
111  /* Make sure we know where we stand */
112  CLKCONCMD = CLKCONCMD_OSC32K | CLKCONCMD_OSC;
113 
114  /* Stay with 32 KHz RC OSC, Chance System Clock to 32 MHz */
115  CLKCONCMD &= ~CLKCONCMD_OSC;
116  while(CLKCONSTA & CLKCONCMD_OSC);
117 
118  /* Tickspeed 500 kHz for timers[1-4] */
119  CLKCONCMD |= CLKCONCMD_TICKSPD2 | CLKCONCMD_TICKSPD1;
120  while(CLKCONSTA != CLKCONCMD);
121 
122  /* Initialize tick value */
123  timer_value = ST0;
124  timer_value += ((unsigned long int)ST1) << 8;
125  timer_value += ((unsigned long int)ST2) << 16;
126  timer_value += TICK_VAL;
127  ST2 = (unsigned char)(timer_value >> 16);
128  ST1 = (unsigned char)(timer_value >> 8);
129  ST0 = (unsigned char)timer_value;
130 
131  STIE = 1; /* IEN0.STIE interrupt enable */
132 }
133 /*---------------------------------------------------------------------------*/
134 /* avoid referencing bits, we don't call code which use them */
135 #pragma save
136 #if CC_CONF_OPTIMIZE_STACK_SIZE
137 #pragma exclude bits
138 #endif
139 void
140 clock_isr(void) __interrupt(ST_VECTOR)
141 {
143  ENERGEST_ON(ENERGEST_TYPE_IRQ);
144 
145  /*
146  * Read value of the ST0:ST1:ST2, add TICK_VAL and write it back.
147  * Next interrupt occurs after the current time + TICK_VAL
148  */
149  timer_value = ST0;
150  timer_value += ((unsigned long int)ST1) << 8;
151  timer_value += ((unsigned long int)ST2) << 16;
152  timer_value += TICK_VAL;
153  ST2 = (unsigned char)(timer_value >> 16);
154  ST1 = (unsigned char)(timer_value >> 8);
155  ST0 = (unsigned char)timer_value;
156 
157  ++count;
158 
159  /* Make sure the CLOCK_CONF_SECOND is a power of two, to ensure
160  that the modulo operation below becomes a logical and and not
161  an expensive divide. Algorithm from Wikipedia:
162  http://en.wikipedia.org/wiki/Power_of_two */
163 #if (CLOCK_CONF_SECOND & (CLOCK_CONF_SECOND - 1)) != 0
164 #error CLOCK_CONF_SECOND must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...).
165 #error Change CLOCK_CONF_SECOND in contiki-conf.h.
166 #endif
167  if(count % CLOCK_CONF_SECOND == 0) {
168  ++seconds;
169  }
170 
171 #if CLOCK_CONF_STACK_FRIENDLY
172  sleep_flag = 1;
173 #else
174  if(etimer_pending()
175  && (etimer_next_expiration_time() - count - 1) > MAX_TICKS) {
177  }
178 #endif
179 
180  STIF = 0; /* IRCON.STIF */
181  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
182  ENABLE_INTERRUPTS();
183 }
184 #pragma restore
185 /*---------------------------------------------------------------------------*/
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:94
Definitions for TI/Chipcon cc2530, cc2531 and cc2533 SFR registers.
void clock_init(void)
Initialize the clock library.
Definition: clock.c:76
Header file with definitions of bit masks for some cc2530 SFRs
Header file for the energy estimation mechanism
CCIF clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:41
clock_time_t etimer_next_expiration_time(void)
Get next event timer expiration time.
Definition: etimer.c:229
void etimer_request_poll(void)
Make the event timer aware that the clock has changed.
Definition: etimer.c:145
CCIF unsigned long clock_seconds(void)
Get the current value of the platform seconds.
Definition: clock.c:57
int etimer_pending(void)
Check if there are any non-expired event timers.
Definition: etimer.c:223
#define DISABLE_INTERRUPTS()
Disable interrupts, saving the previous state so it can be later restored with RESTORE_INTERRUPTS().
Definition: gnu.h:405
void clock_wait(clock_time_t t)
Wait for a given number of ticks.
Definition: clock.c:166
__xdata __at(0x0000)
Each iteration is ~1.0xy usec, so this function delays for roughly len usec.
Definition: clock.c:55
Event timer header file.
void clock_isr(void)
The clock Interrupt Service Routine.
Definition: clock.c:238