1 /*
2  * Copyright (c) 2021 - 2023, 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 #ifndef NRFY_WDT_H__
35 #define NRFY_WDT_H__
36 
37 #include <nrfx.h>
38 #include <hal/nrf_wdt.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 NRFY_STATIC_INLINE bool __nrfy_internal_wdt_event_handle(NRF_WDT_Type *  p_reg,
45                                                          uint32_t        mask,
46                                                          nrf_wdt_event_t event,
47                                                          uint32_t *      p_evt_mask);
48 
49 NRFY_STATIC_INLINE uint32_t __nrfy_internal_wdt_events_process(NRF_WDT_Type * p_reg, uint32_t mask);
50 
51 NRFY_STATIC_INLINE void __nrfy_internal_wdt_event_enabled_clear(NRF_WDT_Type *  p_reg,
52                                                                 uint32_t        mask,
53                                                                 nrf_wdt_event_t event);
54 
55 /**
56  * @defgroup nrfy_wdt WDT HALY
57  * @{
58  * @ingroup nrf_wdt
59  * @brief   Hardware access layer with cache and barrier support for managing the WDT peripheral.
60  */
61 
62 #if NRF_WDT_HAS_STOP || defined(__NRFX_DOXYGEN__)
63 /** @refhal{NRF_WDT_HAS_STOP} */
64 #define NRFY_WDT_HAS_STOP 1
65 #else
66 #define NRFY_WDT_HAS_STOP 0
67 #endif
68 
69 /** @brief WDT configuration structure. */
70 typedef struct
71 {
72     uint32_t behaviour;    ///< Watchdog behaviour flags bitmask, constructed from @ref nrf_wdt_behaviour_mask_t.
73     uint32_t reload_value; ///< Watchdog counter initial value.
74 } nrfy_wdt_config_t;
75 
76 /**
77  * @brief Function for configuring the WDT.
78  *
79  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
80  * @param[in] p_config Pointer to the peripheral configuration structure.
81  */
nrfy_wdt_periph_configure(NRF_WDT_Type * p_reg,nrfy_wdt_config_t const * p_config)82 NRFY_STATIC_INLINE void nrfy_wdt_periph_configure(NRF_WDT_Type *            p_reg,
83                                                   nrfy_wdt_config_t const * p_config)
84 {
85     nrf_wdt_behaviour_set(p_reg, p_config->behaviour);
86     nrf_wdt_reload_value_set(p_reg, p_config->reload_value);
87     nrf_barrier_w();
88 }
89 
90 /**
91  * @brief Function for initializing the specified WDT interrupts.
92  *
93  * @param[in] p_reg        Pointer to the structure of registers of the peripheral.
94  * @param[in] mask         Mask of interrupts to be initialized.
95  * @param[in] irq_priority Interrupt priority.
96  * @param[in] enable       True if interrupts are to be enabled, false otherwise.
97  */
nrfy_wdt_int_init(NRF_WDT_Type * p_reg,uint32_t mask,uint8_t irq_priority,bool enable)98 NRFY_STATIC_INLINE void nrfy_wdt_int_init(NRF_WDT_Type * p_reg,
99                                           uint32_t       mask,
100                                           uint8_t        irq_priority,
101                                           bool           enable)
102 {
103     __nrfy_internal_wdt_event_enabled_clear(p_reg, mask, NRF_WDT_EVENT_TIMEOUT);
104 #if NRFY_WDT_HAS_STOP
105     __nrfy_internal_wdt_event_enabled_clear(p_reg, mask, NRF_WDT_EVENT_STOPPED);
106 #endif
107     nrf_barrier_w();
108 
109     NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_reg), irq_priority);
110     NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_reg));
111 
112     if (enable)
113     {
114         nrf_wdt_int_enable(p_reg, mask);
115     }
116     nrf_barrier_w();
117 }
118 
119 /**
120  * @brief Function for uninitializing the WDT interrupts.
121  *
122  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
123  */
nrfy_wdt_int_uninit(NRF_WDT_Type * p_reg)124 NRFY_STATIC_INLINE void nrfy_wdt_int_uninit(NRF_WDT_Type * p_reg)
125 {
126     NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_reg));
127     nrf_barrier_w();
128 }
129 
130 /**
131  * @brief Function for processing the specified WDT events.
132  *
133  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
134  * @param[in] mask  Mask of events to be processed, created by @ref NRFY_EVENT_TO_INT_BITMASK.
135  *
136  * @return Mask of events that were generated and processed.
137  *         To be checked against the result of @ref NRFY_EVENT_TO_INT_BITMASK().
138  */
nrfy_wdt_events_process(NRF_WDT_Type * p_reg,uint32_t mask)139 NRFY_STATIC_INLINE uint32_t nrfy_wdt_events_process(NRF_WDT_Type * p_reg, uint32_t mask)
140 {
141     uint32_t evt_mask = __nrfy_internal_wdt_events_process(p_reg, mask);
142     nrf_barrier_w();
143     return evt_mask;
144 }
145 
146 /** @refhal{nrf_wdt_task_trigger} */
nrfy_wdt_task_trigger(NRF_WDT_Type * p_reg,nrf_wdt_task_t task)147 NRFY_STATIC_INLINE void nrfy_wdt_task_trigger(NRF_WDT_Type * p_reg, nrf_wdt_task_t task)
148 {
149     nrf_wdt_task_trigger(p_reg, task);
150     nrf_barrier_w();
151 }
152 
153 /** @refhal{nrf_wdt_task_address_get} */
nrfy_wdt_task_address_get(NRF_WDT_Type const * p_reg,nrf_wdt_task_t task)154 NRFY_STATIC_INLINE uint32_t nrfy_wdt_task_address_get(NRF_WDT_Type const * p_reg,
155                                                       nrf_wdt_task_t       task)
156 {
157     return nrf_wdt_task_address_get(p_reg, task);
158 }
159 
160 /** @refhal{nrf_wdt_event_clear} */
nrfy_wdt_event_clear(NRF_WDT_Type * p_reg,nrf_wdt_event_t event)161 NRFY_STATIC_INLINE void nrfy_wdt_event_clear(NRF_WDT_Type * p_reg, nrf_wdt_event_t event)
162 {
163     nrf_wdt_event_clear(p_reg, event);
164     nrf_barrier_w();
165 }
166 
167 /** @refhal{nrf_wdt_event_check} */
nrfy_wdt_event_check(NRF_WDT_Type const * p_reg,nrf_wdt_event_t event)168 NRFY_STATIC_INLINE bool nrfy_wdt_event_check(NRF_WDT_Type const * p_reg, nrf_wdt_event_t event)
169 {
170     nrf_barrier_r();
171     bool check = nrf_wdt_event_check(p_reg, event);
172     nrf_barrier_r();
173     return check;
174 }
175 
176 /** @refhal{nrf_wdt_event_address_get} */
nrfy_wdt_event_address_get(NRF_WDT_Type const * p_reg,nrf_wdt_event_t event)177 NRFY_STATIC_INLINE uint32_t nrfy_wdt_event_address_get(NRF_WDT_Type const * p_reg,
178                                                        nrf_wdt_event_t      event)
179 {
180     return nrf_wdt_event_address_get(p_reg, event);
181 }
182 
183 /** @refhal{nrf_wdt_int_enable} */
nrfy_wdt_int_enable(NRF_WDT_Type * p_reg,uint32_t mask)184 NRFY_STATIC_INLINE void nrfy_wdt_int_enable(NRF_WDT_Type * p_reg, uint32_t mask)
185 {
186     nrf_wdt_int_enable(p_reg, mask);
187     nrf_barrier_w();
188 }
189 
190 /** @refhal{nrf_wdt_int_enable_check} */
nrfy_wdt_int_enable_check(NRF_WDT_Type const * p_reg,uint32_t mask)191 NRFY_STATIC_INLINE uint32_t nrfy_wdt_int_enable_check(NRF_WDT_Type const * p_reg, uint32_t mask)
192 {
193     nrf_barrier_rw();
194     uint32_t check = nrf_wdt_int_enable_check(p_reg, mask);
195     nrf_barrier_r();
196     return check;
197 }
198 
199 /** @refhal{nrf_wdt_int_disable} */
nrfy_wdt_int_disable(NRF_WDT_Type * p_reg,uint32_t mask)200 NRFY_STATIC_INLINE void nrfy_wdt_int_disable(NRF_WDT_Type * p_reg, uint32_t mask)
201 {
202     nrf_wdt_int_disable(p_reg, mask);
203     nrf_barrier_w();
204 }
205 
206 #if defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
207 /** @refhal{nrf_wdt_subscribe_set} */
nrfy_wdt_subscribe_set(NRF_WDT_Type * p_reg,nrf_wdt_task_t task,uint8_t channel)208 NRFY_STATIC_INLINE void nrfy_wdt_subscribe_set(NRF_WDT_Type * p_reg,
209                                                nrf_wdt_task_t task,
210                                                uint8_t        channel)
211 {
212     nrf_wdt_subscribe_set(p_reg, task, channel);
213     nrf_barrier_w();
214 }
215 
216 /** @refhal{nrf_wdt_subscribe_clear} */
nrfy_wdt_subscribe_clear(NRF_WDT_Type * p_reg,nrf_wdt_task_t task)217 NRFY_STATIC_INLINE void nrfy_wdt_subscribe_clear(NRF_WDT_Type * p_reg, nrf_wdt_task_t task)
218 {
219     nrf_wdt_subscribe_clear(p_reg, task);
220     nrf_barrier_w();
221 }
222 
223 /** @refhal{nrf_wdt_publish_set} */
nrfy_wdt_publish_set(NRF_WDT_Type * p_reg,nrf_wdt_event_t event,uint8_t channel)224 NRFY_STATIC_INLINE void nrfy_wdt_publish_set(NRF_WDT_Type *  p_reg,
225                                              nrf_wdt_event_t event,
226                                              uint8_t         channel)
227 {
228     nrf_wdt_publish_set(p_reg, event, channel);
229     nrf_barrier_w();
230 }
231 
232 /** @refhal{nrf_wdt_publish_clear} */
nrfy_wdt_publish_clear(NRF_WDT_Type * p_reg,nrf_wdt_event_t event)233 NRFY_STATIC_INLINE void nrfy_wdt_publish_clear(NRF_WDT_Type * p_reg, nrf_wdt_event_t event)
234 {
235     nrf_wdt_publish_clear(p_reg, event);
236     nrf_barrier_w();
237 }
238 #endif // defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
239 
240 /** @refhal{nrf_wdt_behaviour_set} */
nrfy_wdt_behaviour_set(NRF_WDT_Type * p_reg,uint32_t mask)241 NRFY_STATIC_INLINE void nrfy_wdt_behaviour_set(NRF_WDT_Type * p_reg, uint32_t mask)
242 {
243     nrf_wdt_behaviour_set(p_reg, mask);
244     nrf_barrier_w();
245 }
246 
247 /** @refhal{nrf_wdt_started_check} */
nrfy_wdt_started_check(NRF_WDT_Type const * p_reg)248 NRFY_STATIC_INLINE bool nrfy_wdt_started_check(NRF_WDT_Type const * p_reg)
249 {
250     nrf_barrier_r();
251     bool check = nrf_wdt_started_check(p_reg);
252     nrf_barrier_r();
253     return check;
254 }
255 
256 /** @refhal{nrf_wdt_request_status_check} */
nrfy_wdt_request_status_check(NRF_WDT_Type const * p_reg,nrf_wdt_rr_register_t rr_register)257 NRFY_STATIC_INLINE bool nrfy_wdt_request_status_check(NRF_WDT_Type const *  p_reg,
258                                                       nrf_wdt_rr_register_t rr_register)
259 {
260     nrf_barrier_r();
261     bool check = nrf_wdt_request_status_check(p_reg, rr_register);
262     nrf_barrier_r();
263     return check;
264 }
265 
266 /** @refhal{nrf_wdt_request_status_get} */
nrfy_wdt_request_status_get(NRF_WDT_Type const * p_reg)267 NRFY_STATIC_INLINE uint32_t nrfy_wdt_request_status_get(NRF_WDT_Type const * p_reg)
268 {
269     nrf_barrier_r();
270     uint32_t ret = nrf_wdt_request_status_get(p_reg);
271     nrf_barrier_r();
272     return ret;
273 }
274 
275 /** @refhal{nrf_wdt_reload_value_set} */
nrfy_wdt_reload_value_set(NRF_WDT_Type * p_reg,uint32_t reload_value)276 NRFY_STATIC_INLINE void nrfy_wdt_reload_value_set(NRF_WDT_Type * p_reg, uint32_t reload_value)
277 {
278     nrf_wdt_reload_value_set(p_reg, reload_value);
279     nrf_barrier_w();
280 }
281 
282 /** @refhal{nrf_wdt_reload_value_get} */
nrfy_wdt_reload_value_get(NRF_WDT_Type const * p_reg)283 NRFY_STATIC_INLINE uint32_t nrfy_wdt_reload_value_get(NRF_WDT_Type const * p_reg)
284 {
285     nrf_barrier_rw();
286     uint32_t ret = nrf_wdt_reload_value_get(p_reg);
287     nrf_barrier_r();
288     return ret;
289 }
290 
291 /** @refhal{nrf_wdt_reload_request_enable} */
nrfy_wdt_reload_request_enable(NRF_WDT_Type * p_reg,nrf_wdt_rr_register_t rr_register)292 NRFY_STATIC_INLINE void nrfy_wdt_reload_request_enable(NRF_WDT_Type *       p_reg,
293                                                        nrf_wdt_rr_register_t rr_register)
294 {
295     nrf_wdt_reload_request_enable(p_reg, rr_register);
296     nrf_barrier_w();
297 }
298 
299 /** @refhal{nrf_wdt_reload_request_disable} */
nrfy_wdt_reload_request_disable(NRF_WDT_Type * p_reg,nrf_wdt_rr_register_t rr_register)300 NRFY_STATIC_INLINE void nrfy_wdt_reload_request_disable(NRF_WDT_Type *       p_reg,
301                                                         nrf_wdt_rr_register_t rr_register)
302 {
303     nrf_wdt_reload_request_disable(p_reg, rr_register);
304     nrf_barrier_w();
305 }
306 
307 /** @refhal{nrf_wdt_reload_request_enable_check} */
nrfy_wdt_reload_request_enable_check(NRF_WDT_Type const * p_reg,nrf_wdt_rr_register_t rr_register)308 NRFY_STATIC_INLINE bool nrfy_wdt_reload_request_enable_check(NRF_WDT_Type const *  p_reg,
309                                                              nrf_wdt_rr_register_t rr_register)
310 {
311     nrf_barrier_rw();
312     bool check = nrf_wdt_reload_request_enable_check(p_reg, rr_register);
313     nrf_barrier_r();
314     return check;
315 }
316 
317 /** @refhal{nrf_wdt_reload_request_set} */
nrfy_wdt_reload_request_set(NRF_WDT_Type * p_reg,nrf_wdt_rr_register_t rr_register)318 NRFY_STATIC_INLINE void nrfy_wdt_reload_request_set(NRF_WDT_Type *        p_reg,
319                                                     nrf_wdt_rr_register_t rr_register)
320 {
321     nrf_wdt_reload_request_set(p_reg, rr_register);
322     nrf_barrier_w();
323 }
324 
325 #if NRFY_WDT_HAS_STOP
326 /** @refhal{nrf_wdt_task_stop_enable_set} */
nrfy_wdt_task_stop_enable_set(NRF_WDT_Type * p_reg,bool enable)327 NRFY_STATIC_INLINE void nrfy_wdt_task_stop_enable_set(NRF_WDT_Type * p_reg, bool enable)
328 {
329     nrf_wdt_task_stop_enable_set(p_reg, enable);
330     nrf_barrier_w();
331 }
332 #endif
333 
334 /** @} */
335 
__nrfy_internal_wdt_event_handle(NRF_WDT_Type * p_reg,uint32_t mask,nrf_wdt_event_t event,uint32_t * p_evt_mask)336 NRFY_STATIC_INLINE bool __nrfy_internal_wdt_event_handle(NRF_WDT_Type *  p_reg,
337                                                          uint32_t        mask,
338                                                          nrf_wdt_event_t event,
339                                                          uint32_t *      p_evt_mask)
340 {
341     if ((mask & NRFY_EVENT_TO_INT_BITMASK(event)) && nrf_wdt_event_check(p_reg, event))
342     {
343         nrf_wdt_event_clear(p_reg, event);
344         if (p_evt_mask)
345         {
346             *p_evt_mask |= NRFY_EVENT_TO_INT_BITMASK(event);
347         }
348         return true;
349     }
350     return false;
351 }
352 
__nrfy_internal_wdt_events_process(NRF_WDT_Type * p_reg,uint32_t mask)353 NRFY_STATIC_INLINE uint32_t __nrfy_internal_wdt_events_process(NRF_WDT_Type * p_reg, uint32_t mask)
354 {
355     uint32_t evt_mask = 0;
356 
357     nrf_barrier_r();
358     (void)__nrfy_internal_wdt_event_handle(p_reg, mask, NRF_WDT_EVENT_TIMEOUT, &evt_mask);
359 #if NRFY_WDT_HAS_STOP
360     (void)__nrfy_internal_wdt_event_handle(p_reg, mask, NRF_WDT_EVENT_STOPPED, &evt_mask);
361 #endif
362 
363     return evt_mask;
364 }
365 
__nrfy_internal_wdt_event_enabled_clear(NRF_WDT_Type * p_reg,uint32_t mask,nrf_wdt_event_t event)366 NRFY_STATIC_INLINE void __nrfy_internal_wdt_event_enabled_clear(NRF_WDT_Type *  p_reg,
367                                                                 uint32_t        mask,
368                                                                 nrf_wdt_event_t event)
369 {
370     if (mask & NRFY_EVENT_TO_INT_BITMASK(event))
371     {
372         nrf_wdt_event_clear(p_reg, event);
373     }
374 }
375 
376 #ifdef __cplusplus
377 }
378 #endif
379 
380 #endif // NRFY_WDT_H__
381