1 /*
2 * Copyright (c) 2014 - 2020, 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 * 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 * 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 * p_instance)99 void nrfx_rtc_uninit(nrfx_rtc_t 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 * p_instance)119 void nrfx_rtc_enable(nrfx_rtc_t 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 * p_instance)128 void nrfx_rtc_disable(nrfx_rtc_t 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 * p_instance,uint32_t channel)137 nrfx_err_t nrfx_rtc_cc_disable(nrfx_rtc_t 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_enable_check(p_instance->p_reg, int_mask))
148 {
149 nrf_rtc_int_disable(p_instance->p_reg, int_mask);
150 if (nrf_rtc_event_check(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.",
161 p_instance->instance_id,
162 (unsigned long)channel);
163 err_code = NRFX_SUCCESS;
164 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
165 return err_code;
166 }
167
nrfx_rtc_cc_set(nrfx_rtc_t const * p_instance,uint32_t channel,uint32_t val,bool enable_irq)168 nrfx_err_t nrfx_rtc_cc_set(nrfx_rtc_t const * p_instance,
169 uint32_t channel,
170 uint32_t val,
171 bool enable_irq)
172 {
173 NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
174 NRFX_ASSERT(channel < p_instance->cc_channel_count);
175
176 nrfx_err_t err_code;
177 uint32_t int_mask = RTC_CHANNEL_INT_MASK(channel);
178 nrf_rtc_event_t event = RTC_CHANNEL_EVENT_ADDR(channel);
179
180 nrf_rtc_event_disable(p_instance->p_reg, int_mask);
181 nrf_rtc_int_disable(p_instance->p_reg, int_mask);
182
183 val = RTC_WRAP(val);
184 if (m_cb[p_instance->instance_id].reliable)
185 {
186 nrf_rtc_cc_set(p_instance->p_reg,channel, val);
187 uint32_t cnt = nrf_rtc_counter_get(p_instance->p_reg);
188 int32_t diff = cnt - val;
189 if (cnt < val)
190 {
191 diff += RTC_COUNTER_COUNTER_Msk;
192 }
193 if (diff < m_cb[p_instance->instance_id].tick_latency)
194 {
195 err_code = NRFX_ERROR_TIMEOUT;
196 NRFX_LOG_WARNING("Function: %s, error code: %s.",
197 __func__,
198 NRFX_LOG_ERROR_STRING_GET(err_code));
199 return err_code;
200 }
201 }
202 else
203 {
204 nrf_rtc_cc_set(p_instance->p_reg,channel,val);
205 }
206
207 if (enable_irq)
208 {
209 nrf_rtc_event_clear(p_instance->p_reg, event);
210 nrf_rtc_int_enable(p_instance->p_reg, int_mask);
211 }
212 nrf_rtc_event_enable(p_instance->p_reg,int_mask);
213
214 NRFX_LOG_INFO("RTC id: %d, channel enabled: %lu, compare value: %lu.",
215 p_instance->instance_id,
216 (unsigned long)channel,
217 (unsigned long)val);
218 err_code = NRFX_SUCCESS;
219 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
220 return err_code;
221 }
222
nrfx_rtc_tick_enable(nrfx_rtc_t const * p_instance,bool enable_irq)223 void nrfx_rtc_tick_enable(nrfx_rtc_t const * p_instance, bool enable_irq)
224 {
225 nrf_rtc_event_t event = NRF_RTC_EVENT_TICK;
226 uint32_t mask = NRF_RTC_INT_TICK_MASK;
227
228 nrf_rtc_event_clear(p_instance->p_reg, event);
229 nrf_rtc_event_enable(p_instance->p_reg, mask);
230 if (enable_irq)
231 {
232 nrf_rtc_int_enable(p_instance->p_reg, mask);
233 }
234 NRFX_LOG_INFO("Tick events enabled.");
235 }
236
nrfx_rtc_tick_disable(nrfx_rtc_t const * p_instance)237 void nrfx_rtc_tick_disable(nrfx_rtc_t const * p_instance)
238 {
239 uint32_t mask = NRF_RTC_INT_TICK_MASK;
240
241 nrf_rtc_event_disable(p_instance->p_reg, mask);
242 nrf_rtc_int_disable(p_instance->p_reg, mask);
243 NRFX_LOG_INFO("Tick events disabled.");
244 }
245
nrfx_rtc_overflow_enable(nrfx_rtc_t const * p_instance,bool enable_irq)246 void nrfx_rtc_overflow_enable(nrfx_rtc_t const * p_instance, bool enable_irq)
247 {
248 nrf_rtc_event_t event = NRF_RTC_EVENT_OVERFLOW;
249 uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK;
250
251 nrf_rtc_event_clear(p_instance->p_reg, event);
252 nrf_rtc_event_enable(p_instance->p_reg, mask);
253 if (enable_irq)
254 {
255 nrf_rtc_int_enable(p_instance->p_reg, mask);
256 }
257 }
258
nrfx_rtc_overflow_disable(nrfx_rtc_t const * p_instance)259 void nrfx_rtc_overflow_disable(nrfx_rtc_t const * p_instance)
260 {
261 uint32_t mask = NRF_RTC_INT_OVERFLOW_MASK;
262 nrf_rtc_event_disable(p_instance->p_reg, mask);
263 nrf_rtc_int_disable(p_instance->p_reg, mask);
264 }
265
nrfx_rtc_max_ticks_get(nrfx_rtc_t const * p_instance)266 uint32_t nrfx_rtc_max_ticks_get(nrfx_rtc_t const * p_instance)
267 {
268 uint32_t ticks;
269 if (m_cb[p_instance->instance_id].reliable)
270 {
271 ticks = RTC_COUNTER_COUNTER_Msk - m_cb[p_instance->instance_id].tick_latency;
272 }
273 else
274 {
275 ticks = RTC_COUNTER_COUNTER_Msk;
276 }
277 return ticks;
278 }
279
irq_handler(NRF_RTC_Type * p_reg,uint32_t instance_id,uint32_t channel_count)280 static void irq_handler(NRF_RTC_Type * p_reg,
281 uint32_t instance_id,
282 uint32_t channel_count)
283 {
284 uint32_t i;
285 uint32_t int_mask = (uint32_t)NRF_RTC_INT_COMPARE0_MASK;
286 nrf_rtc_event_t event = NRF_RTC_EVENT_COMPARE_0;
287
288 for (i = 0; i < channel_count; i++)
289 {
290 if (nrf_rtc_int_enable_check(p_reg, int_mask) && nrf_rtc_event_check(p_reg, event))
291 {
292 nrf_rtc_event_disable(p_reg, int_mask);
293 nrf_rtc_int_disable(p_reg, int_mask);
294 nrf_rtc_event_clear(p_reg, event);
295 NRFX_LOG_DEBUG("Event: %s, instance id: %lu.",
296 EVT_TO_STR(event),
297 (unsigned long)instance_id);
298 m_handlers[instance_id]((nrfx_rtc_int_type_t)i);
299 }
300 int_mask <<= 1;
301 event = (nrf_rtc_event_t)((uint32_t)event + sizeof(uint32_t));
302 }
303
304 event = NRF_RTC_EVENT_TICK;
305 if (nrf_rtc_int_enable_check(p_reg, NRF_RTC_INT_TICK_MASK) && nrf_rtc_event_check(p_reg, event))
306 {
307 nrf_rtc_event_clear(p_reg, event);
308 NRFX_LOG_DEBUG("Event: %s, instance id: %lu.",
309 EVT_TO_STR(event),
310 (unsigned long)instance_id);
311 m_handlers[instance_id](NRFX_RTC_INT_TICK);
312 }
313
314 event = NRF_RTC_EVENT_OVERFLOW;
315 if (nrf_rtc_int_enable_check(p_reg, NRF_RTC_INT_OVERFLOW_MASK) &&
316 nrf_rtc_event_check(p_reg, event))
317 {
318 nrf_rtc_event_clear(p_reg, event);
319 NRFX_LOG_DEBUG("Event: %s, instance id: %lu.",
320 EVT_TO_STR(event),
321 (unsigned long)instance_id);
322 m_handlers[instance_id](NRFX_RTC_INT_OVERFLOW);
323 }
324 }
325
326 #if NRFX_CHECK(NRFX_RTC0_ENABLED)
nrfx_rtc_0_irq_handler(void)327 void nrfx_rtc_0_irq_handler(void)
328 {
329 irq_handler(NRF_RTC0, NRFX_RTC0_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(0));
330 }
331 #endif
332
333 #if NRFX_CHECK(NRFX_RTC1_ENABLED)
nrfx_rtc_1_irq_handler(void)334 void nrfx_rtc_1_irq_handler(void)
335 {
336 irq_handler(NRF_RTC1, NRFX_RTC1_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(1));
337 }
338 #endif
339
340 #if NRFX_CHECK(NRFX_RTC2_ENABLED)
nrfx_rtc_2_irq_handler(void)341 void nrfx_rtc_2_irq_handler(void)
342 {
343 irq_handler(NRF_RTC2, NRFX_RTC2_INST_IDX, NRF_RTC_CC_CHANNEL_COUNT(2));
344 }
345 #endif
346
347 #endif // NRFX_CHECK(NRFX_RTC_ENABLED)
348