Contiki-NG
clock.c
1/*
2 * Copyright (c) 2005, 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 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 */
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 = TAR;
59 t2 = TAR;
60 } while(t1 != t2);
61 return t1;
62}
63/*---------------------------------------------------------------------------*/
64ISR(TIMERA1, timera1)
65{
67
68 if(TAIV == 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(TACTL & MC1 && TACCR1 - read_tar() == 1);
73
74 last_tar = read_tar();
75 /* Make sure interrupt time is future */
76 while(!CLOCK_LT(last_tar, TACCR1)) {
77 TACCR1 += 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
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 TAR = fclock;
124 TACCR1 = 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) (TAR - 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 /* TACTL = TASSEL0 | TACLR | ID_1;*/
154
155 /* Select ACLK 32768Hz clock */
156 /* TACTL = TASSEL0 | TACLR; */
157
158#if INTERVAL==32768/CLOCK_SECOND
159 TACTL = TASSEL0 | TACLR;
160#elif INTERVAL==16384/CLOCK_SECOND
161 TACTL = TASSEL0 | TACLR | ID_1;
162#else
163#error NEED TO UPDATE clock.c to match interval!
164#endif
165
166 /* Initialize ccr1 to create the X ms interval. */
167 /* CCR1 interrupt enabled, interrupt occurs when timer equals CCR. */
168 TACCTL1 = CCIE;
169
170 /* Interrupt after X ms. */
171 TACCR1 = INTERVAL;
172
173 /* Start Timer_A in continuous mode. */
174 TACTL |= MC1;
175
176 count = 0;
177
178 /* Enable interrupts. */
179 eint();
180
181}
182/*---------------------------------------------------------------------------*/
183/**
184 * Delay the CPU for a multiple of 2.83 us.
185 */
186void
187clock_delay(unsigned int i)
188{
189 while(i--) {
190 _NOP();
191 }
192}
193/*---------------------------------------------------------------------------*/
194/*
195 * Wait for a multiple of 10 ms.
196 *
197 */
198void
199clock_wait(clock_time_t i)
200{
201 clock_time_t start;
202
203 start = clock_time();
204 while(clock_time() - start < (clock_time_t)i);
205}
206/*---------------------------------------------------------------------------*/
207void
208clock_set_seconds(unsigned long sec)
209{
210 int s;
211 s = splhigh();
212 seconds = sec;
213 splx(s);
214}
215/*---------------------------------------------------------------------------*/
216unsigned long
218{
219 unsigned long t1, t2;
220 do {
221 t1 = seconds;
222 t2 = seconds;
223 } while(t1 != t2);
224 return t1;
225}
226/*---------------------------------------------------------------------------*/
227rtimer_clock_t
228clock_counter(void)
229{
230 rtimer_clock_t t1, t2;
231 do {
232 t1 = TAR;
233 t2 = TAR;
234 } while(t1 != t2);
235 return t1;
236}
237/*---------------------------------------------------------------------------*/
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
void watchdog_start(void)
Starts the WDT in watchdog mode if enabled by user configuration, maximum interval.
Definition: watchdog.c:72
static volatile uint64_t count
Num.
Definition: clock.c:50
void watchdog_stop(void)
Stops the WDT such that it won't timeout and cause MCU reset.
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:231
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:237
static void start(void)
Start measurement.