1 /*
2  * Copyright (c) 2015 - 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 NRF_WDT_H__
33 #define NRF_WDT_H__
34 
35 #include <nrfx.h>
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 
41 #ifndef NRF_WDT0
42 #define NRF_WDT0 NRF_WDT
43 #endif
44 
45 /**
46  * @defgroup nrf_wdt_hal WDT HAL
47  * @{
48  * @ingroup nrf_wdt
49  * @brief   Hardware access layer for managing the Watchdog Timer (WDT) peripheral.
50  */
51 
52 /** @brief Number of WDT channels. */
53 #define NRF_WDT_CHANNEL_NUMBER 0x8UL
54 
55 /** @brief WDT register reload value. */
56 #define NRF_WDT_RR_VALUE       0x6E524635UL /* Fixed value; should not be modified. */
57 
58 
59 /** @brief WDT tasks. */
60 typedef enum
61 {
62     NRF_WDT_TASK_START = offsetof(NRF_WDT_Type, TASKS_START), /**< Task for starting WDT. */
63 } nrf_wdt_task_t;
64 
65 /** @brief WDT events. */
66 typedef enum
67 {
68     NRF_WDT_EVENT_TIMEOUT = offsetof(NRF_WDT_Type, EVENTS_TIMEOUT), /**< Event from WDT time-out. */
69 } nrf_wdt_event_t;
70 
71 /** @brief WDT behavior in the SLEEP or HALT CPU modes. */
72 typedef enum
73 {
74     NRF_WDT_BEHAVIOUR_RUN_SLEEP        = WDT_CONFIG_SLEEP_Msk,                       /**< WDT will run when CPU is in SLEEP mode. */
75     NRF_WDT_BEHAVIOUR_RUN_HALT         = WDT_CONFIG_HALT_Msk,                        /**< WDT will run when CPU is in HALT mode. */
76     NRF_WDT_BEHAVIOUR_RUN_SLEEP_HALT   = WDT_CONFIG_SLEEP_Msk | WDT_CONFIG_HALT_Msk, /**< WDT will run when CPU is in SLEEP or HALT mode. */
77     NRF_WDT_BEHAVIOUR_PAUSE_SLEEP_HALT = 0,                                          /**< WDT will be paused when CPU is in SLEEP or HALT mode. */
78 } nrf_wdt_behaviour_t;
79 
80 /** @brief WDT reload request registers. */
81 typedef enum
82 {
83     NRF_WDT_RR0 = 0, /**< Reload request register 0. */
84     NRF_WDT_RR1,     /**< Reload request register 1. */
85     NRF_WDT_RR2,     /**< Reload request register 2. */
86     NRF_WDT_RR3,     /**< Reload request register 3. */
87     NRF_WDT_RR4,     /**< Reload request register 4. */
88     NRF_WDT_RR5,     /**< Reload request register 5. */
89     NRF_WDT_RR6,     /**< Reload request register 6. */
90     NRF_WDT_RR7      /**< Reload request register 7. */
91 } nrf_wdt_rr_register_t;
92 
93 /** @brief WDT interrupts. */
94 typedef enum
95 {
96     NRF_WDT_INT_TIMEOUT_MASK = WDT_INTENSET_TIMEOUT_Msk, /**< WDT interrupt from time-out event. */
97 } nrf_wdt_int_mask_t;
98 
99 
100 /**
101  * @brief Function for configuring the watchdog behavior when the CPU is sleeping or halted.
102  *
103  * @param[in] p_reg     Pointer to the structure of registers of the peripheral.
104  * @param[in] behaviour Watchdog behavior when CPU is in SLEEP or HALT mode.
105  */
106 NRF_STATIC_INLINE void nrf_wdt_behaviour_set(NRF_WDT_Type * p_reg, nrf_wdt_behaviour_t behaviour);
107 
108 /**
109  * @brief Function for starting the WDT task.
110  *
111  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
112  * @param[in] task  Task.
113  */
114 NRF_STATIC_INLINE void nrf_wdt_task_trigger(NRF_WDT_Type * p_reg, nrf_wdt_task_t task);
115 
116 /**
117  * @brief Function for clearing the WDT event register.
118  *
119  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
120  * @param[in] event Event.
121  */
122 NRF_STATIC_INLINE void nrf_wdt_event_clear(NRF_WDT_Type * p_reg, nrf_wdt_event_t event);
123 
124 /**
125  * @brief Function for retrieving the state of the WDT event.
126  *
127  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
128  * @param[in] event Event to be checked.
129  *
130  * @retval true  The event has been generated.
131  * @retval false The event has not been generated.
132  */
133 NRF_STATIC_INLINE bool nrf_wdt_event_check(NRF_WDT_Type const * p_reg, nrf_wdt_event_t event);
134 
135 /**
136  * @brief Function for enabling the specified interrupt.
137  *
138  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
139  * @param[in] mask  Mask of interrupts to be enabled.
140  */
141 NRF_STATIC_INLINE void nrf_wdt_int_enable(NRF_WDT_Type * p_reg, uint32_t mask);
142 
143 /**
144  * @brief Function for checking if the specified interrupts are enabled.
145  *
146  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
147  * @param[in] mask  Mask of interrupts to be checked.
148  *
149  * @return Mask of enabled interrupts.
150  */
151 NRF_STATIC_INLINE uint32_t nrf_wdt_int_enable_check(NRF_WDT_Type const * p_reg, uint32_t mask);
152 
153 /**
154  * @brief Function for disabling a specific interrupt.
155  *
156  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
157  * @param[in] mask  Mask of interrupts to be disabled.
158  */
159 NRF_STATIC_INLINE void nrf_wdt_int_disable(NRF_WDT_Type * p_reg, uint32_t mask);
160 
161 #if defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
162 /**
163  * @brief Function for setting the subscribe configuration for a given
164  *        WDT task.
165  *
166  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
167  * @param[in] task    Task for which to set the configuration.
168  * @param[in] channel Channel through which to subscribe events.
169  */
170 NRF_STATIC_INLINE void nrf_wdt_subscribe_set(NRF_WDT_Type * p_reg,
171                                              nrf_wdt_task_t task,
172                                              uint8_t        channel);
173 
174 /**
175  * @brief Function for clearing the subscribe configuration for a given
176  *        WDT task.
177  *
178  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
179  * @param[in] task  Task for which to clear the configuration.
180  */
181 NRF_STATIC_INLINE void nrf_wdt_subscribe_clear(NRF_WDT_Type * p_reg, nrf_wdt_task_t task);
182 
183 /**
184  * @brief Function for setting the publish configuration for a given
185  *        WDT event.
186  *
187  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
188  * @param[in] event   Event for which to set the configuration.
189  * @param[in] channel Channel through which to publish the event.
190  */
191 NRF_STATIC_INLINE void nrf_wdt_publish_set(NRF_WDT_Type *  p_reg,
192                                            nrf_wdt_event_t event,
193                                            uint8_t         channel);
194 
195 /**
196  * @brief Function for clearing the publish configuration for a given
197  *        WDT event.
198  *
199  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
200  * @param[in] event Event for which to clear the configuration.
201  */
202 NRF_STATIC_INLINE void nrf_wdt_publish_clear(NRF_WDT_Type * p_reg, nrf_wdt_event_t event);
203 #endif // defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
204 
205 /**
206  * @brief Function for returning the address of a specific WDT task register.
207  *
208  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
209  * @param[in] task  Task.
210  *
211  * @return Address of requested task register
212  */
213 NRF_STATIC_INLINE uint32_t nrf_wdt_task_address_get(NRF_WDT_Type const * p_reg,
214                                                     nrf_wdt_task_t       task);
215 
216 /**
217  * @brief Function for returning the address of a specific WDT event register.
218  *
219  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
220  * @param[in] event Event.
221  *
222  * @return Address of requested event register
223  */
224 NRF_STATIC_INLINE uint32_t nrf_wdt_event_address_get(NRF_WDT_Type const * p_reg,
225                                                      nrf_wdt_event_t      event);
226 
227 /**
228  * @brief Function for retrieving the watchdog status.
229  *
230  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
231  *
232  * @retval true  The watchdog is started.
233  * @retval false The watchdog is not started.
234  */
235 NRF_STATIC_INLINE bool nrf_wdt_started(NRF_WDT_Type const * p_reg);
236 
237 /**
238  * @brief Function for retrieving the watchdog reload request status.
239  *
240  * @param[in] p_reg       Pointer to the structure of registers of the peripheral.
241  * @param[in] rr_register Reload request register to be checked.
242  *
243  * @retval true  Reload request is running.
244  * @retval false No reload requests are running.
245  */
246 NRF_STATIC_INLINE bool nrf_wdt_request_status(NRF_WDT_Type const *  p_reg,
247                                               nrf_wdt_rr_register_t rr_register);
248 
249 /**
250  * @brief Function for setting the watchdog reload value.
251  *
252  * @param[in] p_reg        Pointer to the structure of registers of the peripheral.
253  * @param[in] reload_value Watchdog counter initial value.
254  */
255 NRF_STATIC_INLINE void nrf_wdt_reload_value_set(NRF_WDT_Type * p_reg, uint32_t reload_value);
256 
257 /**
258  * @brief Function for retrieving the watchdog reload value.
259  *
260  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
261  *
262  * @return Reload value.
263  */
264 NRF_STATIC_INLINE uint32_t nrf_wdt_reload_value_get(NRF_WDT_Type const * p_reg);
265 
266 /**
267  * @brief Function for enabling a specific reload request register.
268  *
269  * @param[in] p_reg       Pointer to the structure of registers of the peripheral.
270  * @param[in] rr_register Reload request register to be enabled.
271  */
272 NRF_STATIC_INLINE void nrf_wdt_reload_request_enable(NRF_WDT_Type *        p_reg,
273                                                      nrf_wdt_rr_register_t rr_register);
274 
275 /**
276  * @brief Function for disabling a specific reload request register.
277  *
278  * @param[in] p_reg       Pointer to the structure of registers of the peripheral.
279  * @param[in] rr_register Reload request register to be disabled.
280  */
281 NRF_STATIC_INLINE void nrf_wdt_reload_request_disable(NRF_WDT_Type *        p_reg,
282                                                       nrf_wdt_rr_register_t rr_register);
283 
284 /**
285  * @brief Function for retrieving the status of a specific reload request register.
286  *
287  * @param[in] p_reg       Pointer to the structure of registers of the peripheral.
288  * @param[in] rr_register Reload request register to be checked.
289  *
290  * @retval true  The reload request register is enabled.
291  * @retval false The reload request register is not enabled.
292  */
293 NRF_STATIC_INLINE bool nrf_wdt_reload_request_is_enabled(NRF_WDT_Type const *  p_reg,
294                                                          nrf_wdt_rr_register_t rr_register);
295 
296 /**
297  * @brief Function for setting a specific reload request register.
298  *
299  * @param[in] p_reg       Pointer to the structure of registers of the peripheral.
300  * @param[in] rr_register Reload request register to set.
301  */
302 NRF_STATIC_INLINE void nrf_wdt_reload_request_set(NRF_WDT_Type *        p_reg,
303                                                   nrf_wdt_rr_register_t rr_register);
304 
305 #ifndef NRF_DECLARE_ONLY
306 
nrf_wdt_behaviour_set(NRF_WDT_Type * p_reg,nrf_wdt_behaviour_t behaviour)307 NRF_STATIC_INLINE void nrf_wdt_behaviour_set(NRF_WDT_Type * p_reg, nrf_wdt_behaviour_t behaviour)
308 {
309     p_reg->CONFIG = behaviour;
310 }
311 
nrf_wdt_task_trigger(NRF_WDT_Type * p_reg,nrf_wdt_task_t task)312 NRF_STATIC_INLINE void nrf_wdt_task_trigger(NRF_WDT_Type * p_reg, nrf_wdt_task_t task)
313 {
314     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x01UL;
315 }
316 
nrf_wdt_event_clear(NRF_WDT_Type * p_reg,nrf_wdt_event_t event)317 NRF_STATIC_INLINE void nrf_wdt_event_clear(NRF_WDT_Type * p_reg, nrf_wdt_event_t event)
318 {
319     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL;
320     nrf_event_readback((uint8_t *)p_reg + (uint32_t)event);
321 }
322 
nrf_wdt_event_check(NRF_WDT_Type const * p_reg,nrf_wdt_event_t event)323 NRF_STATIC_INLINE bool nrf_wdt_event_check(NRF_WDT_Type const * p_reg, nrf_wdt_event_t event)
324 {
325     return (bool)*((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event));
326 }
327 
nrf_wdt_int_enable(NRF_WDT_Type * p_reg,uint32_t mask)328 NRF_STATIC_INLINE void nrf_wdt_int_enable(NRF_WDT_Type * p_reg, uint32_t mask)
329 {
330     p_reg->INTENSET = mask;
331 }
332 
nrf_wdt_int_enable_check(NRF_WDT_Type const * p_reg,uint32_t mask)333 NRF_STATIC_INLINE uint32_t nrf_wdt_int_enable_check(NRF_WDT_Type const * p_reg, uint32_t mask)
334 {
335     return p_reg->INTENSET & mask;
336 }
337 
nrf_wdt_int_disable(NRF_WDT_Type * p_reg,uint32_t mask)338 NRF_STATIC_INLINE void nrf_wdt_int_disable(NRF_WDT_Type * p_reg, uint32_t mask)
339 {
340     p_reg->INTENCLR = mask;
341 }
342 
343 #if defined(DPPI_PRESENT)
nrf_wdt_subscribe_set(NRF_WDT_Type * p_reg,nrf_wdt_task_t task,uint8_t channel)344 NRF_STATIC_INLINE void nrf_wdt_subscribe_set(NRF_WDT_Type * p_reg,
345                                              nrf_wdt_task_t task,
346                                              uint8_t        channel)
347 {
348     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) =
349             ((uint32_t)channel | WDT_SUBSCRIBE_START_EN_Msk);
350 }
351 
nrf_wdt_subscribe_clear(NRF_WDT_Type * p_reg,nrf_wdt_task_t task)352 NRF_STATIC_INLINE void nrf_wdt_subscribe_clear(NRF_WDT_Type * p_reg, nrf_wdt_task_t task)
353 {
354     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) = 0;
355 }
356 
nrf_wdt_publish_set(NRF_WDT_Type * p_reg,nrf_wdt_event_t event,uint8_t channel)357 NRF_STATIC_INLINE void nrf_wdt_publish_set(NRF_WDT_Type *  p_reg,
358                                            nrf_wdt_event_t event,
359                                            uint8_t         channel)
360 {
361     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) event + 0x80uL)) =
362             ((uint32_t)channel | WDT_PUBLISH_TIMEOUT_EN_Msk);
363 }
364 
nrf_wdt_publish_clear(NRF_WDT_Type * p_reg,nrf_wdt_event_t event)365 NRF_STATIC_INLINE void nrf_wdt_publish_clear(NRF_WDT_Type * p_reg, nrf_wdt_event_t event)
366 {
367     *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) event + 0x80uL)) = 0;
368 }
369 #endif // defined(DPPI_PRESENT)
370 
nrf_wdt_task_address_get(NRF_WDT_Type const * p_reg,nrf_wdt_task_t task)371 NRF_STATIC_INLINE uint32_t nrf_wdt_task_address_get(NRF_WDT_Type const * p_reg,
372                                                     nrf_wdt_task_t       task)
373 {
374     return ((uint32_t)p_reg + (uint32_t)task);
375 }
376 
nrf_wdt_event_address_get(NRF_WDT_Type const * p_reg,nrf_wdt_event_t event)377 NRF_STATIC_INLINE uint32_t nrf_wdt_event_address_get(NRF_WDT_Type const * p_reg,
378                                                      nrf_wdt_event_t      event)
379 {
380     return ((uint32_t)p_reg + (uint32_t)event);
381 }
382 
nrf_wdt_started(NRF_WDT_Type const * p_reg)383 NRF_STATIC_INLINE bool nrf_wdt_started(NRF_WDT_Type const * p_reg)
384 {
385     return (bool)(p_reg->RUNSTATUS);
386 }
387 
nrf_wdt_request_status(NRF_WDT_Type const * p_reg,nrf_wdt_rr_register_t rr_register)388 NRF_STATIC_INLINE bool nrf_wdt_request_status(NRF_WDT_Type const *  p_reg,
389                                               nrf_wdt_rr_register_t rr_register)
390 {
391     return (bool)(((p_reg->REQSTATUS) >> rr_register) & 0x1UL);
392 }
393 
nrf_wdt_reload_value_set(NRF_WDT_Type * p_reg,uint32_t reload_value)394 NRF_STATIC_INLINE void nrf_wdt_reload_value_set(NRF_WDT_Type * p_reg, uint32_t reload_value)
395 {
396     p_reg->CRV = reload_value;
397 }
398 
nrf_wdt_reload_value_get(NRF_WDT_Type const * p_reg)399 NRF_STATIC_INLINE uint32_t nrf_wdt_reload_value_get(NRF_WDT_Type const * p_reg)
400 {
401     return (uint32_t)p_reg->CRV;
402 }
403 
nrf_wdt_reload_request_enable(NRF_WDT_Type * p_reg,nrf_wdt_rr_register_t rr_register)404 NRF_STATIC_INLINE void nrf_wdt_reload_request_enable(NRF_WDT_Type *        p_reg,
405                                                      nrf_wdt_rr_register_t rr_register)
406 {
407     p_reg->RREN |= 0x1UL << rr_register;
408 }
409 
nrf_wdt_reload_request_disable(NRF_WDT_Type * p_reg,nrf_wdt_rr_register_t rr_register)410 NRF_STATIC_INLINE void nrf_wdt_reload_request_disable(NRF_WDT_Type *        p_reg,
411                                                       nrf_wdt_rr_register_t rr_register)
412 {
413     p_reg->RREN &= ~(0x1UL << rr_register);
414 }
415 
nrf_wdt_reload_request_is_enabled(NRF_WDT_Type const * p_reg,nrf_wdt_rr_register_t rr_register)416 NRF_STATIC_INLINE bool nrf_wdt_reload_request_is_enabled(NRF_WDT_Type const *  p_reg,
417                                                          nrf_wdt_rr_register_t rr_register)
418 {
419     return (bool)(p_reg->RREN & (0x1UL << rr_register));
420 }
421 
nrf_wdt_reload_request_set(NRF_WDT_Type * p_reg,nrf_wdt_rr_register_t rr_register)422 NRF_STATIC_INLINE void nrf_wdt_reload_request_set(NRF_WDT_Type *        p_reg,
423                                                   nrf_wdt_rr_register_t rr_register)
424 {
425     p_reg->RR[rr_register] = NRF_WDT_RR_VALUE;
426 }
427 
428 #endif // NRF_DECLARE_ONLY
429 
430 /** @} */
431 
432 #ifdef __cplusplus
433 }
434 #endif
435 
436 #endif // NRF_WDT_H__
437