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