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 #ifndef NRFX_RTC_H__
33 #define NRFX_RTC_H__
34 
35 #include <nrfx.h>
36 #include <hal/nrf_rtc.h>
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 /**
43  * @defgroup nrfx_rtc RTC driver
44  * @{
45  * @ingroup nrf_rtc
46  * @brief   Real Timer Counter (RTC) peripheral driver.
47  */
48 
49 /** @brief Macro for converting microseconds into ticks. */
50 #define NRFX_RTC_US_TO_TICKS(us,freq) (((us) * (freq)) / 1000000U)
51 
52 /** @brief RTC driver interrupt types. */
53 typedef enum
54 {
55     NRFX_RTC_INT_COMPARE0 = 0, /**< Interrupt from COMPARE0 event. */
56     NRFX_RTC_INT_COMPARE1 = 1, /**< Interrupt from COMPARE1 event. */
57     NRFX_RTC_INT_COMPARE2 = 2, /**< Interrupt from COMPARE2 event. */
58     NRFX_RTC_INT_COMPARE3 = 3, /**< Interrupt from COMPARE3 event. */
59     NRFX_RTC_INT_TICK     = 4, /**< Interrupt from TICK event. */
60     NRFX_RTC_INT_OVERFLOW = 5  /**< Interrupt from OVERFLOW event. */
61 } nrfx_rtc_int_type_t;
62 
63 /** @brief RTC driver instance structure. */
64 typedef struct
65 {
66     NRF_RTC_Type  * p_reg;            /**< Pointer to instance register set. */
67     IRQn_Type       irq;              /**< Instance IRQ ID. */
68     uint8_t         instance_id;      /**< Index of the driver instance. For internal use only. */
69     uint8_t         cc_channel_count; /**< Number of capture/compare channels. */
70 } nrfx_rtc_t;
71 
72 /** @brief Macro for creating an RTC driver instance. */
73 #define NRFX_RTC_INSTANCE(id)                                   \
74 {                                                               \
75     .p_reg            = NRFX_CONCAT_2(NRF_RTC, id),             \
76     .irq              = NRFX_CONCAT_3(RTC, id, _IRQn),          \
77     .instance_id      = NRFX_CONCAT_3(NRFX_RTC, id, _INST_IDX), \
78     .cc_channel_count = NRF_RTC_CC_CHANNEL_COUNT(id),           \
79 }
80 
81 #ifndef __NRFX_DOXYGEN__
82 enum {
83 #if NRFX_CHECK(NRFX_RTC0_ENABLED)
84     NRFX_RTC0_INST_IDX,
85 #endif
86 #if NRFX_CHECK(NRFX_RTC1_ENABLED)
87     NRFX_RTC1_INST_IDX,
88 #endif
89 #if NRFX_CHECK(NRFX_RTC2_ENABLED)
90     NRFX_RTC2_INST_IDX,
91 #endif
92     NRFX_RTC_ENABLED_COUNT
93 };
94 #endif
95 
96 /** @brief RTC driver instance configuration structure. */
97 typedef struct
98 {
99     uint16_t prescaler;          /**< Prescaler. */
100     uint8_t  interrupt_priority; /**< Interrupt priority. */
101     uint8_t  tick_latency;       /**< Maximum length of the interrupt handler in ticks (maximum 7.7 ms). */
102     bool     reliable;           /**< Reliable mode flag. */
103 } nrfx_rtc_config_t;
104 
105 /**
106  * @brief RTC driver default configuration.
107  *
108  * This configuration sets up RTC with the following options:
109  * - frequency 32.768 kHz
110  * - maximum latency 2000 us
111  * - reliability checks disabled
112  */
113 #define NRFX_RTC_DEFAULT_CONFIG                                  \
114 {                                                                \
115     .prescaler          = RTC_FREQ_TO_PRESCALER(32768),          \
116     .interrupt_priority = NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY,  \
117     .tick_latency       = NRFX_RTC_US_TO_TICKS(2000, 32768),     \
118     .reliable           = false,                                 \
119 }
120 
121 /** @brief RTC driver instance handler type. */
122 typedef void (*nrfx_rtc_handler_t)(nrfx_rtc_int_type_t int_type);
123 
124 /**
125  * @brief Function for initializing the RTC driver instance.
126  *
127  * After initialization, the instance is in power off state.
128  *
129  * @param[in] p_instance Pointer to the driver instance structure.
130  * @param[in] p_config   Pointer to the structure with the initial configuration.
131  * @param[in] handler    Event handler provided by the user.
132  *                       Must not be NULL.
133  *
134  * @retval NRFX_SUCCESS             Successfully initialized.
135  * @retval NRFX_ERROR_INVALID_STATE The instance is already initialized.
136  */
137 nrfx_err_t nrfx_rtc_init(nrfx_rtc_t const *        p_instance,
138                          nrfx_rtc_config_t const * p_config,
139                          nrfx_rtc_handler_t        handler);
140 
141 /**
142  * @brief Function for uninitializing the RTC driver instance.
143  *
144  * After uninitialization, the instance is in idle state. The hardware should return to the state
145  * before initialization.
146  *
147  * @param[in] p_instance Pointer to the driver instance structure.
148  */
149 void nrfx_rtc_uninit(nrfx_rtc_t const * p_instance);
150 
151 /**
152  * @brief Function for enabling the RTC driver instance.
153  *
154  * @param[in] p_instance Pointer to the driver instance structure.
155  */
156 void nrfx_rtc_enable(nrfx_rtc_t const * p_instance);
157 
158 /**
159  * @brief Function for disabling the RTC driver instance.
160  *
161  * @param[in] p_instance Pointer to the driver instance structure.
162  */
163 void nrfx_rtc_disable(nrfx_rtc_t const * p_instance);
164 
165 /**
166  * @brief Function for setting a compare channel.
167  *
168  * The function powers on the instance if the instance was in power off state.
169  *
170  * The driver is not entering a critical section when configuring RTC, which means that it can be
171  * preempted for a certain amount of time. When the driver was preempted and the value to be set
172  * is short in time, there is a risk that the driver sets a compare value that is
173  * behind. In this case, if the reliable mode is enabled for the specified instance,
174  * the risk is handled.
175  * However, to detect if the requested value is behind, this mode makes the following assumptions:
176  *  -  The maximum preemption time in ticks (8-bit value) is known and is less than 7.7 ms
177  *   (for prescaler = 0, RTC frequency 32 kHz).
178  *  -  The requested absolute compare value is not bigger than (0x00FFFFFF)-tick_latency. It is
179  *   the user's responsibility to ensure this.
180  *
181  * @param[in] p_instance Pointer to the driver instance structure.
182  * @param[in] channel    One of the channels of the instance.
183  * @param[in] val        Absolute value to be set in the compare register.
184  * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
185  *
186  * @retval NRFX_SUCCESS       The procedure is successful.
187  * @retval NRFX_ERROR_TIMEOUT The compare is not set because the request value is behind the
188  *                            current counter value. This error can only be reported
189  *                            if the reliable mode is enabled.
190  */
191 nrfx_err_t nrfx_rtc_cc_set(nrfx_rtc_t const * p_instance,
192                            uint32_t           channel,
193                            uint32_t           val,
194                            bool               enable_irq);
195 
196 /**
197  * @brief Function for disabling a channel.
198  *
199  * This function disables channel events and channel interrupts.
200  *
201  * @param[in] p_instance Pointer to the driver instance structure.
202  * @param[in] channel    One of the channels of the instance.
203  *
204  * @retval NRFX_SUCCESS       The procedure is successful.
205  * @retval NRFX_ERROR_TIMEOUT Interrupt is pending on the requested channel.
206  */
207 nrfx_err_t nrfx_rtc_cc_disable(nrfx_rtc_t const * p_instance, uint32_t channel);
208 
209 /**
210  * @brief Function for enabling the TICK event.
211  *
212  * This function enables the tick event and optionally the interrupt.
213  *
214  * @param[in] p_instance Pointer to the driver instance structure.
215  * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
216  */
217 void nrfx_rtc_tick_enable(nrfx_rtc_t const * p_instance, bool enable_irq);
218 
219 /**
220  * @brief Function for disabling the TICK event.
221  *
222  * This function disables the TICK event and interrupt.
223  *
224  * @param[in] p_instance Pointer to the driver instance structure.
225  */
226 void nrfx_rtc_tick_disable(nrfx_rtc_t const * p_instance);
227 
228 /**
229  * @brief Function for enabling overflow.
230  *
231  * This function enables the overflow event and optionally the interrupt.
232  *
233  * @param[in] p_instance Pointer to the driver instance structure.
234  * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
235  */
236 void nrfx_rtc_overflow_enable(nrfx_rtc_t const * p_instance, bool enable_irq);
237 
238 /**
239  * @brief Function for disabling overflow.
240  *
241  * This function disables the overflow event and interrupt.
242  *
243  * @param[in] p_instance Pointer to the driver instance structure.
244  */
245 void nrfx_rtc_overflow_disable(nrfx_rtc_t const * p_instance);
246 
247 /**
248  * @brief Function for getting the maximum relative tick value that can be set in the compare channel.
249  *
250  * When a stack (for example SoftDevice) is used and it occupies high priority interrupts,
251  * the application code can be interrupted at any moment for a certain period of time.
252  * If the reliable mode is enabled, the provided maximum latency is taken into account
253  * and the return value is smaller than the RTC counter resolution.
254  * If the reliable mode is disabled, the return value equals the counter resolution.
255  *
256  * @param[in] p_instance Pointer to the driver instance structure.
257  *
258  * @return Maximum ticks value.
259  */
260 uint32_t nrfx_rtc_max_ticks_get(nrfx_rtc_t const * p_instance);
261 
262 /**
263  * @brief Function for disabling all instance interrupts.
264   *
265  * @param[in] p_instance Pointer to the driver instance structure.
266  * @param[in] p_mask     Pointer to the location where the mask is filled.
267  */
268 NRFX_STATIC_INLINE void nrfx_rtc_int_disable(nrfx_rtc_t const * p_instance,
269                                              uint32_t *         p_mask);
270 
271 /**
272  * @brief Function for enabling instance interrupts.
273  *
274  * @param[in] p_instance Pointer to the driver instance structure.
275  * @param[in] mask       Mask of interrupts to enable.
276  */
277 NRFX_STATIC_INLINE void nrfx_rtc_int_enable(nrfx_rtc_t const * p_instance, uint32_t mask);
278 
279 /**
280  * @brief Function for retrieving the current counter value.
281  *
282  * @param[in] p_instance Pointer to the driver instance structure.
283  *
284  * @return Counter value.
285  */
286 NRFX_STATIC_INLINE uint32_t nrfx_rtc_counter_get(nrfx_rtc_t const * p_instance);
287 
288 /**
289  * @brief Function for clearing the counter value.
290  *
291  * @param[in] p_instance Pointer to the driver instance structure.
292  */
293 NRFX_STATIC_INLINE void nrfx_rtc_counter_clear(nrfx_rtc_t const * p_instance);
294 
295 /**
296  * @brief Function for returning a requested task address for the RTC driver instance.
297  *
298  * The task address can be used by the PPI module.
299  *
300  * @param[in] p_instance Pointer to the instance.
301  * @param[in] task       One of the peripheral tasks.
302  *
303  * @return Address of task register.
304  */
305 NRFX_STATIC_INLINE uint32_t nrfx_rtc_task_address_get(nrfx_rtc_t const * p_instance,
306                                                       nrf_rtc_task_t     task);
307 
308 /**
309  * @brief Function for returning a requested event address for the RTC driver instance.
310  *
311  * The event address can be used by the PPI module.
312  *
313  * @param[in] p_instance Pointer to the driver instance structure.
314  * @param[in] event      One of the peripheral events.
315  *
316  * @return Address of event register.
317  */
318 NRFX_STATIC_INLINE uint32_t nrfx_rtc_event_address_get(nrfx_rtc_t const * p_instance,
319                                                        nrf_rtc_event_t    event);
320 
321 #ifndef NRFX_DECLARE_ONLY
nrfx_rtc_int_disable(nrfx_rtc_t const * p_instance,uint32_t * p_mask)322 NRFX_STATIC_INLINE void nrfx_rtc_int_disable(nrfx_rtc_t const * p_instance,
323                                              uint32_t *         p_mask)
324 {
325     *p_mask = nrf_rtc_int_enable_check(p_instance->p_reg, ~0uL);
326     nrf_rtc_int_disable(p_instance->p_reg, NRF_RTC_INT_TICK_MASK |
327                                            NRF_RTC_INT_OVERFLOW_MASK |
328                                            NRF_RTC_INT_COMPARE0_MASK |
329                                            NRF_RTC_INT_COMPARE1_MASK |
330                                            NRF_RTC_INT_COMPARE2_MASK |
331                                            NRF_RTC_INT_COMPARE3_MASK);
332 }
333 
nrfx_rtc_int_enable(nrfx_rtc_t const * p_instance,uint32_t mask)334 NRFX_STATIC_INLINE void nrfx_rtc_int_enable(nrfx_rtc_t const * p_instance, uint32_t mask)
335 {
336     nrf_rtc_int_enable(p_instance->p_reg, mask);
337 }
338 
nrfx_rtc_counter_get(nrfx_rtc_t const * p_instance)339 NRFX_STATIC_INLINE uint32_t nrfx_rtc_counter_get(nrfx_rtc_t const * p_instance)
340 {
341     return nrf_rtc_counter_get(p_instance->p_reg);
342 }
343 
nrfx_rtc_counter_clear(nrfx_rtc_t const * p_instance)344 NRFX_STATIC_INLINE void nrfx_rtc_counter_clear(nrfx_rtc_t const * p_instance)
345 {
346     nrf_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_CLEAR);
347 }
348 
nrfx_rtc_task_address_get(nrfx_rtc_t const * p_instance,nrf_rtc_task_t task)349 NRFX_STATIC_INLINE uint32_t nrfx_rtc_task_address_get(nrfx_rtc_t const * p_instance,
350                                                       nrf_rtc_task_t     task)
351 {
352     return nrf_rtc_task_address_get(p_instance->p_reg, task);
353 }
354 
nrfx_rtc_event_address_get(nrfx_rtc_t const * p_instance,nrf_rtc_event_t event)355 NRFX_STATIC_INLINE uint32_t nrfx_rtc_event_address_get(nrfx_rtc_t const * p_instance,
356                                                        nrf_rtc_event_t    event)
357 {
358     return nrf_rtc_event_address_get(p_instance->p_reg, event);
359 }
360 #endif // NRFX_DECLARE_ONLY
361 
362 /** @} */
363 
364 
365 void nrfx_rtc_0_irq_handler(void);
366 void nrfx_rtc_1_irq_handler(void);
367 void nrfx_rtc_2_irq_handler(void);
368 
369 
370 #ifdef __cplusplus
371 }
372 #endif
373 
374 #endif // NRFX_RTC_H__
375