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 cc243x
35  * \author
36  * Zach Shelby (zach@sensinode.com) - original
37  * George Oikonomou - <oikonomou@users.sourceforge.net>
38  */
39 #include "sys/clock.h"
40 #include "sys/etimer.h"
41 #include "cc2430_sfr.h"
42 #include "sys/energest.h"
43 
44 /* Sleep timer runs on the 32k RC osc. */
45 /* One clock tick is 7.8 ms */
46 #define TICK_VAL (32768/128) /* 256 */
47 /*---------------------------------------------------------------------------*/
48 #if CLOCK_CONF_STACK_FRIENDLY
49 volatile uint8_t sleep_flag;
50 #endif
51 /*---------------------------------------------------------------------------*/
52 /* Used in sleep timer interrupt for calculating the next interrupt time */
53 static unsigned long timer_value;
54 static volatile CC_AT_DATA clock_time_t count = 0; /* Uptime in ticks */
55 static volatile CC_AT_DATA clock_time_t seconds = 0; /* Uptime in secs */
56 /*---------------------------------------------------------------------------*/
57 /**
58  * Each iteration is ~1.0xy usec, so this function delays for roughly len usec
59  */
60 void
61 clock_delay_usec(uint16_t len)
62 {
64  while(len--) {
65  ASM(nop); ASM(nop);
66  ASM(nop); ASM(nop);
67  }
68  ENABLE_INTERRUPTS();
69 }
70 /*---------------------------------------------------------------------------*/
71 /**
72  * Wait for a multiple of ~8 ms (a tick)
73  */
74 void
75 clock_wait(clock_time_t i)
76 {
77  clock_time_t start;
78 
79  start = clock_time();
80  while(clock_time() - start < (clock_time_t)i);
81 }
82 /*---------------------------------------------------------------------------*/
83 CCIF clock_time_t
85 {
86  return count;
87 }
88 /*---------------------------------------------------------------------------*/
89 CCIF unsigned long
91 {
92  return seconds;
93 }
94 /*---------------------------------------------------------------------------*/
95 void
97 {
98  CLKCON = OSC32K | TICKSPD2 | TICKSPD1; /* tickspeed 500 kHz for timers[1-4] */
99 
100  /* Initialize tick value */
101  timer_value = ST0; /* ST low bits [7:0] */
102  timer_value += ((unsigned long int)ST1) << 8; /* middle bits [15:8] */
103  timer_value += ((unsigned long int)ST2) << 16; /* high bits [23:16] */
104  timer_value += TICK_VAL; /* Init value 256 */
105  ST2 = (unsigned char)(timer_value >> 16);
106  ST1 = (unsigned char)(timer_value >> 8);
107  ST0 = (unsigned char)timer_value;
108 
109  IEN0_STIE = 1; /* IEN0.STIE acknowledge Sleep Timer Interrupt */
110 }
111 /*---------------------------------------------------------------------------*/
112 #pragma save
113 #if CC_CONF_OPTIMIZE_STACK_SIZE
114 #pragma exclude bits
115 #endif
116 void
117 clock_ISR(void) __interrupt(ST_VECTOR)
118 {
120  ENERGEST_ON(ENERGEST_TYPE_IRQ);
121 
122  /*
123  * If the Sleep timer throws an interrupt while we are powering down to
124  * PM1, we need to abort the power down. Clear SLEEP.MODE, this will signal
125  * main() to abort the PM1 transition
126  */
127  SLEEP &= 0xFC;
128 
129  /*
130  * Read value of the ST0:ST1:ST2, add TICK_VAL and write it back.
131  * Next interrupt occurs after the current time + TICK_VAL
132  */
133  timer_value = ST0;
134  timer_value += ((unsigned long int)ST1) << 8;
135  timer_value += ((unsigned long int)ST2) << 16;
136  timer_value += TICK_VAL;
137  ST2 = (unsigned char)(timer_value >> 16);
138  ST1 = (unsigned char)(timer_value >> 8);
139  ST0 = (unsigned char)timer_value;
140 
141  ++count;
142 
143  /* Make sure the CLOCK_CONF_SECOND is a power of two, to ensure
144  that the modulo operation below becomes a logical and and not
145  an expensive divide. Algorithm from Wikipedia:
146  http://en.wikipedia.org/wiki/Power_of_two */
147 #if (CLOCK_CONF_SECOND & (CLOCK_CONF_SECOND - 1)) != 0
148 #error CLOCK_CONF_SECOND must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...).
149 #error Change CLOCK_CONF_SECOND in contiki-conf.h.
150 #endif
151  if(count % CLOCK_CONF_SECOND == 0) {
152  ++seconds;
153  }
154 
155 #if CLOCK_CONF_STACK_FRIENDLY
156  sleep_flag = 1;
157 #else
158  if(etimer_pending()
159  && (etimer_next_expiration_time() - count - 1) > MAX_TICKS) {
161  }
162 #endif
163 
164  IRCON_STIF = 0;
165  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
166  ENABLE_INTERRUPTS();
167 }
168 #pragma restore
169 /*---------------------------------------------------------------------------*/
CC2430 registers header file for CC2430.
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:94
void clock_init(void)
Initialize the clock library.
Definition: clock.c:76
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
#define SLEEP
Constant SLEEP for sub-register SR_TRX_STATUS.
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
Event timer header file.