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