1 /*
2  * Copyright (c) 2016-2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_TIMER_NRF_RTC_TIMER_H
8 #define ZEPHYR_INCLUDE_DRIVERS_TIMER_NRF_RTC_TIMER_H
9 
10 #include <zephyr/sys_clock.h>
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 /** @brief Maximum allowed time span that is considered to be in the future.
17  */
18 #define NRF_RTC_TIMER_MAX_SCHEDULE_SPAN BIT(23)
19 
20 /** @brief RTC timer compare event handler.
21  *
22  * Called from RTC ISR context when processing a compare event.
23  *
24  * @param id Compare channel ID.
25  *
26  * @param expire_time An actual absolute expiration time set for a compare
27  *		      channel. It can differ from the requested target time
28  *		      and the difference can be used to determine whether the
29  *		      time set was delayed.
30  *
31  * @param user_data Pointer to a user context data.
32  */
33 typedef void (*z_nrf_rtc_timer_compare_handler_t)(int32_t id,
34 						uint64_t expire_time,
35 						void *user_data);
36 
37 /** @brief Allocate RTC compare channel.
38  *
39  * Channel 0 is used for the system clock.
40  *
41  * @retval Non-negative indicates allocated channel ID.
42  * @retval -ENOMEM if channel cannot be allocated.
43  */
44 int32_t z_nrf_rtc_timer_chan_alloc(void);
45 
46 /** @brief Free RTC compare channel.
47  *
48  * @param chan Previously allocated channel ID.
49  */
50 void z_nrf_rtc_timer_chan_free(int32_t chan);
51 
52 /** @brief Read current absolute time.
53  *
54  * @return Current absolute time.
55  */
56 uint64_t z_nrf_rtc_timer_read(void);
57 
58 /** @brief Get COMPARE event register address.
59  *
60  * Address can be used for (D)PPI.
61  *
62  * @param chan Channel ID between 0 and CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT.
63  *
64  * @return Register address.
65  */
66 uint32_t z_nrf_rtc_timer_compare_evt_address_get(int32_t chan);
67 
68 /** @brief Get CAPTURE task register address.
69  *
70  * Address can be used for (D)PPI.
71  *
72  * @note Not all platforms have CAPTURE task.
73  *
74  * @param chan Channel ID between 1 and CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT.
75  *
76  * @return Register address.
77  */
78 uint32_t z_nrf_rtc_timer_capture_task_address_get(int32_t chan);
79 
80 /** @brief Safely disable compare event interrupt.
81  *
82  * Function returns key indicating whether interrupt was already disabled.
83  *
84  * @param chan Channel ID between 1 and CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT.
85  *
86  * @return key passed to @ref z_nrf_rtc_timer_compare_int_unlock.
87  */
88 bool z_nrf_rtc_timer_compare_int_lock(int32_t chan);
89 
90 /** @brief Safely enable compare event interrupt.
91  *
92  * Event interrupt is conditionally enabled based on @p key.
93  *
94  * @param chan Channel ID between 1 and CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT.
95  *
96  * @param key Key returned by @ref z_nrf_rtc_timer_compare_int_lock.
97  */
98 void z_nrf_rtc_timer_compare_int_unlock(int32_t chan, bool key);
99 
100 /** @brief Read compare register value.
101  *
102  * @param chan Channel ID between 0 and CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT.
103  *
104  * @return Value set in the compare register.
105  */
106 uint32_t z_nrf_rtc_timer_compare_read(int32_t chan);
107 
108 /** @brief  Try to set compare channel to given value.
109  *
110  * Provided value is absolute and cannot be further in the future than
111  * @c NRF_RTC_TIMER_MAX_SCHEDULE_SPAN. If given value is in the past then an RTC
112  * interrupt is triggered immediately. Otherwise function continuously retries
113  * to set compare register until value that is written is far enough in the
114  * future and will generate an event. Because of that, compare register value
115  * may be different than the one requested. During this operation interrupt
116  * from that compare channel is disabled. Other interrupts are not locked during
117  * this operation.
118  *
119  * @param chan Channel ID between 1 and CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT.
120  *
121  * @param target_time Absolute target time in ticks.
122  *
123  * @param handler User function called in the context of the RTC interrupt.
124  *
125  * @param user_data Data passed to the handler.
126  *
127  * @retval 0 if the compare channel was set successfully.
128  * @retval -EINVAL if provided target time was further than
129  *         @c NRF_RTC_TIMER_MAX_SCHEDULE_SPAN ticks in the future.
130  *
131  * @sa @ref z_nrf_rtc_timer_exact_set
132  */
133 int z_nrf_rtc_timer_set(int32_t chan, uint64_t target_time,
134 			 z_nrf_rtc_timer_compare_handler_t handler,
135 			 void *user_data);
136 
137 /** @brief Try to set compare channel exactly to given value.
138  *
139  * @note This function is similar to @ref z_nrf_rtc_timer_set, but the compare
140  * channel will be set to expected value only when it can be guaranteed that
141  * the hardware event will be generated exactly at expected @c target_time in
142  * the future. If the @c target_time is in the past or so close in the future
143  * that the reliable generation of event would require adjustment of compare
144  * value (as would @ref z_nrf_rtc_timer_set function do), neither the hardware
145  * event nor interrupt will be generated and the function fails.
146  *
147  * @param chan Channel ID between 1 and CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT.
148  *
149  * @param target_time Absolute target time in ticks.
150  *
151  * @param handler User function called in the context of the RTC interrupt.
152  *
153  * @param user_data Data passed to the handler.
154  *
155  * @retval 0 if the compare channel was set successfully.
156  * @retval -EINVAL if provided target time was further than
157  *         @c NRF_RTC_TIMER_MAX_SCHEDULE_SPAN ticks in the future
158  *         or the target time is in the past or is so close in the future that
159  *         event generation could not be guaranteed without adjusting
160  *         compare value of that channel.
161  */
162 int z_nrf_rtc_timer_exact_set(int32_t chan, uint64_t target_time,
163 			      z_nrf_rtc_timer_compare_handler_t handler,
164 			      void *user_data);
165 
166 /** @brief Abort a timer requested with @ref z_nrf_rtc_timer_set.
167  *
168  * If an abort operation is performed too late it is still possible for an event
169  * to fire. The user can detect a spurious event by comparing absolute time
170  * provided in callback and a result of @ref z_nrf_rtc_timer_read. During this
171  * operation interrupt from that compare channel is disabled. Other interrupts
172  * are not locked during this operation.
173  *
174  * @param chan Channel ID between 1 and CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT.
175  */
176 void z_nrf_rtc_timer_abort(int32_t chan);
177 
178 /** @brief Convert system clock time to RTC ticks.
179  *
180  * @p t can be absolute or relative. @p t cannot be further into the future
181  * from now than the RTC range (e.g. 512 seconds if RTC is running at 32768 Hz).
182  *
183  * @retval Positive value represents @p t in RTC tick value.
184  * @retval -EINVAL if @p t is out of range.
185  */
186 uint64_t z_nrf_rtc_timer_get_ticks(k_timeout_t t);
187 
188 /** @brief Get offset between nrf53 network cpu system clock and application cpu
189  * system clock.
190  *
191  * Returned value added to the current system tick on network cpu gives current
192  * application cpu system tick. Function can only be used on network cpu. It
193  * requires @ref CONFIG_NRF53_SYNC_RTC being enabled.
194  *
195  * @retval Non-negative offset given in RTC ticks.
196  * @retval -ENOSYS if operation is not supported.
197  * @retval -EBUSY if synchronization is not yet completed.
198  */
199 int z_nrf_rtc_timer_nrf53net_offset_get(void);
200 
201 /** @brief Move RTC counter forward using TRIGOVRFLW hardware feature.
202  *
203  * RTC has a hardware feature which can force counter to jump to 0xFFFFF0 value
204  * which is close to overflow. Function is using this feature and updates
205  * driver internal to perform time shift to the future. Operation can only be
206  * performed when there are no active alarms set. It should be used for testing
207  * only.
208  *
209  * @retval 0 on successful shift.
210  * @retval -EBUSY if there are active alarms.
211  * @retval -EAGAIN if current counter value is too close to overflow.
212  * @retval -ENOTSUP if option is disabled in Kconfig or additional channels are enabled.
213  */
214 int z_nrf_rtc_timer_trigger_overflow(void);
215 
216 #ifdef __cplusplus
217 }
218 #endif
219 
220 #endif /* ZEPHYR_INCLUDE_DRIVERS_TIMER_NRF_RTC_TIMER_H */
221