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