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