Contiki-NG
rtimer-arch-slow.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, SICS Swedish ICT.
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 Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * RTIMER for NXP jn516x: 32 kHz mode
36  * \author
37  * Atis Elsts <atis.elsts@sics.se>
38  */
39 
40 #include "sys/rtimer.h"
41 #include "sys/clock.h"
42 #include <AppHardwareApi.h>
43 #include <PeripheralRegs.h>
44 #include <MicroSpecific.h>
45 #include "dev/watchdog.h"
46 #include "sys/process.h"
47 
48 #if RTIMER_USE_32KHZ
49 
50 #define DEBUG 0
51 #if DEBUG
52 #include <stdio.h>
53 #define PRINTF(...) printf(__VA_ARGS__)
54 #else
55 #define PRINTF(...)
56 #endif
57 
58 #define RTIMER_TIMER_ISR_DEV E_AHI_DEVICE_SYSCTRL
59 /* 1.5 days wraparound time */
60 #define MAX_VALUE 0xFFFFFFFF
61 /* make this small to more easily detect wraparound bugs */
62 #define START_VALUE (60 * RTIMER_ARCH_SECOND)
63 #define WRAPAROUND_VALUE ((uint64_t)0x1FFFFFFFFFF)
64 
65 static volatile rtimer_clock_t scheduled_time;
66 static volatile uint8_t has_next;
67 
68 /*---------------------------------------------------------------------------*/
69 static void
70 timerISR(uint32 u32Device, uint32 u32ItemBitmap)
71 {
72  PRINTF("\ntimer isr %u %u\n", u32Device, u32ItemBitmap);
73  if(u32Device != RTIMER_TIMER_ISR_DEV) {
74  return;
75  }
76 
77  if(u32ItemBitmap & TICK_TIMER_MASK) {
78  /* 32-bit overflow happened; restart the timer */
79  uint32_t ticks_late = WRAPAROUND_VALUE - u64AHI_WakeTimerReadLarge(TICK_TIMER);
80 
81  PRINTF("\nrtimer oflw, missed ticks %u\n", ticks_late);
82 
83  vAHI_WakeTimerStartLarge(TICK_TIMER, MAX_VALUE - ticks_late);
84  }
85 
86  if(u32ItemBitmap & WAKEUP_TIMER_MASK) {
87  PRINTF("\nrtimer fire @ %u\n", rtimer_arch_now());
88 
89  /* Compare with the current time, as after sleep there is
90  * a fake interrupt generated 10ms earlier to wake up & reinitialize
91  * the system before the actual rtimer fires.
92  */
93  rtimer_clock_t now = rtimer_arch_now();
94  if(RTIMER_CLOCK_LT(now + 1, scheduled_time)) {
95  vAHI_WakeTimerEnable(WAKEUP_TIMER, TRUE);
96  vAHI_WakeTimerStartLarge(WAKEUP_TIMER, scheduled_time - now);
97  } else {
98  has_next = 0;
100  rtimer_run_next();
101  process_nevents();
102  }
103  }
104 }
105 /*---------------------------------------------------------------------------*/
106 void
107 rtimer_arch_init(void)
108 {
109  /* Initialise tick timer to run continuously */
110  vAHI_TickTimerIntEnable(0);
111  vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);
112  vAHI_TickTimerWrite(0);
113  vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_CONT);
114 
115  vAHI_SysCtrlRegisterCallback(timerISR);
116  /* set the highest priority for the rtimer interrupt */
117  vAHI_InterruptSetPriority(MICRO_ISR_MASK_SYSCTRL, 15);
118  /* enable interrupt on a rtimer */
119  vAHI_WakeTimerEnable(WAKEUP_TIMER, TRUE);
120  /* enable interrupt on 32-bit overflow */
121  vAHI_WakeTimerEnable(TICK_TIMER, TRUE);
122  /* count down from START_VALUE */
123  vAHI_WakeTimerStartLarge(TICK_TIMER, START_VALUE);
124 
125  (void)u32AHI_Init();
126 }
127 /*---------------------------------------------------------------------------*/
128 void
129 rtimer_arch_reinit(rtimer_clock_t sleep_start, rtimer_clock_t sleep_ticks)
130 {
131  uint64_t t;
132 
133  uint32_t wakeup_time = sleep_start + (uint64_t)sleep_ticks * (F_CPU / 2) / RTIMER_SECOND;
134 
135  /* Initialise tick timer to run continuously */
136  vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);
137  vAHI_TickTimerIntEnable(0);
138  WAIT_FOR_EDGE(t);
139  vAHI_TickTimerWrite(wakeup_time);
140  vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_CONT);
141 
142  /* call pending interrupts */
143  (void)u32AHI_Init();
144 
145  if(has_next) {
146  /* reschedule the timer */
147  rtimer_arch_schedule(scheduled_time);
148  }
149 }
150 /*---------------------------------------------------------------------------*/
151 rtimer_clock_t
152 rtimer_arch_now(void)
153 {
154  return START_VALUE - (rtimer_clock_t)u64AHI_WakeTimerReadLarge(TICK_TIMER);
155 }
156 /*---------------------------------------------------------------------------*/
157 void
158 rtimer_arch_schedule(rtimer_clock_t t)
159 {
160  PRINTF("rtimer_arch_schedule time %lu\n", t);
161  vAHI_WakeTimerEnable(WAKEUP_TIMER, TRUE);
162  vAHI_WakeTimerStartLarge(WAKEUP_TIMER, t - rtimer_arch_now());
163  scheduled_time = t;
164  has_next = 1;
165 }
166 /*---------------------------------------------------------------------------*/
167 rtimer_clock_t
168 rtimer_arch_time_to_rtimer(void)
169 {
170  rtimer_clock_t now = RTIMER_NOW();
171  if(has_next) {
172  return scheduled_time >= now ? scheduled_time - now : 0;
173  }
174  /* if no wakeup is scheduled yet return maximum time */
175  return (rtimer_clock_t)-1;
176 }
177 /*---------------------------------------------------------------------------*/
178 #endif /* RTIMER_USE_32KHZ */
#define rtimer_arch_now()
Definition: rtimer-arch.h:47
void rtimer_arch_schedule(rtimer_clock_t t)
Schedules an rtimer task to be triggered at time t.
Definition: rtimer-arch.c:71
#define RTIMER_SECOND
Number of rtimer ticks for 1 second.
Definition: rtimer.h:112
void rtimer_arch_init(void)
We don&#39;t need to explicitly initialise anything but this routine is required by the API...
Definition: rtimer-arch.c:59
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:185
void rtimer_run_next(void)
Execute the next real-time task and schedule the next task, if any.
Definition: rtimer.c:92
void watchdog_start(void)
Starts the WDT in watchdog mode if enabled by user configuration, maximum interval.
Definition: watchdog.c:72
Header file for the real-time timer module.
Header file for the Contiki process interface.
int process_nevents(void)
Number of events waiting to be processed.
Definition: process.c:316