Contiki 3.x
clock.c
1 #include <contiki.h>
2 #include <sys/clock.h>
3 #include <sys/cc.h>
4 #include <sys/etimer.h>
5 #include <sys/rtimer.h>
6 #include <sys/energest.h>
7 #include "derivative.h"
8 
9 #include "cpu.h"
10 #include "nvic.h"
11 #include "debug-uart.h"
12 
13 #include "contiki-conf.h"
14 
15 #ifdef SYSTICK_DEBUG
16 #include "gpio.h"
17 #endif
18 
19 /* Sanity check reload value for SysTick counter */
20 #if DEFAULT_SYSTEM_CLOCK % CLOCK_SECOND
21  /* Clock speed and CLOCK_SECOND gives a remainder, bad choices */
22  #error SYSCLOCK/CLOCK_SECOND gives a remainder: Accuracy of Systick is reduced.
23 #endif
24 
25 #if (CLOCK_SETUP == 0)
26  /* MCGIRCLK = 32kHz, OSCERCLK = NA. */
27  #define CLOCK_TPM0_PRESCALE 0x00U
28  #define CLOCK_LPTMR_SOURCE 0x00U
29  #define CLOCK_LPTMR_PRESCALE 0x00U
30 
31  #warning CLOCK_SETUP = 0 reduces timing accuracy!
32 
33 #elif (CLOCK_SETUP == 1)
34  /* MCGIRCLK = 32kHz, OSCERCLK = 8MHz. */
35  #define CLOCK_TPM0_PRESCALE 0x00U
36  #define CLOCK_LPTMR_SOURCE 0x03U
37  #define CLOCK_LPTMR_PRESCALE 0x02U
38 
39 #elif (CLOCK_SETUP == 2)
40  /* MCGIRCLK = 4MHz. OSCERCLK = NA. */
41  #define CLOCK_TPM0_PRESCALE 0x07U
42  #define CLOCK_LPTMR_SOURCE 0x00U
43  #define CLOCK_LPTMR_PRESCALE 0x01U
44 
45  #warning CLOCK_SETUP = 2 reduces timing accuracy!
46 
47 #elif (CLOCK_SETUP == 3)
48  /* MCGIRCLK = 32kHz. OSCERCLK = 4MHz. */
49  #define CLOCK_TPM0_PRESCALE 0x00U
50  #define CLOCK_LPTMR_SOURCE 0x03U
51  #define CLOCK_LPTMR_PRESCALE 0x01U
52 
53 #elif (CLOCK_SETUP == 4)
54  /* MCGIRCLK = 32kHz, OSCERCLK = 8MHz. */
55  #define CLOCK_TPM0_PRESCALE 0x00U
56  #define CLOCK_LPTMR_SOURCE 0x03U
57  #define CLOCK_LPTMR_PRESCALE 0x02U
58 
59 #else
60  #error Unsupported CLOCK_SETUP, cannot accurately set counter parameters.
61 #endif
62 
63 #define RTIMER_CLOCK_TICK_RATIO (RTIMER_SECOND / CLOCK_SECOND)
64 
65 
66 static volatile uint64_t rt_ticks_startup, rt_ticks_epoch;
67 
68 void
70 {
71  /* Need to configure a timer to use for the counter value. */
72 
73  /* Make sure MCGIRCLK is enabled & set to run in STOP. */
74  MCG_C1 |= MCG_C1_IRCLKEN_MASK | MCG_C1_IREFSTEN_MASK;
75 
76  /* Configure TPM0 Clocking. */
77  SIM_SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK); /* Clear TPM Clock source. */
78  SIM_SOPT2 |= SIM_SOPT2_TPMSRC(0x03); /* Set the TPM clock to MCGIRCLK */
79  SIM_SCGC6 |= SIM_SCGC6_TPM0_MASK; /* Enable clock to TPM. */
80 
81  /* Configure TPM0. */
82  TPM0_CNT = TPM_CNT_COUNT(0x00); /* Reset counter register */
83  TPM0_MOD = 0xFFFF; /* Set up modulo register use all 16-bits */
84  TPM0_SC = TPM_SC_TOF_MASK | TPM_SC_PS(CLOCK_TPM0_PRESCALE); /* Clear TOF & set Prescale. */
85  TPM0_CONF = 0x00U; /* Clear CONF so that TPM works in WAIT */
86 
87  /* Configure Channel 0 for RTIMER interrupts. */
88  TPM0_C0SC = TPM_CnSC_MSA_MASK; /* Config Channel 0 for software compare. */
89  TPM0_C0V = TPM_CnV_VAL(0x00); /* Set up channel value register */
90 
91  /* Clear other channel status and control register */
92  TPM0_C1SC = 0x00U;
93  TPM0_C2SC = 0x00U;
94  TPM0_C3SC = 0x00U;
95  TPM0_C4SC = 0x00U;
96  TPM0_C5SC = 0x00U;
97 
98  /* Configure TPM0 interrupt in NVIC. */
99  NVIC_SetPriority(TPM0_IRQn, 0x80); /* Set priority of TPM0 interrupt. */
100 
101  rt_ticks_startup = 0;
102  rt_ticks_epoch = 0;
103 
104  TPM0_SC = TPM_SC_CMOD(0x01); /* Enable the counter. */
105 
106 
107  /* We also need a timer for clock_delay_usec. Use LPTMR for this:
108  * Configured to tick every microsecond, or as close as we can get.
109  * TPM1 would be easier BUT all TPMs must have same clock source. */
110  SIM_SCGC5 |= SIM_SCGC5_LPTMR_MASK; /* Enable clock to LPTMR. */
111  LPTMR0_CSR = LPTMR_CSR_TCF_MASK; /* Clear LPTMR0 TCF flag & disable LPTMR. */
112 
113 #if (CLOCK_SETUP == 0)
114  LPTMR0_PSR = LPTMR_PSR_PCS(CLOCK_LPTMR_SOURCE) /* Configure LPTMR prescale and clock source. */
115  | LPTMR_PSR_PRESCALE(CLOCK_LPTMR_PRESCALE)
116  | LPTMR_PSR_PBYP_MASK; /* With prescaler bypass. */
117 #else
118  LPTMR0_PSR = LPTMR_PSR_PCS(CLOCK_LPTMR_SOURCE) /* Configure LPTMR prescale and clock source. */
119  | LPTMR_PSR_PRESCALE(CLOCK_LPTMR_PRESCALE);
120 #endif
121 
122 
123  /* Configure the Systick to fire CLOCK_SECOND number of times each second.
124  * This is configured with the CLOCK_CONF_SECOND define in contiki-conf.h
125  * and has a default value of 32 in Contiki but a platform default of 128.
126  */
127  if(SysTick_Config(DEFAULT_SYSTEM_CLOCK/CLOCK_SECOND))
128  {
129  printf("ERROR: Invalid Systick Setting in clock.c\n\r");
130  }
131 #ifdef SYSTICK_DEBUG
132  gpio_set_output(SYSTICK_DEBUG_GPIO, port_pin_to_mask(SYSTICK_DEBUG_PIN));
133  port_conf_pin(SYSTICK_DEBUG_PORT, SYSTICK_DEBUG_PIN, (PORT_PCR_MUX_GPIO | PORT_PCR_ISF_MASK));
134  gpio_clr_pin(SYSTICK_DEBUG_GPIO, port_pin_to_mask(SYSTICK_DEBUG_PIN));
135 #endif
136 }
137 
138 
139 /*---------------------------------------------------------------------------*/
140 clock_time_t
142 {
143  return rt_ticks_startup / RTIMER_CLOCK_TICK_RATIO;
144 }
145 /*---------------------------------------------------------------------------*/
146 void
147 clock_set_seconds(unsigned long sec)
148 {
149  rt_ticks_epoch = (uint64_t)sec * RTIMER_SECOND;
150 }
151 /*---------------------------------------------------------------------------*/
152 unsigned long
154 {
155  return rt_ticks_epoch / RTIMER_SECOND;
156 }
157 /*---------------------------------------------------------------------------*/
158 
159 
160 
161 void
162 clock_wait(clock_time_t i)
163 {
164  clock_time_t start;
165 
166  start = clock_time();
167  while(clock_time() - start < (clock_time_t)i);
168 }
169 
170 /* Arch-specific clock delay. Uses XXX for accuracy. */
171 void
172 clock_delay_usec(uint16_t dt)
173 {
174  LPTMR0_CSR = LPTMR_CSR_TCF_MASK; /* Clear LPTMR0 TCF flag & disable LPTMR. */
175 
176 #if (CLOCK_SETUP == 0)
177  /* Set CMR to be as close as possible but we only have a 30.5uS resolution. */
178  if (dt % 31 == 0) {
179  LPTMR0_CMR = dt / 31;
180  } else {
181  LPTMR0_CMR = (dt / 31) + 1;
182  }
183 #else
184  LPTMR0_CMR = dt; /* Set Compare to number of ms. */
185 #endif
186 
187  LPTMR0_CSR = LPTMR_CSR_TEN_MASK; /* Enable the counter. */
188 
189  while(!(LPTMR0_CSR & LPTMR_CSR_TCF_MASK)); /* Block until the compare flag is set. */
190  LPTMR0_CSR = LPTMR_CSR_TCF_MASK; /* Clear LPTMR0 TCF flag & disable LPTMR. */
191 }
192 
193 void
194 clock_delay(unsigned int i)
195 {
196  clock_delay_usec(i);
197 }
198 
199 
200 /*---------------------------------------------------------------------------*/
201 
202 void update_ticks(void)
203 {
204  rtimer_clock_t now;
205  uint64_t prev_rt_ticks_startup, cur_rt_ticks_startup_hi;
206 
207  now = RTIMER_NOW(); /* Get the current TPM0 count. */
208  prev_rt_ticks_startup = rt_ticks_startup;
209  cur_rt_ticks_startup_hi = prev_rt_ticks_startup >> 16;
210 
211  while(TPM0_SC & TPM_SC_TOF_MASK) { /* Check to see if the counter has overflowed. */
212  TPM0_SC |= TPM_SC_TOF_MASK; /* If TPM0_SC TOF bit is still set after a write, */
213  cur_rt_ticks_startup_hi++; /* it means that there has been a second overflow. */
214  }
215 
216  rt_ticks_startup = (cur_rt_ticks_startup_hi << 16) | now;
217 
218  rt_ticks_epoch += rt_ticks_startup - prev_rt_ticks_startup;
219 
220  /*
221  * Inform the etimer library that the system clock has changed and that an
222  * etimer might have expired.
223  */
224  if(etimer_pending()) {
226  }
227 }
228 
229 
230 /* Systick Interrupt Handler. */
231 void SysTick_Handler()
232 {
233  ENERGEST_ON(ENERGEST_TYPE_IRQ);
234  (void)SysTick->CTRL; /* Dummy read CSR register to clear Count flag. SysTick->CTRL in CMSIS */
235  SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk; /* Clear pending interrupt in SCB. */
236 
237  update_ticks();
238  //printf("ST\n");
239 
240 #if (DISABLE_WDOG == 0)
241  if(CPU_Watchdog_Disabled()) {
242  SIM_SRVCOP = 0x55;
243  SIM_SRVCOP = 0xAA;
244  }
245 #endif
246 
247 #ifdef SYSTICK_DEBUG
248  //gpio_tgl_pin(SYSTICK_DEBUG_GPIO, port_pin_to_mask(SYSTICK_DEBUG_PIN));
249 #endif
250 
251  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
252 }
Header file for the real-time timer module.
static void start(void)
Start measurement.
TPM0 single interrupt vector for all sources.
Definition: MKL25Z4.h:161
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:135
void etimer_request_poll(void)
Make the event timer aware that the clock has changed.
Definition: etimer.c:145
int etimer_pending(void)
Check if there are any non-expired event timers.
Definition: etimer.c:231
clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:41
Default definitions of C compiler quirk work-arounds.
void gpio_set_output(GPIO_Type *Port, uint32_t Pin_Mask)
Set pins with Pin_Mask of port with GPIOn_BASE_PTR to output.
Definition: gpio.c:135
Header file for the energy estimation mechanism
void clock_init()
Initialize the clock library.
Definition: clock.c:76
#define SysTick
Definition: core_cm0.h:495
#define SCB
Definition: core_cm0.h:494
static void update_ticks(void)
Update the software clock ticks and seconds.
Definition: clock.c:193
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
Set Interrupt Priority.
Definition: core_cm0.h:602
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
void gpio_clr_pin(GPIO_Type *Port, uint32_t Pin_Mask)
Clear pins with Pin_Mask of port with GPIOn_BASE_PTR low.
Definition: gpio.c:147
void port_conf_pin(PORT_Type *Port, uint8_t Pin, uint32_t PCR)
Configure the specified Pin of the port with PORTx_BASE_PTR with PCR.
Definition: gpio.c:40
void clock_delay(unsigned int i)
Obsolete delay function but we implement it here since some code still uses it.
Definition: clock.c:170
Event timer header file.
void clock_wait(clock_time_t i)
Wait for a given number of ticks.
Definition: clock.c:162
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
System Tick Configuration.
Definition: core_cm0.h:676
unsigned long clock_seconds(void)
Get the current value of the platform seconds.
Definition: clock.c:54
Header file for the MKL25Z NVIC functions.
void clock_delay_usec(uint16_t usec)
Delay a given number of microseconds.
Definition: clock.c:94
#define SCB_ICSR_PENDSTCLR_Msk
Definition: core_cm0.h:368
uint32_t port_pin_to_mask(uint8_t pin)
Convert a pin number (0 to 31) to a pin mask.
Definition: gpio.c:46
void clock_set_seconds(unsigned long sec)
Set the value of the platform seconds.
Definition: clock.c:147