Contiki-NG
clock.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/
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 *
14 * 3. Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31/**
32 * \addtogroup cc2538
33 * @{
34 *
35 * \defgroup cc2538-clock cc2538 Clock
36 *
37 * Implementation of the clock module for the cc2538
38 *
39 * To implement the clock functionality, we use the SysTick peripheral on the
40 * cortex-M3. We run the system clock at a configurable speed and set the
41 * SysTick to give us 128 interrupts / sec. However, the Sleep Timer counter
42 * value is used for the number of elapsed ticks in order to avoid a
43 * significant time drift caused by PM1/2. Contrary to the Sleep Timer, the
44 * SysTick peripheral is indeed frozen during PM1/2, so adjusting upon wake-up
45 * a tick counter based on this peripheral would hardly be accurate.
46 * @{
47 *
48 * \file
49 * Clock driver implementation for the TI cc2538
50 */
51#include "contiki.h"
52#include "cc2538_cm3.h"
53#include "reg.h"
54#include "cpu.h"
55#include "dev/gptimer.h"
56#include "dev/sys-ctrl.h"
57
58#include "sys/energest.h"
59#include "sys/etimer.h"
60#include "sys/rtimer.h"
61
62#include <stdint.h>
63/*---------------------------------------------------------------------------*/
64#define RTIMER_CLOCK_TICK_RATIO (RTIMER_SECOND / CLOCK_SECOND)
65
66/* Prescaler for GPT0:Timer A used for clock_delay_usec(). */
67#if SYS_CTRL_SYS_CLOCK < SYS_CTRL_1MHZ
68#error System clock speeds below 1MHz are not supported
69#endif
70#define PRESCALER_VALUE (SYS_CTRL_SYS_CLOCK / SYS_CTRL_1MHZ - 1)
71
72/* Period of the SysTick counter expressed as a number of ticks */
73#if SYS_CTRL_SYS_CLOCK % CLOCK_SECOND
74/* Too low clock speeds will lead to reduced accurracy */
75#error System clock speed too slow for CLOCK_SECOND, accuracy reduced
76#endif
77#define SYSTICK_PERIOD (SYS_CTRL_SYS_CLOCK / CLOCK_SECOND)
78
79static volatile uint64_t rt_ticks_startup = 0, rt_ticks_epoch = 0;
80/*---------------------------------------------------------------------------*/
81/**
82 * \brief Arch-specific implementation of clock_init for the cc2538
83 *
84 * We initialise the SysTick to fire 128 interrupts per second, giving us a
85 * value of 128 for CLOCK_SECOND
86 *
87 * We also initialise GPT0:Timer A, which is used by clock_delay_usec().
88 * We use 16-bit range (individual), count-down, one-shot, no interrupts.
89 * The prescaler is computed according to the system clock in order to get 1
90 * tick per usec.
91 */
92void
94{
95 SysTick_Config(SYSTICK_PERIOD);
96
97 /*
98 * Remove the clock gate to enable GPT0 and then initialise it
99 * We only use GPT0 for clock_delay_usec. We initialise it here so we can
100 * have it ready when it's needed
101 */
103
104 /* Make sure GPT0 is off */
105 REG(GPT_0_BASE + GPTIMER_CTL) = 0;
106
107 /* 16-bit */
108 REG(GPT_0_BASE + GPTIMER_CFG) = 0x04;
109
110 /* One-Shot, Count Down, No Interrupts */
111 REG(GPT_0_BASE + GPTIMER_TAMR) = GPTIMER_TAMR_TAMR_ONE_SHOT;
112
113 /* Prescale depending on system clock used */
114 REG(GPT_0_BASE + GPTIMER_TAPR) = PRESCALER_VALUE;
115}
116/*---------------------------------------------------------------------------*/
117clock_time_t
119{
120 return rt_ticks_startup / RTIMER_CLOCK_TICK_RATIO;
121}
122/*---------------------------------------------------------------------------*/
123void
124clock_set_seconds(unsigned long sec)
125{
126 rt_ticks_epoch = (uint64_t)sec * RTIMER_SECOND;
127}
128/*---------------------------------------------------------------------------*/
129unsigned long
131{
132 return rt_ticks_epoch / RTIMER_SECOND;
133}
134/*---------------------------------------------------------------------------*/
135void
136clock_wait(clock_time_t i)
137{
138 clock_time_t start;
139
140 start = clock_time();
141 while(clock_time() - start < (clock_time_t)i);
142}
143/*---------------------------------------------------------------------------*/
144/*
145 * Arch-specific implementation of clock_delay_usec for the cc2538
146 *
147 * See clock_init() for GPT0 Timer A's configuration
148 */
149void
151{
152 REG(GPT_0_BASE + GPTIMER_TAILR) = dt;
154
155 /* One-Shot mode: TAEN will be cleared when the timer reaches 0 */
157}
158/*---------------------------------------------------------------------------*/
159/**
160 * \brief Obsolete delay function but we implement it here since some code
161 * still uses it
162 */
163void
164clock_delay(unsigned int i)
165{
167}
168/*---------------------------------------------------------------------------*/
169/**
170 * \brief Update the software clock ticks and seconds
171 *
172 * This function is used to update the software tick counters whenever the
173 * system clock might have changed, which can occur upon a SysTick ISR or upon
174 * wake-up from PM1/2.
175 *
176 * For the software clock ticks counter, the Sleep Timer counter value is used
177 * as the base tick value, and extended to a 64-bit value thanks to a detection
178 * of wraparounds.
179 *
180 * For the seconds counter, the changes of the Sleep Timer counter value are
181 * added to the reference time, which is either the startup time or the value
182 * passed to clock_set_seconds().
183 *
184 * This function polls the etimer process if an etimer has expired.
185 */
186static void
188{
189 rtimer_clock_t now;
190 uint64_t prev_rt_ticks_startup, cur_rt_ticks_startup;
191 uint32_t cur_rt_ticks_startup_hi;
192
193 now = RTIMER_NOW();
194 prev_rt_ticks_startup = rt_ticks_startup;
195
196 cur_rt_ticks_startup_hi = prev_rt_ticks_startup >> 32;
197 if(now < (rtimer_clock_t)prev_rt_ticks_startup) {
198 cur_rt_ticks_startup_hi++;
199 }
200 cur_rt_ticks_startup = (uint64_t)cur_rt_ticks_startup_hi << 32 | now;
201 rt_ticks_startup = cur_rt_ticks_startup;
202
203 rt_ticks_epoch += cur_rt_ticks_startup - prev_rt_ticks_startup;
204
205 /*
206 * Inform the etimer library that the system clock has changed and that an
207 * etimer might have expired.
208 */
209 if(etimer_pending()) {
211 }
212}
213/*---------------------------------------------------------------------------*/
214/**
215 * \brief Adjust the clock following missed SysTick ISRs
216 *
217 * This function is useful when coming out of PM1/2, during which the system
218 * clock is stopped. We adjust the clock counters like after any SysTick ISR.
219 *
220 * \note This function is only meant to be used by lpm_exit(). Applications
221 * should really avoid calling this
222 */
223void
225{
226 /* Halt the SysTick while adjusting */
227 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
228
229 update_ticks();
230
231 /* Re-Start the SysTick */
232 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
233}
234/*---------------------------------------------------------------------------*/
235/**
236 * \brief The clock Interrupt Service Routine
237 *
238 * It polls the etimer process if an etimer has expired. It also updates the
239 * software clock tick and seconds counter.
240 */
241void
243{
244 update_ticks();
245}
246/*---------------------------------------------------------------------------*/
247
248/**
249 * @}
250 * @}
251 */
CMSIS Cortex-M3 core peripheral access layer header file for CC2538.
Header file with prototypes for interrupt control on the cc2538 Cortex-M3 micro.
Header file for the energy estimation mechanism.
Event timer header file.
Header file for the cc2538 General Purpose Timers.
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_adjust(void)
Adjust the clock following missed SysTick ISRs.
Definition: clock.c:224
static void update_ticks(void)
Update the software clock ticks and seconds.
Definition: clock.c:187
void clock_init(void)
Arch-specific implementation of clock_init for the cc2538.
Definition: clock.c:93
void clock_isr(void)
The clock Interrupt Service Routine.
Definition: clock.c:242
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:150
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
#define GPTIMER_CFG
GPTM configuration.
Definition: gptimer.h:58
#define GPT_0_BASE
GPTIMER0.
Definition: gptimer.h:49
#define GPTIMER_TAMR
GPTM Timer A mode.
Definition: gptimer.h:59
#define GPTIMER_CTL_TAEN
Timer A enable.
Definition: gptimer.h:149
#define GPTIMER_TAILR
GPTM Timer A interval load.
Definition: gptimer.h:67
#define GPTIMER_TAPR
GPTM Timer A prescale.
Definition: gptimer.h:71
#define GPTIMER_CTL
GPTM control.
Definition: gptimer.h:61
#define SYS_CTRL_RCGCGPT_GPT0
GPT0 clock enable, CPU running.
Definition: sys-ctrl.h:139
#define SYS_CTRL_RCGCGPT
GPT[3:0] clocks - active mode.
Definition: sys-ctrl.h:67
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
#define RTIMER_SECOND
Number of rtimer ticks for 1 second.
Definition: rtimer.h:112
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:185
static void start(void)
Start measurement.
Header file with register manipulation macro definitions.
Header file for the real-time timer module.
Header file for the cc2538 System Control driver.