Contiki-NG
Loading...
Searching...
No Matches
clock.c
1/*
2 * Copyright (c) 2011, 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#include "contiki.h"
33#include "sys/clock.h"
34#include "sys/etimer.h"
35#include "sys/energest.h"
36#include "rtimer-arch.h"
37#include "dev/watchdog.h"
38#include "isr_compat.h"
39
40#define INTERVAL (RTIMER_ARCH_SECOND / CLOCK_SECOND)
41
42#define MAX_TICKS (~((clock_time_t)0) / 2)
43
44#define HW_CLOCK_LT(a, b) ((int16_t)((a)-(b)) < 0)
45
46static volatile unsigned long seconds;
47
48static volatile clock_time_t count = 0;
49/* last_tar is used for calculating clock_fine, last_ccr might be better? */
50static volatile uint16_t last_tar = 0;
51/*---------------------------------------------------------------------------*/
52static inline uint16_t
53read_tar(void)
54{
55 /* Same as clock_counter(), but can be inlined */
56 uint16_t t1, t2;
57 do {
58 t1 = TA1R;
59 t2 = TA1R;
60 } while(t1 != t2);
61 return t1;
62}
63/*---------------------------------------------------------------------------*/
64ISR(TIMER1_A1, timera1)
65{
66 /* watchdog_start(); */
67
68 if(TA1IV == 2) {
69
70 /* HW timer bug fix: Interrupt handler called before TR==CCR.
71 * Occurs when timer state is toggled between STOP and CONT. */
72 while(TA1CTL & MC1 && TA1CCR1 - TA1R == 1);
73
74 last_tar = read_tar();
75 /* Make sure interrupt time is future */
76 while(!HW_CLOCK_LT(last_tar, TA1CCR1)) {
77 TA1CCR1 += INTERVAL;
78 ++count;
79
80 /* Make sure the CLOCK_CONF_SECOND is a power of two, to ensure
81 that the modulo operation below becomes a logical and and not
82 an expensive divide. Algorithm from Wikipedia:
83 http://en.wikipedia.org/wiki/Power_of_two */
84#if (CLOCK_CONF_SECOND & (CLOCK_CONF_SECOND - 1)) != 0
85#error CLOCK_CONF_SECOND must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...).
86#error Change CLOCK_CONF_SECOND in contiki-conf.h.
87#endif
88 if(count % CLOCK_CONF_SECOND == 0) {
89 ++seconds;
90 energest_flush();
91 }
92 last_tar = read_tar();
93 }
94
95 if(etimer_pending() &&
96 (etimer_next_expiration_time() - count - 1) > MAX_TICKS) {
98 LPM4_EXIT;
99 }
100
101 }
102 /* if(process_nevents() >= 0) {
103 LPM4_EXIT;
104 }*/
105
106 /* watchdog_stop(); */
107}
108/*---------------------------------------------------------------------------*/
109clock_time_t
111{
112 clock_time_t t1, t2;
113 do {
114 t1 = count;
115 t2 = count;
116 } while(t1 != t2);
117 return t1;
118}
119/*---------------------------------------------------------------------------*/
120void
121clock_set(clock_time_t clock, clock_time_t fclock)
122{
123 TA1R = fclock;
124 TA1CCR1 = fclock + INTERVAL;
125 count = clock;
126}
127/*---------------------------------------------------------------------------*/
128int
130{
131 return INTERVAL;
132}
133/*---------------------------------------------------------------------------*/
134unsigned short
135clock_fine(void)
136{
137 unsigned short t;
138 /* Assign last_tar to local varible that can not be changed by interrupt */
139 t = last_tar;
140 /* perform calc based on t, TAR will not be changed during interrupt */
141 return (unsigned short) (TA1R - t);
142}
143/*---------------------------------------------------------------------------*/
144void
146{
147 dint();
148
149 /* Select SMCLK (2.4576MHz), clear TAR */
150 /* TACTL = TASSEL1 | TACLR | ID_3; */
151
152 /* Select ACLK 32768Hz clock, divide by 2 */
153/* TA1CTL = TASSEL0 | TACLR | ID_1; */
154
155#if INTERVAL==32768/CLOCK_SECOND
156 TA1CTL = TASSEL0 | TACLR;
157#elif INTERVAL==16384/CLOCK_SECOND
158 TA1CTL = TASSEL0 | TACLR | ID_1;
159#else
160#error NEED TO UPDATE clock.c to match interval!
161#endif
162
163 /* Initialize ccr1 to create the X ms interval. */
164 /* CCR1 interrupt enabled, interrupt occurs when timer equals CCR1. */
165 TA1CCTL1 = CCIE;
166
167 /* Interrupt after X ms. */
168 TA1CCR1 = INTERVAL;
169
170 /* Start Timer_A in continuous mode. */
171 TA1CTL |= MC1;
172
173 count = 0;
174
175 /* Enable interrupts. */
176 eint();
177
178}
179/*---------------------------------------------------------------------------*/
180/**
181 * Delay the CPU for a multiple of 2.83 us.
182 */
183void
184clock_delay(unsigned int i)
185{
186 while(i--) {
187 _NOP();
188 }
189}
190/*---------------------------------------------------------------------------*/
191/*
192 * Wait for a multiple of 10 ms.
193 *
194 */
195void
196clock_wait(clock_time_t i)
197{
198 clock_time_t start;
199
200 start = clock_time();
201 while(clock_time() - start < (clock_time_t)i);
202}
203/*---------------------------------------------------------------------------*/
204void
205clock_set_seconds(unsigned long sec)
206{
207 int s;
208 s = splhigh();
209 seconds = sec;
210 splx(s);
211}
212/*---------------------------------------------------------------------------*/
213unsigned long
215{
216 unsigned long t1, t2;
217 do {
218 t1 = seconds;
219 t2 = seconds;
220 } while(t1 != t2);
221 return t1;
222}
223/*---------------------------------------------------------------------------*/
224rtimer_clock_t
225clock_counter(void)
226{
227 rtimer_clock_t t1, t2;
228 do {
229 t1 = TA1R;
230 t2 = TA1R;
231 } while(t1 != t2);
232 return t1;
233}
234/*---------------------------------------------------------------------------*/
Header file for the energy estimation mechanism.
Event timer header file.
void clock_set_seconds(unsigned long sec)
Set the value of the platform seconds.
Definition clock.c:124
unsigned long clock_seconds(void)
Get the current value of the platform seconds.
Definition clock.c:130
void clock_init(void)
Arch-specific implementation of clock_init for the cc2538.
Definition clock.c:93
void clock_wait(clock_time_t i)
Wait for a given number of ticks.
Definition clock.c:136
clock_time_t clock_time(void)
Get the current clock time.
Definition clock.c:118
void clock_delay(unsigned int i)
Obsolete delay function but we implement it here since some code still uses it.
Definition clock.c:164
static volatile uint64_t count
Num.
Definition clock.c:50
int clock_fine_max(void)
Deprecated platform-specific routines.
Definition clock.c:129
int etimer_pending(void)
Check if there are any non-expired event timers.
Definition etimer.c:225
void etimer_request_poll(void)
Make the event timer aware that the clock has changed.
Definition etimer.c:145
clock_time_t etimer_next_expiration_time(void)
Get next event timer expiration time.
Definition etimer.c:231
static void start(void)
Start measurement.