1 /*
2  * Copyright (c) 2019 - 2024, 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 NRF_MWU_H__
35 #define NRF_MWU_H__
36 
37 #include <nrfx.h>
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /**
44  * @defgroup nrf_mwu_hal MWU HAL
45  * @{
46  * @ingroup nrf_mwu
47  * @brief   Hardware access layer for managing the Memory Watch Unit (MWU) peripheral.
48  */
49 
50 /** @brief MWU events. */
51 typedef enum
52 {
53     NRF_MWU_EVENT_REGION0_WRITE  = offsetof(NRF_MWU_Type, EVENTS_REGION[0].WA),  ///< Write access to region 0 detected.
54     NRF_MWU_EVENT_REGION0_READ   = offsetof(NRF_MWU_Type, EVENTS_REGION[0].RA),  ///< Read access to region 0 detected.
55     NRF_MWU_EVENT_REGION1_WRITE  = offsetof(NRF_MWU_Type, EVENTS_REGION[1].WA),  ///< Write access to region 1 detected.
56     NRF_MWU_EVENT_REGION1_READ   = offsetof(NRF_MWU_Type, EVENTS_REGION[1].RA),  ///< Read access to region 1 detected.
57     NRF_MWU_EVENT_REGION2_WRITE  = offsetof(NRF_MWU_Type, EVENTS_REGION[2].WA),  ///< Write access to region 2 detected.
58     NRF_MWU_EVENT_REGION2_READ   = offsetof(NRF_MWU_Type, EVENTS_REGION[2].RA),  ///< Read access to region 2 detected.
59     NRF_MWU_EVENT_REGION3_WRITE  = offsetof(NRF_MWU_Type, EVENTS_REGION[3].WA),  ///< Write access to region 3 detected.
60     NRF_MWU_EVENT_REGION3_READ   = offsetof(NRF_MWU_Type, EVENTS_REGION[3].RA),  ///< Read access to region 3 detected.
61     NRF_MWU_EVENT_PREGION0_WRITE = offsetof(NRF_MWU_Type, EVENTS_PREGION[0].WA), ///< Write access to peripheral region 0 detected.
62     NRF_MWU_EVENT_PREGION0_READ  = offsetof(NRF_MWU_Type, EVENTS_PREGION[0].RA), ///< Read access to peripheral region 0 detected.
63     NRF_MWU_EVENT_PREGION1_WRITE = offsetof(NRF_MWU_Type, EVENTS_PREGION[1].WA), ///< Write access to peripheral region 1 detected.
64     NRF_MWU_EVENT_PREGION1_READ  = offsetof(NRF_MWU_Type, EVENTS_PREGION[1].RA), ///< Read access to peripheral region 1 detected.
65 } nrf_mwu_event_t;
66 
67 /** @brief MWU interrupt masks. */
68 typedef enum
69 {
70     NRF_MWU_INT_REGION0_WRITE_MASK  = MWU_INTEN_REGION0WA_Msk,  ///< Interrupt on REGION[0].WA event.
71     NRF_MWU_INT_REGION0_READ_MASK   = MWU_INTEN_REGION0RA_Msk,  ///< Interrupt on REGION[0].RA event.
72     NRF_MWU_INT_REGION1_WRITE_MASK  = MWU_INTEN_REGION1WA_Msk,  ///< Interrupt on REGION[1].WA event.
73     NRF_MWU_INT_REGION1_READ_MASK   = MWU_INTEN_REGION1RA_Msk,  ///< Interrupt on REGION[1].RA event.
74     NRF_MWU_INT_REGION2_WRITE_MASK  = MWU_INTEN_REGION2WA_Msk,  ///< Interrupt on REGION[2].WA event.
75     NRF_MWU_INT_REGION2_READ_MASK   = MWU_INTEN_REGION2RA_Msk,  ///< Interrupt on REGION[2].RA event.
76     NRF_MWU_INT_REGION3_WRITE_MASK  = MWU_INTEN_REGION3WA_Msk,  ///< Interrupt on REGION[3].WA event.
77     NRF_MWU_INT_REGION3_READ_MASK   = MWU_INTEN_REGION3RA_Msk,  ///< Interrupt on REGION[3].RA event.
78     NRF_MWU_INT_PREGION0_WRITE_MASK = MWU_INTEN_PREGION0WA_Msk, ///< Interrupt on PREGION[0].WA event.
79     NRF_MWU_INT_PREGION0_READ_MASK  = MWU_INTEN_PREGION0RA_Msk, ///< Interrupt on PREGION[0].RA event.
80     NRF_MWU_INT_PREGION1_WRITE_MASK = MWU_INTEN_PREGION1WA_Msk, ///< Interrupt on PREGION[1].WA event.
81     NRF_MWU_INT_PREGION1_READ_MASK  = MWU_INTEN_PREGION1RA_Msk, ///< Interrupt on PREGION[1].RA event.
82 } nrf_mwu_int_mask_t;
83 
84 /** @brief MWU region watch masks. */
85 typedef enum
86 {
87     NRF_MWU_WATCH_REGION0_WRITE  = MWU_REGIONEN_RGN0WA_Msk,  ///< Region 0 write access watch mask.
88     NRF_MWU_WATCH_REGION0_READ   = MWU_REGIONEN_RGN0RA_Msk,  ///< Region 0 read access watch mask.
89     NRF_MWU_WATCH_REGION1_WRITE  = MWU_REGIONEN_RGN1WA_Msk,  ///< Region 1 write access watch mask.
90     NRF_MWU_WATCH_REGION1_READ   = MWU_REGIONEN_RGN1RA_Msk,  ///< Region 1 read access watch mask.
91     NRF_MWU_WATCH_REGION2_WRITE  = MWU_REGIONEN_RGN2WA_Msk,  ///< Region 2 write access watch mask.
92     NRF_MWU_WATCH_REGION2_READ   = MWU_REGIONEN_RGN2RA_Msk,  ///< Region 2 read access watch mask.
93     NRF_MWU_WATCH_REGION3_WRITE  = MWU_REGIONEN_RGN3WA_Msk,  ///< Region 3 write access watch mask.
94     NRF_MWU_WATCH_REGION3_READ   = MWU_REGIONEN_RGN3RA_Msk,  ///< Region 3 read access watch mask.
95     NRF_MWU_WATCH_PREGION0_WRITE = MWU_REGIONEN_PRGN0WA_Msk, ///< Peripheral region 0 write access watch mask.
96     NRF_MWU_WATCH_PREGION0_READ  = MWU_REGIONEN_PRGN0RA_Msk, ///< Peripheral region 0 read access watch mask.
97     NRF_MWU_WATCH_PREGION1_WRITE = MWU_REGIONEN_PRGN1WA_Msk, ///< Peripheral region 1 write access watch mask.
98     NRF_MWU_WATCH_PREGION1_READ  = MWU_REGIONEN_PRGN1RA_Msk, ///< Peripheral region 1 read access watch mask.
99 } nrf_mwu_region_watch_t;
100 
101 /**
102  * @brief Function for retrieving the state of the MWU event.
103  *
104  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
105  * @param[in] event Event to be checked.
106  *
107  * @retval true  The event has been generated.
108  * @retval false The event has not been generated.
109  */
110 NRF_STATIC_INLINE bool nrf_mwu_event_check(NRF_MWU_Type const * p_reg,
111                                            nrf_mwu_event_t      event);
112 
113 /**
114  * @brief Function for clearing a specific MWU event.
115  *
116  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
117  * @param[in] event Event to clear.
118  */
119 NRF_STATIC_INLINE void nrf_mwu_event_clear(NRF_MWU_Type *  p_reg,
120                                            nrf_mwu_event_t event);
121 
122 /**
123  * @brief Function for getting the address of a specific MWU event register.
124  *
125  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
126  * @param[in] event Requested event.
127  *
128  * @return Address of the specified event register.
129  */
130 NRF_STATIC_INLINE uint32_t nrf_mwu_event_address_get(NRF_MWU_Type const * p_reg,
131                                                      nrf_mwu_event_t      event);
132 
133 /**
134  * @brief Function for enabling specified interrupts.
135  *
136  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
137  * @param[in] mask  Mask of interrupts to be enabled.
138  *                  Use @ref nrf_mwu_int_mask_t values for bit masking.
139  */
140 NRF_STATIC_INLINE void nrf_mwu_int_enable(NRF_MWU_Type * p_reg, uint32_t mask);
141 
142 /**
143  * @brief Function for checking if the specified interrupts are enabled.
144  *
145  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
146  * @param[in] mask  Mask of interrupts to be checked.
147  *                  Use @ref nrf_mwu_int_mask_t values for bit masking.
148  *
149  * @return Mask of enabled interrupts.
150  */
151 NRF_STATIC_INLINE uint32_t nrf_mwu_int_enable_check(NRF_MWU_Type const * p_reg, uint32_t mask);
152 
153 /**
154  * @brief Function for disabling specified interrupts.
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  *                  Use @ref nrf_mwu_int_mask_t values for bit masking.
159  */
160 NRF_STATIC_INLINE void nrf_mwu_int_disable(NRF_MWU_Type * p_reg, uint32_t mask);
161 
162 /**
163  * @brief Function for enabling specified non-maskable interrupts.
164  *
165  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
166  * @param[in] mask  Mask of interrupts to be enabled.
167  */
168 NRF_STATIC_INLINE void nrf_mwu_nmi_enable(NRF_MWU_Type * p_reg, uint32_t mask);
169 
170 /**
171  * @brief Function for checking if the specified non-maskable interrupts are enabled.
172  *
173  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
174  * @param[in] mask  Mask of interrupts to be checked.
175  *
176  * @return Mask of enabled interrupts.
177  */
178 NRF_STATIC_INLINE uint32_t nrf_mwu_nmi_enable_check(NRF_MWU_Type const * p_reg, uint32_t mask);
179 
180 /**
181  * @brief Function for disabling specified non-maskable interrupts.
182  *
183  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
184  * @param[in] mask  Mask of interrupts to be disabled.
185  */
186 NRF_STATIC_INLINE void nrf_mwu_nmi_disable(NRF_MWU_Type * p_reg, uint32_t mask);
187 
188 /**
189  * @brief Function for setting address range of the specified user region.
190  *
191  * @param[in] p_reg      Pointer to the structure of registers of the peripheral.
192  * @param[in] region_idx Region number to configure.
193  * @param[in] start_addr Memory address defining the beginning of the region.
194  * @param[in] end_addr   Memory address defining the end of the region.
195  */
196 NRF_STATIC_INLINE void nrf_mwu_user_region_range_set(NRF_MWU_Type * p_reg,
197                                                      uint8_t        region_idx,
198                                                      uint32_t       start_addr,
199                                                      uint32_t       end_addr);
200 
201 /**
202  * @brief Function for enabling memory access watch mechanism.
203  *
204  * @param[in] p_reg          Pointer to the structure of registers of the peripheral.
205  * @param[in] reg_watch_mask Mask that defines regions and access types to watch.
206  *                           Compose this mask from @ref nrf_mwu_region_watch_t values.
207  */
208 NRF_STATIC_INLINE void nrf_mwu_region_watch_enable(NRF_MWU_Type * p_reg, uint32_t reg_watch_mask);
209 
210 /**
211  * @brief Function for disabling memory access watch mechanism.
212  *
213  * @param[in] p_reg          Pointer to the structure of registers of the peripheral.
214  * @param[in] reg_watch_mask Mask that defines regions and access types to stop watching.
215  *                           Compose this mask from @ref nrf_mwu_region_watch_t values.
216  */
217 NRF_STATIC_INLINE void nrf_mwu_region_watch_disable(NRF_MWU_Type * p_reg, uint32_t reg_watch_mask);
218 
219 /**
220  * @brief Function for getting memory access watch configuration mask.
221  *
222  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
223  *
224  * @return Mask that defines regions and access types being watched.
225  */
226 NRF_STATIC_INLINE uint32_t nrf_mwu_region_watch_get(NRF_MWU_Type const * p_reg);
227 
228 /**
229  * @brief Function for configuring peripheral subregions for watching.
230  *
231  * @param[in] p_reg          Pointer to the structure of registers of the peripheral.
232  * @param[in] per_reg_idx    Peripheral region containing specified subregions.
233  * @param[in] subregion_mask Mask that defines subregions to include into the specified peripheral region.
234  */
235 NRF_STATIC_INLINE void nrf_mwu_subregions_configure(NRF_MWU_Type * p_reg,
236                                                     uint8_t        per_reg_idx,
237                                                     uint32_t       subregion_mask);
238 
239 /**
240  * @brief Function for getting the mask of the write access flags of peripheral subregions
241  *
242  * @param[in] p_reg       Pointer to the structure of registers of the peripheral.
243  * @param[in] per_reg_idx Peripheral region containing subregions to be checked.
244  *
245  * @return Mask specifying subregions that were write accessed.
246  */
247 NRF_STATIC_INLINE uint32_t nrf_mwu_subregions_write_accesses_get(NRF_MWU_Type const * p_reg,
248                                                                  uint8_t              per_reg_idx);
249 
250 /**
251  * @brief Function for clearing write access flags of peripheral subregions.
252  *
253  * @param[in] p_reg          Pointer to the structure of registers of the peripheral.
254  * @param[in] per_reg_idx    Peripheral region containing subregion accesses to clear.
255  * @param[in] subregion_mask Mask that defines subregion write accesses to clear.
256  */
257 NRF_STATIC_INLINE void nrf_mwu_subregions_write_accesses_clear(NRF_MWU_Type * p_reg,
258                                                                uint8_t        per_reg_idx,
259                                                                uint32_t       subregion_mask);
260 
261 /**
262  * @brief Function for getting the mask of the read access flags of peripheral subregions
263  *
264  * @param[in] p_reg       Pointer to the structure of registers of the peripheral.
265  * @param[in] per_reg_idx Peripheral region containing subregions to be checked.
266  *
267  * @return Mask specifying subregions that were read accessed.
268  */
269 NRF_STATIC_INLINE uint32_t nrf_mwu_subregions_read_accesses_get(NRF_MWU_Type const * p_reg,
270                                                                 uint8_t              per_reg_idx);
271 
272 /**
273  * @brief Function for clearing read access flags of peripheral subregions.
274  *
275  * @param[in] p_reg          Pointer to the structure of registers of the peripheral.
276  * @param[in] per_reg_idx    Peripheral region containing subregion accesses to clear.
277  * @param[in] subregion_mask Mask that defines subregion read accesses to clear.
278  */
279 NRF_STATIC_INLINE void nrf_mwu_subregions_read_accesses_clear(NRF_MWU_Type * p_reg,
280                                                               uint8_t        per_reg_idx,
281                                                               uint32_t       subregion_mask);
282 
283 #ifndef NRF_DECLARE_ONLY
284 
nrf_mwu_event_check(NRF_MWU_Type const * p_reg,nrf_mwu_event_t event)285 NRF_STATIC_INLINE bool nrf_mwu_event_check(NRF_MWU_Type const * p_reg,
286                                            nrf_mwu_event_t      event)
287 {
288     return nrf_event_check(p_reg, event);
289 }
290 
nrf_mwu_event_clear(NRF_MWU_Type * p_reg,nrf_mwu_event_t event)291 NRF_STATIC_INLINE void nrf_mwu_event_clear(NRF_MWU_Type *  p_reg,
292                                            nrf_mwu_event_t event)
293 {
294     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0;
295     nrf_event_readback((uint8_t *)p_reg + (uint32_t)event);
296 }
297 
nrf_mwu_event_address_get(NRF_MWU_Type const * p_reg,nrf_mwu_event_t event)298 NRF_STATIC_INLINE uint32_t nrf_mwu_event_address_get(NRF_MWU_Type const * p_reg,
299                                                      nrf_mwu_event_t      event)
300 {
301     return nrf_task_event_address_get(p_reg, event);
302 }
303 
nrf_mwu_int_enable(NRF_MWU_Type * p_reg,uint32_t mask)304 NRF_STATIC_INLINE void nrf_mwu_int_enable(NRF_MWU_Type * p_reg, uint32_t mask)
305 {
306     p_reg->INTENSET = mask;
307 }
308 
nrf_mwu_int_enable_check(NRF_MWU_Type const * p_reg,uint32_t mask)309 NRF_STATIC_INLINE uint32_t nrf_mwu_int_enable_check(NRF_MWU_Type const * p_reg, uint32_t mask)
310 {
311     return p_reg->INTENSET & mask;
312 }
313 
nrf_mwu_int_disable(NRF_MWU_Type * p_reg,uint32_t mask)314 NRF_STATIC_INLINE void nrf_mwu_int_disable(NRF_MWU_Type * p_reg, uint32_t mask)
315 {
316     p_reg->INTENCLR = mask;
317 }
318 
nrf_mwu_nmi_enable(NRF_MWU_Type * p_reg,uint32_t mask)319 NRF_STATIC_INLINE void nrf_mwu_nmi_enable(NRF_MWU_Type * p_reg, uint32_t mask)
320 {
321     p_reg->NMIENSET = mask;
322 }
323 
nrf_mwu_nmi_enable_check(NRF_MWU_Type const * p_reg,uint32_t mask)324 NRF_STATIC_INLINE uint32_t nrf_mwu_nmi_enable_check(NRF_MWU_Type const * p_reg, uint32_t mask)
325 {
326     return p_reg->NMIENSET & mask;
327 }
328 
nrf_mwu_nmi_disable(NRF_MWU_Type * p_reg,uint32_t mask)329 NRF_STATIC_INLINE void nrf_mwu_nmi_disable(NRF_MWU_Type * p_reg, uint32_t mask)
330 {
331     p_reg->NMIENCLR = mask;
332 }
333 
nrf_mwu_user_region_range_set(NRF_MWU_Type * p_reg,uint8_t region_idx,uint32_t start_addr,uint32_t end_addr)334 NRF_STATIC_INLINE void nrf_mwu_user_region_range_set(NRF_MWU_Type * p_reg,
335                                                      uint8_t        region_idx,
336                                                      uint32_t       start_addr,
337                                                      uint32_t       end_addr)
338 {
339     NRFX_ASSERT(end_addr >= start_addr);
340 
341     p_reg->REGION[region_idx].START = start_addr;
342     p_reg->REGION[region_idx].END = end_addr;
343 }
344 
nrf_mwu_region_watch_enable(NRF_MWU_Type * p_reg,uint32_t reg_watch_mask)345 NRF_STATIC_INLINE void nrf_mwu_region_watch_enable(NRF_MWU_Type * p_reg, uint32_t reg_watch_mask)
346 {
347     p_reg->REGIONENSET = reg_watch_mask;
348 }
349 
nrf_mwu_region_watch_disable(NRF_MWU_Type * p_reg,uint32_t reg_watch_mask)350 NRF_STATIC_INLINE void nrf_mwu_region_watch_disable(NRF_MWU_Type * p_reg, uint32_t reg_watch_mask)
351 {
352     p_reg->REGIONENCLR = reg_watch_mask;
353 }
354 
nrf_mwu_region_watch_get(NRF_MWU_Type const * p_reg)355 NRF_STATIC_INLINE uint32_t nrf_mwu_region_watch_get(NRF_MWU_Type const * p_reg)
356 {
357     return p_reg->REGIONENSET;
358 }
359 
nrf_mwu_subregions_configure(NRF_MWU_Type * p_reg,uint8_t per_reg_idx,uint32_t subregion_mask)360 NRF_STATIC_INLINE void nrf_mwu_subregions_configure(NRF_MWU_Type * p_reg,
361                                                     uint8_t        per_reg_idx,
362                                                     uint32_t       subregion_mask)
363 {
364     p_reg->PREGION[per_reg_idx].SUBS = subregion_mask;
365 }
366 
nrf_mwu_subregions_write_accesses_get(NRF_MWU_Type const * p_reg,uint8_t per_reg_idx)367 NRF_STATIC_INLINE uint32_t nrf_mwu_subregions_write_accesses_get(NRF_MWU_Type const * p_reg,
368                                                                  uint8_t              per_reg_idx)
369 {
370     return p_reg->PERREGION[per_reg_idx].SUBSTATWA;
371 }
372 
nrf_mwu_subregions_write_accesses_clear(NRF_MWU_Type * p_reg,uint8_t per_reg_idx,uint32_t subregion_mask)373 NRF_STATIC_INLINE void nrf_mwu_subregions_write_accesses_clear(NRF_MWU_Type * p_reg,
374                                                                uint8_t        per_reg_idx,
375                                                                uint32_t       subregion_mask)
376 {
377     p_reg->PERREGION[per_reg_idx].SUBSTATWA = subregion_mask;
378 }
379 
nrf_mwu_subregions_read_accesses_get(NRF_MWU_Type const * p_reg,uint8_t per_reg_idx)380 NRF_STATIC_INLINE uint32_t nrf_mwu_subregions_read_accesses_get(NRF_MWU_Type const * p_reg,
381                                                                 uint8_t              per_reg_idx)
382 {
383     return p_reg->PERREGION[per_reg_idx].SUBSTATRA;
384 }
385 
nrf_mwu_subregions_read_accesses_clear(NRF_MWU_Type * p_reg,uint8_t per_reg_idx,uint32_t subregion_mask)386 NRF_STATIC_INLINE void nrf_mwu_subregions_read_accesses_clear(NRF_MWU_Type * p_reg,
387                                                               uint8_t        per_reg_idx,
388                                                               uint32_t       subregion_mask)
389 {
390     p_reg->PERREGION[per_reg_idx].SUBSTATRA = subregion_mask;
391 }
392 
393 #endif // NRF_DECLARE_ONLY
394 
395 /** @} */
396 
397 #ifdef __cplusplus
398 }
399 #endif
400 
401 #endif // NRF_MWU_H__
402