Contiki-NG
Loading...
Searching...
No Matches
clock-arch.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018, 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 * 3. Neither the name of the copyright holder nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30/**
31 * \addtogroup cc13xx-cc26xx-clock
32 * @{
33 *
34 * \file
35 * Implementation of the clock libary for CC13xx/CC26xx.
36 *
37 * The periodic polling of etimer is implemented using SysTick. Since
38 * SysTick is paused when the system clock stopped, that is when the
39 * device enters some low-power mode, a wakeup clock is armed with the
40 * next etimer expiration time OR watchdog timeout everytime the device
41 * enters some low-power mode.
42 */
43/*---------------------------------------------------------------------------*/
44#include "contiki.h"
45#include "sys/cc.h"
46#include "sys/clock.h"
47#include "sys/etimer.h"
48/*---------------------------------------------------------------------------*/
49#include <ti/devices/DeviceFamily.h>
50#include DeviceFamily_constructPath(driverlib/aon_rtc.h)
51#include DeviceFamily_constructPath(driverlib/systick.h)
52
53#include <ti/drivers/dpl/ClockP.h>
54#include <ti/drivers/power/PowerCC26XX.h>
55/*---------------------------------------------------------------------------*/
56#include "watchdog-arch.h"
57/*---------------------------------------------------------------------------*/
58#include <stdbool.h>
59#include <stdint.h>
60/*---------------------------------------------------------------------------*/
61static ClockP_Struct wakeup_clk;
62/*---------------------------------------------------------------------------*/
63#define H_WAKEUP_CLK (ClockP_handle(&wakeup_clk))
64
65#define NO_TIMEOUT (~(uint32_t)0)
66
67#define CLOCK_TO_SYSTEM(t) \
68 (uint32_t)(((uint64_t)(t) * 1000 * 1000) / (CLOCK_SECOND * ClockP_getSystemTickPeriod()))
69#define SYSTEM_TO_CLOCK(t) \
70 (clock_time_t)(((uint64_t)(t) * CLOCK_SECOND * ClockP_getSystemTickPeriod()) / (1000 * 1000))
71
72#define RTC_SUBSEC_FRAC ((uint64_t)1 << 32) /* Important to cast to 64-bit */
73/*---------------------------------------------------------------------------*/
74static void
75check_etimer(void)
76{
77 clock_time_t now;
78 clock_time_t next_etimer;
79
80 if(etimer_pending()) {
81 now = clock_time();
82 next_etimer = etimer_next_expiration_time();
83
84 if(!CLOCK_LT(now, next_etimer)) {
86 }
87 }
88}
89/*---------------------------------------------------------------------------*/
90static void
91systick_fxn(void)
92{
93 check_etimer();
94}
95/*---------------------------------------------------------------------------*/
96static void
97wakeup_fxn(uintptr_t arg)
98{
99 (void)arg;
100 check_etimer();
101}
102/*---------------------------------------------------------------------------*/
103static uint32_t
104get_etimer_timeout(void)
105{
106 clock_time_t now;
107 clock_time_t next_etimer;
108
109 if(etimer_pending()) {
110 now = clock_time();
111 next_etimer = etimer_next_expiration_time();
112
113 if(!CLOCK_LT(now, next_etimer)) {
115 /* etimer already expired, return 0 */
116 return 0;
117
118 } else {
119 /* Convert from clock ticks to system ticks */
120 return CLOCK_TO_SYSTEM(next_etimer - now);
121 }
122 } else {
123 /* No expiration */
124 return NO_TIMEOUT;
125 }
126}
127/*---------------------------------------------------------------------------*/
128static uint32_t
129get_watchdog_timeout(void)
130{
131#if (WATCHDOG_DISABLE == 0)
132 /* Convert from watchdog ticks to system ticks */
133 return watchdog_arch_next_timeout() / ClockP_getSystemTickPeriod();
134
135#else
136 /* No expiration */
137 return NO_TIMEOUT;
138#endif
139}
140/*---------------------------------------------------------------------------*/
141bool
143{
144 /*
145 * If the Watchdog is enabled, we must take extra care to wakeup before the
146 * Watchdog times out if the next watchdog timeout is before the next etimer
147 * timeout. This is because the Watchdog only pauses if the device enters
148 * standby. If the device enters idle, the Watchdog still runs and hence the
149 * watchdog will timeout if the next etimer timeout is longer than the
150 * watchdog timeout.
151 */
152
153 uint32_t etimer_timeout;
154 uint32_t watchdog_timeout;
155 uint32_t timeout;
156
157 etimer_timeout = get_etimer_timeout();
158 watchdog_timeout = get_watchdog_timeout();
159
160 timeout = MIN(etimer_timeout, watchdog_timeout);
161 if(timeout == 0) {
162 /* We are not going to sleep, and hence we don't arm the wakeup clock. */
163 return false;
164 }
165
166 /* We are dropping to some low-power mode */
167
168 /* Arm the wakeup clock with the calculated timeout if there is any */
169 if(timeout != NO_TIMEOUT) {
170 ClockP_setTimeout(H_WAKEUP_CLK, timeout);
171 ClockP_start(H_WAKEUP_CLK);
172 }
173
174 return true;
175}
176/*---------------------------------------------------------------------------*/
177void
179{
180 ClockP_stop(H_WAKEUP_CLK);
181}
182/*---------------------------------------------------------------------------*/
183void
185{
186 /*
187 * XXX: Workaround for an observed issue where if SysTick interrupt is not
188 * disabled when entering/leaving some low-power mode may in very rare
189 * occasions clobber the CPU and cause a crash.
190 */
191 SysTickIntDisable();
192
193 /* Drop to some low-power mode */
194 PowerCC26XX_standbyPolicy();
195
196 SysTickIntEnable();
197}
198/*---------------------------------------------------------------------------*/
199void
201{
202 ClockP_Params clk_params;
203 ClockP_FreqHz freq;
204
205 ClockP_Params_init(&clk_params);
206 clk_params.startFlag = false;
207 clk_params.period = 0;
208 ClockP_construct(&wakeup_clk, wakeup_fxn, 0, &clk_params);
209
210 ClockP_getCpuFreq(&freq);
211
212 SysTickPeriodSet(freq.lo / CLOCK_SECOND);
213 SysTickIntRegister(systick_fxn);
214 SysTickIntEnable();
215 SysTickEnable();
216
217 /* enable sync with radio timer */
218 HWREGBITW(AON_RTC_BASE + AON_RTC_O_CTL, AON_RTC_CTL_RTC_UPD_EN_BITN) = 1;
219}
220/*---------------------------------------------------------------------------*/
221clock_time_t
223{
224 /*
225 * RTC counter is in a 64-bits format (SEC[31:0].SUBSEC[31:0]), where SUBSEC
226 * is represented in fractions of a second (VALUE/2^32).
227 */
228 uint64_t now = AONRTCCurrent64BitValueGet();
229 clock_time_t ticks = (clock_time_t)(now / (RTC_SUBSEC_FRAC / CLOCK_SECOND));
230 return ticks;
231}
232/*---------------------------------------------------------------------------*/
233unsigned long
235{
236 unsigned long sec = (unsigned long)AONRTCSecGet();
237 return sec;
238}
239/*---------------------------------------------------------------------------*/
240void
241clock_wait(clock_time_t i)
242{
243 uint32_t usec;
244
245 usec = (uint32_t)((1000 * 1000 * i) / CLOCK_SECOND);
246 clock_delay_usec(usec);
247}
248/*---------------------------------------------------------------------------*/
249void
250clock_delay_usec(uint16_t usec)
251{
252 ClockP_usleep(usec);
253}
254/*---------------------------------------------------------------------------*/
255/**
256 * \brief Obsolete delay function but we implement it here since some code
257 * still uses it.
258 */
259void
260clock_delay(unsigned int i)
261{
263}
264/*---------------------------------------------------------------------------*/
265/**
266 * @}
267 */
Default definitions of C compiler quirk work-arounds.
Event timer header file.
bool clock_arch_enter_idle(void)
Prepare to enter some low-power mode.
Definition clock-arch.c:142
void clock_arch_exit_idle(void)
Cleanup after returning from low-power mode.
Definition clock-arch.c:178
void clock_arch_standby_policy(void)
Called by the Power driver when dropping to some low-power state.
Definition clock-arch.c:184
uint32_t watchdog_arch_next_timeout(void)
Return the next expiration time for the Watchdog.
#define CLOCK_SECOND
A second, measured in system clock time.
Definition clock.h:103
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
unsigned long clock_seconds(void)
Get the current value of the platform seconds.
Definition clock-arch.c:98
void clock_init(void)
Initialize the clock library.
Definition clock-arch.c:77
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition clock-arch.c:114
void clock_wait(clock_time_t i)
Wait for a given number of ticks.
Definition clock-arch.c:104
clock_time_t clock_time(void)
Get the current clock time.
Definition clock-arch.c:92
void clock_delay(unsigned int i)
Obsolete delay function but we implement it here since some code still uses it.
Definition clock-arch.c:139
Header file of the CC13xx/CC26xx watchdog driver.