1 /*
2 * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
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 are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <nrfx.h>
33
34 #if NRFX_CHECK(NRFX_RTC_ENABLED)
35
36 #if !(NRFX_CHECK(NRFX_RTC0_ENABLED) || NRFX_CHECK(NRFX_RTC1_ENABLED) || \
37 NRFX_CHECK(NRFX_RTC2_ENABLED))
38 #error "No enabled RTC instances. Check <nrfx_config.h>."
39 #endif
40
41 #include <nrfx_rtc.h>
42
43 #define NRFX_LOG_MODULE RTC
44 #include <nrfx_log.h>
45
46 #define EVT_TO_STR(event) \
47 (event == NRF_RTC_EVENT_TICK ? "NRF_RTC_EVENT_TICK" : \
48 (event == NRF_RTC_EVENT_OVERFLOW ? "NRF_RTC_EVENT_OVERFLOW" : \
49 (event == NRF_RTC_EVENT_COMPARE_0 ? "NRF_RTC_EVENT_COMPARE_0" : \
50 (event == NRF_RTC_EVENT_COMPARE_1 ? "NRF_RTC_EVENT_COMPARE_1" : \
51 (event == NRF_RTC_EVENT_COMPARE_2 ? "NRF_RTC_EVENT_COMPARE_2" : \
52 (event == NRF_RTC_EVENT_COMPARE_3 ? "NRF_RTC_EVENT_COMPARE_3" : \
53 "UNKNOWN EVENT"))))))
54
55
56 /**@brief RTC driver instance control block structure. */
57 typedef struct
58 {
59 nrfx_drv_state_t state; /**< Instance state. */
60 bool reliable; /**< Reliable mode flag. */
61 uint8_t tick_latency; /**< Maximum length of interrupt handler in ticks (max 7.7 ms). */
62 } nrfx_rtc_cb_t;
63
64 // User callbacks local storage.
65 static nrfx_rtc_handler_t m_handlers[NRFX_RTC_ENABLED_COUNT];
66 static nrfx_rtc_cb_t m_cb[NRFX_RTC_ENABLED_COUNT];
67
nrfx_rtc_init(nrfx_rtc_t const * const p_instance,nrfx_rtc_config_t const * p_config,nrfx_rtc_handler_t handler)68 nrfx_err_t nrfx_rtc_init(nrfx_rtc_t const * const p_instance,
69 nrfx_rtc_config_t const * p_config,
70 nrfx_rtc_handler_t handler)
71 {
72 NRFX_ASSERT(p_config);
73 NRFX_ASSERT(handler);
74 nrfx_err_t err_code;
75
76 m_handlers[p_instance->instance_id] = handler;
77
78 if (m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED)
79 {
80 err_code = NRFX_ERROR_INVALID_STATE;
81 NRFX_LOG_WARNING("Function: %s, error code: %s.",
82 __func__,
83 NRFX_LOG_ERROR_STRING_GET(err_code));
84 return err_code;
85 }
86
87 NRFX_IRQ_PRIORITY_SET(p_instance->irq, p_config->interrupt_priority);
88 NRFX_IRQ_ENABLE(p_instance->irq);
89 nrf_rtc_prescaler_set(p_instance->p_reg, p_config->prescaler);
90 m_cb[p_instance->instance_id].reliable = p_config->reliable;
91 m_cb[p_instance->instance_id].tick_latency = p_config->tick_latency;
92 m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_INITIALIZED;
93
94 err_code = NRFX_SUCCESS;
95 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
96 return err_code;
97 }
98
nrfx_rtc_uninit(nrfx_rtc_t const * const p_instance)99 void nrfx_rtc_uninit(nrfx_rtc_t const * const p_instance)
100 {
101 uint32_t mask = NRF_RTC_INT_TICK_MASK |
102 NRF_RTC_INT_OVERFLOW_MASK |
103 NRF_RTC_INT_COMPARE0_MASK |
104 NRF_RTC_INT_COMPARE1_MASK |
105 NRF_RTC_INT_COMPARE2_MASK |
106 NRF_RTC_INT_COMPARE3_MASK;
107 NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
108
109 NRFX_IRQ_DISABLE(p_instance->irq);
110
111 nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_STOP);
112 nrf_rtc_event_disable(p_instance->p_reg, mask);
113 nrf_rtc_int_disable(p_instance->p_reg, mask);
114
115 m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_UNINITIALIZED;
116 NRFX_LOG_INFO("Uninitialized.");
117 }
118
nrfx_rtc_enable(nrfx_rtc_t const * const p_instance)119 void nrfx_rtc_enable(nrfx_rtc_t const * const p_instance)
120 {
121 NRFX_ASSERT(m_cb[p_instance->instance_id].state == NRFX_DRV_STATE_INITIALIZED);
122
123 nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_START);
124 m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_POWERED_ON;
125 NRFX_LOG_INFO("Enabled.");
126 }
127
nrfx_rtc_disable(nrfx_rtc_t const * const p_instance)128 void nrfx_rtc_disable(nrfx_rtc_t const * const p_instance)
129 {
130 NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
131
132 nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_STOP);
133 m_cb[p_instance->instance_id].state = NRFX_DRV_STATE_INITIALIZED;
134 NRFX_LOG_INFO("Disabled.");
135 }
136
nrfx_rtc_cc_disable(nrfx_rtc_t const * const p_instance,uint32_t channel)137 nrfx_err_t nrfx_rtc_cc_disable(nrfx_rtc_t const * const p_instance, uint32_t channel)
138 {
139 NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
140 NRFX_ASSERT(channel<p_instance->cc_channel_count);
141
142 nrfx_err_t err_code;
143 uint32_t int_mask = RTC_CHANNEL_INT_MASK(channel);
144 nrf_rtc_event_t event = RTC_CHANNEL_EVENT_ADDR(channel);
145
146 nrf_rtc_event_disable(p_instance->p_reg,int_mask);
147 if (nrf_rtc_int_is_enabled(p_instance->p_reg,int_mask))
148 {
149 nrf_rtc_int_disable(p_instance->p_reg,int_mask);
150 if (nrf_rtc_event_pending(p_instance->p_reg,event))
151 {
152 nrf_rtc_event_clear(p_instance->p_reg,event);
153 err_code = NRFX_ERROR_TIMEOUT;
154 NRFX_LOG_WARNING("Function: %s, error code: %s.",
155 __func__,
156 NRFX_LOG_ERROR_STRING_GET(err_code));
157 return err_code;
158 }
159 }
160 NRFX_LOG_INFO("RTC id: %d, channel disabled: %lu.", p_instance->instance_id, channel);
161 err_code = NRFX_SUCCESS;
162 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
163 return err_code;
164 }
165
nrfx_rtc_cc_set(nrfx_rtc_t const * const p_instance,uint32_t channel,uint32_t val,bool enable_irq)166 nrfx_err_t nrfx_rtc_cc_set(nrfx_rtc_t const * const p_instance,
167 uint32_t channel,
168 uint32_t val,
169 bool enable_irq)
170 {
171 NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
172 NRFX_ASSERT(channel<p_instance->cc_channel_count);
173
174 nrfx_err_t err_code;
175 uint32_t int_mask = RTC_CHANNEL_INT_MASK(channel);
176 nrf_rtc_event_t event = RTC_CHANNEL_EVENT_ADDR(channel);
177
178 nrf_rtc_event_disable(p_instance->p_reg, int_mask);
179 nrf_rtc_int_disable(p_instance->p_reg, int_mask);
180
181 val = RTC_WRAP(val);
182 if (m_cb[p_instance->instance_id].reliable)
183 {
184 nrf_rtc_cc_set(p_instance->p_reg,channel,val);
185 uint32_t cnt = nrf_rtc_counter_get(p_instance->p_reg);
186 int32_t diff = cnt - val;
187 if (cnt < val)
188 {
189 diff += RTC_COUNTER_COUNTER_Msk;
190 }
191 if (diff < m_cb[p_instance->instance_id].tick_latency)
192 {
193 err_code = NRFX_ERROR_TIMEOUT;
194 NRFX_LOG_WARNING("Function: %s, error code: %s.",
195 __func__,
196 NRFX_LOG_ERROR_STRING_GET(err_code));
197 return err_code;
198 }
199 }
200 else
201 {
202 nrf_rtc_cc_set(p_instance->p_reg,channel,val);
203 }
204
205 if (enable_irq)
206 {
207 nrf_rtc_event_clear(p_instance->p_reg,event);
208 nrf_rtc_int_enable(p_instance->p_reg, int_mask);
209 }
210 nrf_rtc_event_enable(p_instance->p_reg,int_mask);
211
212 NRFX_LOG_INFO("RTC id: %d, channel enabled: %lu, compare value: %lu.",
213 p_instance->instance_id,
214 channel,
215 val);
216 err_code = NRFX_SUCCESS;
217 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
218 return err_code;
219 }
220
nrfx_rtc_tick_enable(nrfx_rtc_t const * const p_instance,bool enable_irq)221 void nrfx_rtc_tick_enable(nrfx_rtc_t const * const p_instance, bool enable_irq)
222 {
223 nrf_rtc_event_t event = NRF_RTC_EVENT_TICK;
224 uint32_t mask = NRF_RTC_INT_TICK_MASK;
225
226 nrf_rtc_event_clear(p_instance->p_reg, event);
227 nrf_rtc_event_enable(p_instance->p_reg, mask);
228 if (enable_irq)
229 {
230 nrf_rtc_int_enable(p_instance->p_reg, mask);
231 }
232 NRFX_LOG_INFO("Tick events enabled.");
233 }
234
nrfx_rtc_tick_disable(nrfx_rtc_t const * const p_instance)235 void nrfx_rtc_tick_disable(nrfx_rtc_t const * const p_instance)
236 {
237 uint32_t mask = NRF_RTC_INT_TICK_MASK;
238
239 nrf_rtc_event_disable(p_instance->p_reg, mask);
240 nrf_rtc_int_disable(p_instance->p_reg, mask);
241 NRFX_LOG_INFO("Tick events disabled.");
242 }
243
nrfx_rtc_overflow_enable(nrfx_rtc_t const * const p_instance,bool enable_irq)244 void nrfx_rtc_overflow_enable(nrfx_rtc_t const * const p_instance, bool enable_irq)
245 {
246 nrf_rtc_event_t event = NRF_RTC_EVENT_OVERFLOW;
247 uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK;
248
249 nrf_rtc_event_clear(p_instance->p_reg, event);
250 nrf_rtc_event_enable(p_instance->p_reg, mask);
251 if (enable_irq)
252 {
253 nrf_rtc_int_enable(p_instance->p_reg, mask);
254 }
255 }
256
nrfx_rtc_overflow_disable(nrfx_rtc_t const * const p_instance)257 void nrfx_rtc_overflow_disable(nrfx_rtc_t const * const p_instance)
258 {
259 uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK;
260 nrf_rtc_event_disable(p_instance->p_reg, mask);
261 nrf_rtc_int_disable(p_instance->p_reg, mask);
262 }
263
nrfx_rtc_max_ticks_get(nrfx_rtc_t const * const p_instance)264 uint32_t nrfx_rtc_max_ticks_get(nrfx_rtc_t const * const p_instance)
265 {
266 uint32_t ticks;
267 if (m_cb[p_instance->instance_id].reliable)
268 {
269 ticks = RTC_COUNTER_COUNTER_Msk - m_cb[p_instance->instance_id].tick_latency;
270 }
271 else
272 {
273 ticks = RTC_COUNTER_COUNTER_Msk;
274 }
275 return ticks;
276 }
277
irq_handler(NRF_RTC_Type * p_reg,uint32_t instance_id,uint32_t channel_count)278 static void irq_handler(NRF_RTC_Type * p_reg,
279 uint32_t instance_id,
280 uint32_t channel_count)
281 {
282 uint32_t i;
283 uint32_t int_mask = (uint32_t)NRF_RTC_INT_COMPARE0_MASK;
284 nrf_rtc_event_t event = NRF_RTC_EVENT_COMPARE_0;
285
286 for (i = 0; i < channel_count; i++)
287 {
288 if (nrf_rtc_int_is_enabled(p_reg,int_mask) && nrf_rtc_event_pending(p_reg,event))
289 {
290 nrf_rtc_event_disable(p_reg,int_mask);
291 nrf_rtc_int_disable(p_reg,int_mask);
292 nrf_rtc_event_clear(p_reg,event);
293 NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
294 m_handlers[instance_id]((nrfx_rtc_int_type_t)i);
295 }
296 int_mask <<= 1;
297 event = (nrf_rtc_event_t)((uint32_t)event + sizeof(uint32_t));
298 }
299 event = NRF_RTC_EVENT_TICK;
300 if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_TICK_MASK) &&
301 nrf_rtc_event_pending(p_reg, event))
302 {
303 nrf_rtc_event_clear(p_reg, event);
304 NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
305 m_handlers[instance_id](NRFX_RTC_INT_TICK);
306 }
307
308 event = NRF_RTC_EVENT_OVERFLOW;
309 if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_OVERFLOW_MASK) &&
310 nrf_rtc_event_pending(p_reg, event))
311 {
312 nrf_rtc_event_clear(p_reg,event);
313 NRFX_LOG_DEBUG("Event: %s, instance id: %lu.", EVT_TO_STR(event), instance_id);
314 m_handlers[instance_id](NRFX_RTC_INT_OVERFLOW);
315 }
316 }
317
318 #if NRFX_CHECK(NRFX_RTC0_ENABLED)
nrfx_rtc_0_irq_handler(void)319 void nrfx_rtc_0_irq_handler(void)
320 {
321 irq_handler(NRF_RTC0, NRFX_RTC0_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(0));
322 }
323 #endif
324
325 #if NRFX_CHECK(NRFX_RTC1_ENABLED)
nrfx_rtc_1_irq_handler(void)326 void nrfx_rtc_1_irq_handler(void)
327 {
328 irq_handler(NRF_RTC1, NRFX_RTC1_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(1));
329 }
330 #endif
331
332 #if NRFX_CHECK(NRFX_RTC2_ENABLED)
nrfx_rtc_2_irq_handler(void)333 void nrfx_rtc_2_irq_handler(void)
334 {
335 irq_handler(NRF_RTC2, NRFX_RTC2_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(2));
336 }
337 #endif
338
339 #endif // NRFX_CHECK(NRFX_RTC_ENABLED)
340