Contiki-NG
clock.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, 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 /**
32  * \addtogroup cc26xx-clocks
33  * @{
34  *
35  * \defgroup cc26xx-software-clock Software Clock
36  *
37  * Implementation of the clock module for the CC26xx and CC13xx.
38  *
39  * The software clock uses the facilities provided by the AON RTC driver
40  * @{
41  *
42  * \file
43  * Software clock implementation for the TI CC13xx/CC26xx
44  */
45 /*---------------------------------------------------------------------------*/
46 #include "contiki.h"
47 
48 #include "ti-lib.h"
49 /*---------------------------------------------------------------------------*/
50 static volatile uint64_t count;
51 
52 /**< Num. fractions in sub-second. Important to cast to 64-bit */
53 #define RTC_SUBSEC_FRAC ((uint64_t)1 << 32)
54 /*---------------------------------------------------------------------------*/
55 static void
56 power_domain_on(void)
57 {
58  ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH);
59  while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) !=
60  PRCM_DOMAIN_POWER_ON);
61 }
62 /*---------------------------------------------------------------------------*/
63 void
65 {
66  count = 0;
67 
68  /*
69  * Here, we configure GPT0 Timer A, which we subsequently use in
70  * clock_delay_usec
71  *
72  * We need to access registers, so firstly power up the PD and then enable
73  * the clock to GPT0.
74  */
75  if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) !=
76  PRCM_DOMAIN_POWER_ON) {
77  power_domain_on();
78  }
79 
80  ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0);
81  ti_lib_prcm_load_set();
82  while(!ti_lib_prcm_load_get());
83 
84  /* Disable both GPT0 timers */
85  HWREG(GPT0_BASE + GPT_O_CTL) &= ~(GPT_CTL_TAEN | GPT_CTL_TBEN);
86 
87  /*
88  * We assume that the clock is running at 48MHz, we use GPT0 Timer A,
89  * one-shot, countdown, prescaled by 48 gives us 1 tick per usec
90  */
91  ti_lib_timer_configure(GPT0_BASE,
92  TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_ONE_SHOT);
93 
94  /* Global config: split pair (2 x 16-bit wide) */
95  HWREG(GPT0_BASE + GPT_O_CFG) = TIMER_CFG_SPLIT_PAIR >> 24;
96 
97  /*
98  * Pre-scale value 47 pre-scales by 48
99  *
100  * ToDo: The theoretical value here should be 47 (to provide x48 prescale)
101  * However, 49 seems to give results much closer to the desired delay
102  */
103  ti_lib_timer_prescale_set(GPT0_BASE, TIMER_B, 49);
104 
105  /* GPT0 / Timer B: One shot, PWM interrupt enable */
106  HWREG(GPT0_BASE + GPT_O_TBMR) =
107  ((TIMER_CFG_B_ONE_SHOT >> 8) & 0xFF) | GPT_TBMR_TBPWMIE;
108 
109  /* enable sync with radio timer */
110  HWREGBITW(AON_RTC_BASE + AON_RTC_O_CTL, AON_RTC_CTL_RTC_UPD_EN_BITN) = 1;
111 }
112 /*---------------------------------------------------------------------------*/
113 static void
114 update_clock_variable(void)
115 {
116  /*
117  * RTC counter is in a 64-bits format (SEC[31:0].SUBSEC[31:0]), where SUBSEC
118  * is represented in fractions of a second (VALUE/2^32).
119  */
120  uint64_t now = ti_lib_aon_rtc_current_64_bit_value_get();
121  count = (clock_time_t)(now / (RTC_SUBSEC_FRAC / CLOCK_SECOND));
122 }
123 /*---------------------------------------------------------------------------*/
124 clock_time_t
126 {
127  update_clock_variable();
128 
129  return (clock_time_t)(count & 0xFFFFFFFF);
130 }
131 /*---------------------------------------------------------------------------*/
132 void
133 clock_update(void)
134 {
135  update_clock_variable();
136 
137  if(etimer_pending()) {
139  }
140 }
141 /*---------------------------------------------------------------------------*/
142 unsigned long
144 {
145  return (unsigned long)ti_lib_aon_rtc_sec_get();
146 }
147 /*---------------------------------------------------------------------------*/
148 void
149 clock_wait(clock_time_t i)
150 {
151  clock_time_t start;
152 
153  start = clock_time();
154  while(clock_time() - start < (clock_time_t)i);
155 }
156 /*---------------------------------------------------------------------------*/
157 void
158 clock_delay_usec(uint16_t len)
159 {
160  uint32_t clock_status;
161 
162  if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) !=
163  PRCM_DOMAIN_POWER_ON) {
164  power_domain_on();
165  }
166 
167  clock_status = HWREG(PRCM_BASE + PRCM_O_GPTCLKGR) & PRCM_GPIOCLKGR_CLK_EN;
168 
169  ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0);
170  ti_lib_prcm_load_set();
171  while(!ti_lib_prcm_load_get());
172 
173  ti_lib_timer_load_set(GPT0_BASE, TIMER_B, len);
174  ti_lib_timer_enable(GPT0_BASE, TIMER_B);
175 
176  /*
177  * Wait for TBEN to clear. CC26xxware does not provide us with a convenient
178  * function, hence the direct register access here
179  */
180  while(HWREG(GPT0_BASE + GPT_O_CTL) & GPT_CTL_TBEN);
181 
182  if(clock_status == 0) {
183  ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_TIMER0);
184  ti_lib_prcm_load_set();
185  while(!ti_lib_prcm_load_get());
186  }
187 }
188 /*---------------------------------------------------------------------------*/
189 /**
190  * \brief Obsolete delay function but we implement it here since some code
191  * still uses it
192  */
193 void
194 clock_delay(unsigned int i)
195 {
196  clock_delay_usec(i);
197 }
198 /*---------------------------------------------------------------------------*/
199 /**
200  * @}
201  * @}
202  */
static volatile uint64_t count
Num.
Definition: clock.c:50
Header file with macros which rename TI CC26xxware functions.
void etimer_request_poll(void)
Make the event timer aware that the clock has changed.
Definition: etimer.c:145
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
unsigned long clock_seconds(void)
Get the current value of the platform seconds.
Definition: clock.c:130
static void start(void)
Start measurement.
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
int etimer_pending(void)
Check if there are any non-expired event timers.
Definition: etimer.c:231
void clock_delay(unsigned int i)
Obsolete delay function but we implement it here since some code still uses it.
Definition: clock.c:164
clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:118
void clock_init(void)
Arch-specific implementation of clock_init for the cc2538.
Definition: clock.c:93