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 static void
53 power_domain_on(void)
54 {
55  ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH);
56  while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) !=
57  PRCM_DOMAIN_POWER_ON);
58 }
59 /*---------------------------------------------------------------------------*/
60 void
62 {
63  count = 0;
64 
65  /*
66  * Here, we configure GPT0 Timer A, which we subsequently use in
67  * clock_delay_usec
68  *
69  * We need to access registers, so firstly power up the PD and then enable
70  * the clock to GPT0.
71  */
72  if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) !=
73  PRCM_DOMAIN_POWER_ON) {
74  power_domain_on();
75  }
76 
77  ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0);
78  ti_lib_prcm_load_set();
79  while(!ti_lib_prcm_load_get());
80 
81  /* Disable both GPT0 timers */
82  HWREG(GPT0_BASE + GPT_O_CTL) &= ~(GPT_CTL_TAEN | GPT_CTL_TBEN);
83 
84  /*
85  * We assume that the clock is running at 48MHz, we use GPT0 Timer A,
86  * one-shot, countdown, prescaled by 48 gives us 1 tick per usec
87  */
88  ti_lib_timer_configure(GPT0_BASE,
89  TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_ONE_SHOT);
90 
91  /* Global config: split pair (2 x 16-bit wide) */
92  HWREG(GPT0_BASE + GPT_O_CFG) = TIMER_CFG_SPLIT_PAIR >> 24;
93 
94  /*
95  * Pre-scale value 47 pre-scales by 48
96  *
97  * ToDo: The theoretical value here should be 47 (to provide x48 prescale)
98  * However, 49 seems to give results much closer to the desired delay
99  */
100  ti_lib_timer_prescale_set(GPT0_BASE, TIMER_B, 49);
101 
102  /* GPT0 / Timer B: One shot, PWM interrupt enable */
103  HWREG(GPT0_BASE + GPT_O_TBMR) =
104  ((TIMER_CFG_B_ONE_SHOT >> 8) & 0xFF) | GPT_TBMR_TBPWMIE;
105 
106  /* enable sync with radio timer */
107  HWREGBITW(AON_RTC_BASE + AON_RTC_O_CTL, AON_RTC_CTL_RTC_UPD_EN_BITN) = 1;
108 }
109 /*---------------------------------------------------------------------------*/
110 static void
111 update_clock_variable(void)
112 {
113  uint32_t aon_rtc_secs_now;
114  uint32_t aon_rtc_secs_now2;
115  uint16_t aon_rtc_ticks_now;
116 
117  do {
118  aon_rtc_secs_now = HWREG(AON_RTC_BASE + AON_RTC_O_SEC);
119  aon_rtc_ticks_now = HWREG(AON_RTC_BASE + AON_RTC_O_SUBSEC) >> 16;
120  aon_rtc_secs_now2 = HWREG(AON_RTC_BASE + AON_RTC_O_SEC);
121  } while(aon_rtc_secs_now != aon_rtc_secs_now2);
122 
123  /* Convert AON RTC ticks to clock tick counter */
124  count = (aon_rtc_secs_now * CLOCK_SECOND) + (aon_rtc_ticks_now >> 9);
125 }
126 /*---------------------------------------------------------------------------*/
127 clock_time_t
129 {
130  update_clock_variable();
131 
132  return (clock_time_t)(count & 0xFFFFFFFF);
133 }
134 /*---------------------------------------------------------------------------*/
135 void
136 clock_update(void)
137 {
138  update_clock_variable();
139 
140  if(etimer_pending()) {
142  }
143 }
144 /*---------------------------------------------------------------------------*/
145 unsigned long
147 {
148  bool interrupts_disabled;
149  uint32_t secs_now;
150 
151  interrupts_disabled = ti_lib_int_master_disable();
152 
153  secs_now = ti_lib_aon_rtc_sec_get();
154 
155  /* Re-enable interrupts */
156  if(!interrupts_disabled) {
157  ti_lib_int_master_enable();
158  }
159 
160  return (unsigned long)secs_now;
161 }
162 /*---------------------------------------------------------------------------*/
163 void
164 clock_wait(clock_time_t i)
165 {
166  clock_time_t start;
167 
168  start = clock_time();
169  while(clock_time() - start < (clock_time_t)i);
170 }
171 /*---------------------------------------------------------------------------*/
172 void
173 clock_delay_usec(uint16_t len)
174 {
175  uint32_t clock_status;
176 
177  if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) !=
178  PRCM_DOMAIN_POWER_ON) {
179  power_domain_on();
180  }
181 
182  clock_status = HWREG(PRCM_BASE + PRCM_O_GPTCLKGR) & PRCM_GPIOCLKGR_CLK_EN;
183 
184  ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0);
185  ti_lib_prcm_load_set();
186  while(!ti_lib_prcm_load_get());
187 
188  ti_lib_timer_load_set(GPT0_BASE, TIMER_B, len);
189  ti_lib_timer_enable(GPT0_BASE, TIMER_B);
190 
191  /*
192  * Wait for TBEN to clear. CC26xxware does not provide us with a convenient
193  * function, hence the direct register access here
194  */
195  while(HWREG(GPT0_BASE + GPT_O_CTL) & GPT_CTL_TBEN);
196 
197  if(clock_status == 0) {
198  ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_TIMER0);
199  ti_lib_prcm_load_set();
200  while(!ti_lib_prcm_load_get());
201  }
202 }
203 /*---------------------------------------------------------------------------*/
204 /**
205  * \brief Obsolete delay function but we implement it here since some code
206  * still uses it
207  */
208 void
209 clock_delay(unsigned int i)
210 {
211  clock_delay_usec(i);
212 }
213 /*---------------------------------------------------------------------------*/
214 /**
215  * @}
216  * @}
217  */
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