1 /*
2  * Copyright (c) 2021 - 2025, 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_TWIM_H__
35 #define NRFY_TWIM_H__
36 
37 #include <nrfx.h>
38 #include <nrf_erratas.h>
39 #include <hal/nrf_twim.h>
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 typedef struct nrfy_twim_xfer_desc_t nrfy_twim_xfer_desc_t;
46 
47 NRFY_STATIC_INLINE void __nrfy_internal_twim_event_enabled_clear(NRF_TWIM_Type *  p_reg,
48                                                                  uint32_t         mask,
49                                                                  nrf_twim_event_t event);
50 
51 NRFY_STATIC_INLINE bool __nrfy_internal_twim_event_handle(NRF_TWIM_Type *  p_reg,
52                                                           uint32_t         mask,
53                                                           nrf_twim_event_t event,
54                                                           uint32_t *       p_evt_mask);
55 
56 NRFY_STATIC_INLINE
57 uint32_t __nrfy_internal_twim_events_process(NRF_TWIM_Type *               p_reg,
58                                              uint32_t                      mask,
59                                              nrfy_twim_xfer_desc_t const * p_xfer);
60 
61 /**
62  * @defgroup nrfy_twim TWIM HALY
63  * @{
64  * @ingroup nrf_twim
65  * @brief   Hardware access layer with cache and barrier support for managing the TWIM peripheral.
66  */
67 
68 #if NRF_TWIM_HAS_ARRAY_LIST || defined(__NRFX_DOXYGEN__)
69 /** @refhal{NRF_TWIM_HAS_ARRAY_LIST} */
70 #define NRFY_TWIM_HAS_ARRAY_LIST 1
71 #else
72 #define NRFY_TWIM_HAS_ARRAY_LIST 0
73 #endif
74 
75 /** @brief TWIM pins configuration structure. */
76 typedef struct
77 {
78     uint32_t scl_pin; ///< SCL pin number.
79     uint32_t sda_pin; ///< SDA pin number.
80 } nrfy_twim_pins_t;
81 
82 /** @brief TWIM configuration structure. */
83 typedef struct
84 {
85     nrfy_twim_pins_t     pins;          ///< TWIM pins configuation.
86     nrf_twim_frequency_t frequency;     ///< TWIM frequency.
87     bool                 skip_psel_cfg; ///< Skip pin selection configuration.
88                                         /**< When set to true, the driver does not modify
89                                          *   pin select registers in the peripheral.
90                                          *   Those registers are supposed to be set up
91                                          *   externally before the driver is initialized.
92                                          *   @note When both GPIO configuration and pin
93                                          *   selection are to be skipped, the structure
94                                          *   fields that specify pins can be omitted,
95                                          *   as they are ignored anyway. */
96 } nrfy_twim_config_t;
97 
98 /** @brief Structure describing a TWIM transfer. */
99 struct nrfy_twim_xfer_desc_t
100 {
101     uint8_t * p_buffer; ///< Pointer to transferred data.
102     size_t    length;   ///< Number of bytes transferred.
103 };
104 
105 /**
106  * @brief Function for configuring the TWIM.
107  *
108  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
109  * @param[in] p_config Pointer to the peripheral configuration structure.
110  */
nrfy_twim_periph_configure(NRF_TWIM_Type * p_reg,nrfy_twim_config_t const * p_config)111 NRFY_STATIC_INLINE void nrfy_twim_periph_configure(NRF_TWIM_Type *            p_reg,
112                                                    nrfy_twim_config_t const * p_config)
113 {
114     if (!p_config->skip_psel_cfg)
115     {
116         nrf_twim_pins_set(p_reg, p_config->pins.scl_pin, p_config->pins.sda_pin);
117     }
118     nrf_twim_frequency_set(p_reg, p_config->frequency);
119     nrf_barrier_w();
120 }
121 
122 /**
123  * @brief Function for initializing the specified TWIM interrupts.
124  *
125  * @param[in] p_reg        Pointer to the structure of registers of the peripheral.
126  * @param[in] mask         Mask of interrupts to be initialized.
127  * @param[in] irq_priority Interrupt priority.
128  * @param[in] enable       True if interrupts associated with the event mask are to be enabled, false otherwise.
129  */
nrfy_twim_int_init(NRF_TWIM_Type * p_reg,uint32_t mask,uint8_t irq_priority,bool enable)130 NRFY_STATIC_INLINE void nrfy_twim_int_init(NRF_TWIM_Type * p_reg,
131                                            uint32_t        mask,
132                                            uint8_t         irq_priority,
133                                            bool            enable)
134 {
135     __nrfy_internal_twim_event_enabled_clear(p_reg, mask, NRF_TWIM_EVENT_TXSTARTED);
136     __nrfy_internal_twim_event_enabled_clear(p_reg, mask, NRF_TWIM_EVENT_RXSTARTED);
137     __nrfy_internal_twim_event_enabled_clear(p_reg, mask, NRF_TWIM_EVENT_LASTTX);
138     __nrfy_internal_twim_event_enabled_clear(p_reg, mask, NRF_TWIM_EVENT_LASTRX);
139     __nrfy_internal_twim_event_enabled_clear(p_reg, mask, NRF_TWIM_EVENT_STOPPED);
140     __nrfy_internal_twim_event_enabled_clear(p_reg, mask, NRF_TWIM_EVENT_SUSPENDED);
141     __nrfy_internal_twim_event_enabled_clear(p_reg, mask, NRF_TWIM_EVENT_ERROR);
142     nrf_barrier_w();
143 
144     NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_reg), irq_priority);
145     NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_reg));
146     if (enable)
147     {
148         nrf_twim_int_enable(p_reg, mask);
149     }
150     nrf_barrier_w();
151 }
152 
153 /**
154  * @brief Function for uninitializing the TWIM interrupts.
155  *
156  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
157  */
nrfy_twim_int_uninit(NRF_TWIM_Type * p_reg)158 NRFY_STATIC_INLINE void nrfy_twim_int_uninit(NRF_TWIM_Type * p_reg)
159 {
160     NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_reg));
161     nrf_barrier_w();
162 }
163 
164 /**
165  * @brief Function for processing the specified TWIM events.
166  *
167  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
168  * @param[in] mask   Mask of events to be processed, created by @ref NRFY_EVENT_TO_INT_BITMASK();
169  * @param[in] p_xfer Pointer to the structure containing buffer associated with the last reception.
170  *                   Can be NULL.
171  *
172  * @return Mask of events that were generated and processed.
173  *         To be checked against the result of @ref NRFY_EVENT_TO_INT_BITMASK().
174  */
nrfy_twim_events_process(NRF_TWIM_Type * p_reg,uint32_t mask,nrfy_twim_xfer_desc_t const * p_xfer)175 NRFY_STATIC_INLINE uint32_t nrfy_twim_events_process(NRF_TWIM_Type *               p_reg,
176                                                      uint32_t                      mask,
177                                                      nrfy_twim_xfer_desc_t const * p_xfer)
178 {
179     uint32_t evt_mask = __nrfy_internal_twim_events_process(p_reg, mask, p_xfer);
180     nrf_barrier_w();
181     return evt_mask;
182 }
183 
184 /**
185  * @brief Function for setting the TWIM transaction buffer.
186  *
187  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
188  * @param[in] p_xfer Pointer to the structure containing transaction buffer.
189  */
nrfy_twim_tx_buffer_set(NRF_TWIM_Type * p_reg,nrfy_twim_xfer_desc_t const * p_xfer)190 NRFY_STATIC_INLINE void nrfy_twim_tx_buffer_set(NRF_TWIM_Type *               p_reg,
191                                                 nrfy_twim_xfer_desc_t const * p_xfer)
192 {
193     if (p_xfer->p_buffer)
194     {
195         NRFY_CACHE_WB(p_xfer->p_buffer, p_xfer->length);
196     }
197     nrf_twim_tx_buffer_set(p_reg, p_xfer->p_buffer, p_xfer->length);
198     nrf_barrier_w();
199 }
200 
201 /**
202  * @brief Function for setting the TWIM reception buffer.
203  *
204  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
205  * @param[in] p_xfer Pointer to the structure containing reception buffer.
206  */
nrfy_twim_rx_buffer_set(NRF_TWIM_Type * p_reg,nrfy_twim_xfer_desc_t const * p_xfer)207 NRFY_STATIC_INLINE void nrfy_twim_rx_buffer_set(NRF_TWIM_Type *               p_reg,
208                                                 nrfy_twim_xfer_desc_t const * p_xfer)
209 {
210     nrf_twim_rx_buffer_set(p_reg, p_xfer->p_buffer, p_xfer->length);
211     nrf_barrier_w();
212 }
213 
214 /**
215  * @brief Function for starting TWIM transaction.
216  *
217  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
218  * @param[in] p_xfer Pointer to the structure containing transaction buffer.
219  */
nrfy_twim_tx_start(NRF_TWIM_Type * p_reg,nrfy_twim_xfer_desc_t const * p_xfer)220 NRFY_STATIC_INLINE void nrfy_twim_tx_start(NRF_TWIM_Type *               p_reg,
221                                            nrfy_twim_xfer_desc_t const * p_xfer)
222 {
223     nrf_twim_task_trigger(p_reg, NRF_TWIM_TASK_STARTTX);
224     if (p_xfer)
225     {
226         if (p_xfer->length == 0)
227         {
228             nrf_twim_task_trigger(p_reg, NRF_TWIM_TASK_STOP);
229         }
230         nrf_barrier_w();
231         uint32_t mask = NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_SUSPENDED) |
232                         NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_STOPPED) |
233                         NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_ERROR);
234         uint32_t evt_mask = 0;
235         while (!(evt_mask & (NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_SUSPENDED) |
236                              NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_STOPPED))))
237         {
238             evt_mask = __nrfy_internal_twim_events_process(p_reg, mask, p_xfer);
239             if (evt_mask & NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_ERROR))
240             {
241                 bool lasttx_triggered = __nrfy_internal_twim_events_process(p_reg,
242                                                 NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_LASTTX),
243                                                 NULL);
244                 nrf_barrier_rw();
245                 uint32_t shorts_mask = nrf_twim_shorts_get(p_reg);
246                 nrf_barrier_r();
247 
248                 if (!(lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_STOP_MASK)))
249                 {
250                     // Unless LASTTX event arrived and LASTTX_STOP shortcut is active,
251                     // triggering of STOP task in case of error has to be done manually.
252                     nrf_twim_task_trigger(p_reg, NRF_TWIM_TASK_RESUME);
253                     nrf_twim_task_trigger(p_reg, NRF_TWIM_TASK_STOP);
254                     nrf_barrier_w();
255 
256                     // Mark transmission as not finished yet,
257                     // as STOPPED event is expected to arrive.
258                     // If LASTTX_SUSPENDED shortcut is active,
259                     // NACK has been received on last byte sent
260                     // and SUSPENDED event happened to be checked before ERROR,
261                     // transmission will be marked as finished.
262                     // In such case this flag has to be overwritten.
263                     evt_mask = 0;
264                 }
265 
266                 if (lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK))
267                 {
268                     // When STOP task was triggered just before SUSPEND task has taken effect,
269                     // SUSPENDED event may not arrive.
270                     // However if SUSPENDED arrives it always arrives after ERROR.
271                     // Therefore SUSPENDED has to be cleared
272                     // so it does not cause premature termination of busy loop
273                     // waiting for STOPPED event to arrive.
274                     (void)__nrfy_internal_twim_events_process(p_reg,
275                                             NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_SUSPENDED),
276                                             p_xfer);
277                     // Mark transmission as not finished yet,
278                     // for same reasons as above.
279                     evt_mask = 0;
280                 }
281             }
282         }
283     }
284     nrf_barrier_w();
285 }
286 
287 /**
288  * @brief Function for starting TWIM reception.
289  *
290  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
291  * @param[in] p_xfer Pointer to the structure containing reception buffer.
292  */
nrfy_twim_rx_start(NRF_TWIM_Type * p_reg,nrfy_twim_xfer_desc_t const * p_xfer)293 NRFY_STATIC_INLINE void nrfy_twim_rx_start(NRF_TWIM_Type *               p_reg,
294                                            nrfy_twim_xfer_desc_t const * p_xfer)
295 {
296     nrf_twim_task_trigger(p_reg, NRF_TWIM_TASK_STARTRX);
297     if (p_xfer)
298     {
299         if (p_xfer->length == 0)
300         {
301             nrf_twim_task_trigger(p_reg, NRF_TWIM_TASK_STOP);
302         }
303 
304         nrf_barrier_w();
305         uint32_t mask = NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_SUSPENDED) |
306                         NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_STOPPED) |
307                         NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_ERROR);
308         uint32_t evt_mask = 0;
309         while (!(evt_mask & (NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_SUSPENDED) |
310                              NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_STOPPED))))
311         {
312             evt_mask = __nrfy_internal_twim_events_process(p_reg, mask, p_xfer);
313             if (evt_mask & NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_ERROR))
314             {
315                 // triggering of STOP task in case of error has to be done manually.
316                 nrf_twim_task_trigger(p_reg, NRF_TWIM_TASK_STOP);
317                 nrf_barrier_w();
318             }
319         }
320     }
321     nrf_barrier_w();
322 }
323 
324 /**
325  * @brief Function for aborting the ongoing TWIM transaction.
326  *
327  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
328  * @param[in] p_xfer Pointer to the structure containing reception buffer
329  *                   if the abort is to be blocking. NULL for non-blocking operation.
330  */
nrfy_twim_abort(NRF_TWIM_Type * p_reg,nrfy_twim_xfer_desc_t const * p_xfer)331 NRFY_STATIC_INLINE void nrfy_twim_abort(NRF_TWIM_Type * p_reg, nrfy_twim_xfer_desc_t const * p_xfer)
332 {
333     nrf_twim_task_trigger(p_reg, NRF_TWIM_TASK_STOP);
334     if (p_xfer)
335     {
336         nrf_barrier_w();
337         uint32_t evt_mask = NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_STOPPED);
338         while (!__nrfy_internal_twim_events_process(p_reg, evt_mask, p_xfer))
339         {}
340     }
341     nrf_barrier_w();
342 }
343 
344 /**
345  * @brief Function for getting TWIM pins configuration.
346  *
347  * @param[in]  p_reg  Pointer to the structure of registers of the peripheral.
348  * @param[out] p_pins Pointer to the structure to be filled with TWIM pins configuration.
349  */
nrfy_twim_pins_get(NRF_TWIM_Type const * p_reg,nrfy_twim_pins_t * p_pins)350 NRFY_STATIC_INLINE void nrfy_twim_pins_get(NRF_TWIM_Type const * p_reg,
351                                            nrfy_twim_pins_t *    p_pins)
352 {
353     nrf_barrier_rw();
354     p_pins->scl_pin = nrf_twim_scl_pin_get(p_reg);
355     p_pins->sda_pin = nrf_twim_sda_pin_get(p_reg);
356     nrf_barrier_r();
357 }
358 
359 /**
360  * @brief Function for disabling TWIM with all interrupts and shortcuts.
361  *
362  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
363  */
nrfy_twim_stop(NRF_TWIM_Type * p_reg)364 NRFY_STATIC_INLINE void nrfy_twim_stop(NRF_TWIM_Type * p_reg)
365 {
366     nrf_twim_int_disable(p_reg, NRF_TWIM_ALL_INTS_MASK);
367     nrf_twim_shorts_disable(p_reg, NRF_TWIM_ALL_SHORTS_MASK);
368 #if NRF52_ERRATA_89_ENABLE_WORKAROUND
369     if (nrf52_errata_89())
370     {
371         *(volatile uint32_t *)((uint8_t *)p_reg + 0x500UL) = 9;
372     }
373 #endif
374     nrf_twim_disable(p_reg);
375     nrf_barrier_w();
376 }
377 
378 #if NRFY_TWIM_HAS_ARRAY_LIST
379 /**
380  * @brief Function for enabling or disabling the TX list feature.
381  *
382  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
383  * @param[in] enable True if TX list feature is to be enabled, false otherwise.
384  */
nrfy_twim_tx_list_set(NRF_TWIM_Type * p_reg,bool enable)385 NRFY_STATIC_INLINE void nrfy_twim_tx_list_set(NRF_TWIM_Type * p_reg, bool enable)
386 {
387     if (enable)
388     {
389         nrf_twim_tx_list_enable(p_reg);
390     }
391     else
392     {
393         nrf_twim_tx_list_disable(p_reg);
394     }
395     nrf_barrier_w();
396 }
397 
398 /**
399  * @brief Function for enabling or disabling the RX list feature.
400  *
401  * @param[in] p_reg  Pointer to the structure of registers of the peripheral.
402  * @param[in] enable True if RX list feature is to be enabled, false otherwise.
403  */
nrfy_twim_rx_list_set(NRF_TWIM_Type * p_reg,bool enable)404 NRFY_STATIC_INLINE void nrfy_twim_rx_list_set(NRF_TWIM_Type * p_reg, bool enable)
405 {
406     if (enable)
407     {
408         nrf_twim_rx_list_enable(p_reg);
409     }
410     else
411     {
412         nrf_twim_rx_list_disable(p_reg);
413     }
414     nrf_barrier_w();
415 }
416 #endif
417 
418 /**
419  * @brief Function for setting the TWIM pins configuration.
420  *
421  * @param[in]  p_reg  Pointer to the structure of registers of the peripheral.
422  * @param[out] p_pins Pointer to the TWIM pin configurartion structure.
423  */
nrfy_twim_pins_set(NRF_TWIM_Type * p_reg,nrfy_twim_pins_t const * p_pins)424 NRFY_STATIC_INLINE void nrfy_twim_pins_set(NRF_TWIM_Type *          p_reg,
425                                            nrfy_twim_pins_t const * p_pins)
426 {
427     nrf_twim_pins_set(p_reg, p_pins->scl_pin, p_pins->sda_pin);
428     nrf_barrier_w();
429 }
430 
431 /** @refhal{nrf_twim_task_trigger} */
nrfy_twim_task_trigger(NRF_TWIM_Type * p_reg,nrf_twim_task_t task)432 NRFY_STATIC_INLINE void nrfy_twim_task_trigger(NRF_TWIM_Type * p_reg,
433                                                nrf_twim_task_t task)
434 {
435     nrf_twim_task_trigger(p_reg, task);
436     nrf_barrier_w();
437 }
438 
439 /** @refhal{nrf_twim_task_address_get} */
nrfy_twim_task_address_get(NRF_TWIM_Type const * p_reg,nrf_twim_task_t task)440 NRFY_STATIC_INLINE uint32_t nrfy_twim_task_address_get(NRF_TWIM_Type const * p_reg,
441                                                        nrf_twim_task_t       task)
442 {
443     return nrf_twim_task_address_get(p_reg, task);
444 }
445 
446 /** @refhal{nrf_twim_event_clear} */
nrfy_twim_event_clear(NRF_TWIM_Type * p_reg,nrf_twim_event_t event)447 NRFY_STATIC_INLINE void nrfy_twim_event_clear(NRF_TWIM_Type *  p_reg,
448                                               nrf_twim_event_t event)
449 {
450     nrf_twim_event_clear(p_reg, event);
451     nrf_barrier_w();
452 }
453 
454 /** @refhal{nrf_twim_event_check} */
nrfy_twim_event_check(NRF_TWIM_Type const * p_reg,nrf_twim_event_t event)455 NRFY_STATIC_INLINE bool nrfy_twim_event_check(NRF_TWIM_Type const * p_reg,
456                                               nrf_twim_event_t      event)
457 {
458     nrf_barrier_r();
459     bool check = nrf_twim_event_check(p_reg, event);
460     nrf_barrier_r();
461     return check;
462 }
463 
464 /** @refhal{nrf_twim_event_address_get} */
nrfy_twim_event_address_get(NRF_TWIM_Type const * p_reg,nrf_twim_event_t event)465 NRFY_STATIC_INLINE uint32_t nrfy_twim_event_address_get(NRF_TWIM_Type const * p_reg,
466                                                         nrf_twim_event_t      event)
467 {
468     return nrf_twim_event_address_get(p_reg, event);
469 }
470 
471 /** @refhal{nrf_twim_shorts_enable} */
nrfy_twim_shorts_enable(NRF_TWIM_Type * p_reg,uint32_t mask)472 NRFY_STATIC_INLINE void nrfy_twim_shorts_enable(NRF_TWIM_Type * p_reg,
473                                                 uint32_t        mask)
474 {
475     nrf_twim_shorts_enable(p_reg, mask);
476     nrf_barrier_w();
477 }
478 
479 /** @refhal{nrf_twim_shorts_disable} */
nrfy_twim_shorts_disable(NRF_TWIM_Type * p_reg,uint32_t mask)480 NRFY_STATIC_INLINE void nrfy_twim_shorts_disable(NRF_TWIM_Type * p_reg,
481                                                  uint32_t        mask)
482 {
483     nrf_twim_shorts_disable(p_reg, mask);
484     nrf_barrier_w();
485 }
486 
487 /** @refhal{nrf_twim_int_enable} */
nrfy_twim_int_enable(NRF_TWIM_Type * p_reg,uint32_t mask)488 NRFY_STATIC_INLINE void nrfy_twim_int_enable(NRF_TWIM_Type * p_reg,
489                                              uint32_t        mask)
490 {
491     nrf_twim_int_enable(p_reg, mask);
492     nrf_barrier_w();
493 }
494 
495 /** @refhal{nrf_twim_int_disable} */
nrfy_twim_int_disable(NRF_TWIM_Type * p_reg,uint32_t mask)496 NRFY_STATIC_INLINE void nrfy_twim_int_disable(NRF_TWIM_Type * p_reg,
497                                               uint32_t        mask)
498 {
499     nrf_twim_int_disable(p_reg, mask);
500     nrf_barrier_w();
501 }
502 
503 /** @refhal{nrf_twim_int_enable_check} */
nrfy_twim_int_enable_check(NRF_TWIM_Type const * p_reg,uint32_t mask)504 NRFY_STATIC_INLINE uint32_t nrfy_twim_int_enable_check(NRF_TWIM_Type const * p_reg, uint32_t mask)
505 {
506     nrf_barrier_rw();
507     uint32_t check = nrf_twim_int_enable_check(p_reg, mask);
508     nrf_barrier_r();
509     return check;
510 }
511 
512 #if defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
513 /** @refhal{nrf_twim_subscribe_set} */
nrfy_twim_subscribe_set(NRF_TWIM_Type * p_reg,nrf_twim_task_t task,uint8_t channel)514 NRFY_STATIC_INLINE void nrfy_twim_subscribe_set(NRF_TWIM_Type * p_reg,
515                                                 nrf_twim_task_t task,
516                                                 uint8_t         channel)
517 {
518     nrf_twim_subscribe_set(p_reg, task, channel);
519     nrf_barrier_w();
520 }
521 
522 /** @refhal{nrf_twim_subscribe_clear} */
nrfy_twim_subscribe_clear(NRF_TWIM_Type * p_reg,nrf_twim_task_t task)523 NRFY_STATIC_INLINE void nrfy_twim_subscribe_clear(NRF_TWIM_Type * p_reg,
524                                                   nrf_twim_task_t task)
525 {
526     nrf_twim_subscribe_clear(p_reg, task);
527     nrf_barrier_w();
528 
529 }
530 
531 /** @refhal{nrf_twim_publish_set} */
nrfy_twim_publish_set(NRF_TWIM_Type * p_reg,nrf_twim_event_t event,uint8_t channel)532 NRFY_STATIC_INLINE void nrfy_twim_publish_set(NRF_TWIM_Type *  p_reg,
533                                               nrf_twim_event_t event,
534                                               uint8_t          channel)
535 {
536     nrf_twim_publish_set(p_reg, event, channel);
537     nrf_barrier_w();
538 }
539 
540 /** @refhal{nrf_twim_publish_clear} */
nrfy_twim_publish_clear(NRF_TWIM_Type * p_reg,nrf_twim_event_t event)541 NRFY_STATIC_INLINE void nrfy_twim_publish_clear(NRF_TWIM_Type *  p_reg,
542                                                 nrf_twim_event_t event)
543 {
544     nrf_twim_publish_clear(p_reg, event);
545     nrf_barrier_w();
546 }
547 #endif // defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
548 
549 /** @refhal{nrf_twim_enable} */
nrfy_twim_enable(NRF_TWIM_Type * p_reg)550 NRFY_STATIC_INLINE void nrfy_twim_enable(NRF_TWIM_Type * p_reg)
551 {
552     nrf_twim_enable(p_reg);
553     nrf_barrier_w();
554 }
555 
556 /** @refhal{nrf_twim_disable} */
nrfy_twim_disable(NRF_TWIM_Type * p_reg)557 NRFY_STATIC_INLINE void nrfy_twim_disable(NRF_TWIM_Type * p_reg)
558 {
559     nrf_twim_disable(p_reg);
560     nrf_barrier_w();
561 }
562 
563 /** @refhal{nrf_twim_scl_pin_get} */
nrfy_twim_scl_pin_get(NRF_TWIM_Type const * p_reg)564 NRFY_STATIC_INLINE uint32_t nrfy_twim_scl_pin_get(NRF_TWIM_Type const * p_reg)
565 {
566     nrf_barrier_rw();
567     uint32_t scl_pin = nrf_twim_scl_pin_get(p_reg);
568     nrf_barrier_r();
569     return scl_pin;
570 }
571 
572 /** @refhal{nrf_twim_sda_pin_get} */
nrfy_twim_sda_pin_get(NRF_TWIM_Type const * p_reg)573 NRFY_STATIC_INLINE uint32_t nrfy_twim_sda_pin_get(NRF_TWIM_Type const * p_reg)
574 {
575     nrf_barrier_rw();
576     uint32_t sda_pin = nrf_twim_sda_pin_get(p_reg);
577     nrf_barrier_r();
578     return sda_pin;
579 }
580 
581 /** @refhal{nrf_twim_frequency_set} */
nrfy_twim_frequency_set(NRF_TWIM_Type * p_reg,nrf_twim_frequency_t frequency)582 NRFY_STATIC_INLINE void nrfy_twim_frequency_set(NRF_TWIM_Type *      p_reg,
583                                                 nrf_twim_frequency_t frequency)
584 {
585     nrf_twim_frequency_set(p_reg, frequency);
586     nrf_barrier_w();
587 }
588 
589 /** @refhal{nrf_twim_errorsrc_get_and_clear} */
nrfy_twim_errorsrc_get_and_clear(NRF_TWIM_Type * p_reg)590 NRFY_STATIC_INLINE uint32_t nrfy_twim_errorsrc_get_and_clear(NRF_TWIM_Type * p_reg)
591 {
592     nrf_barrier_rw();
593     uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_reg);
594     nrf_barrier_rw();
595     return errorsrc;
596 }
597 
598 /** @refhal{nrf_twim_address_set} */
nrfy_twim_address_set(NRF_TWIM_Type * p_reg,uint8_t address)599 NRFY_STATIC_INLINE void nrfy_twim_address_set(NRF_TWIM_Type * p_reg,
600                                               uint8_t         address)
601 {
602     nrf_twim_address_set(p_reg, address);
603     nrf_barrier_w();
604 }
605 
606 /** @refhal{nrf_twim_shorts_set} */
nrfy_twim_shorts_set(NRF_TWIM_Type * p_reg,uint32_t mask)607 NRFY_STATIC_INLINE void nrfy_twim_shorts_set(NRF_TWIM_Type * p_reg,
608                                              uint32_t        mask)
609 {
610     nrf_twim_shorts_set(p_reg, mask);
611     nrf_barrier_w();
612 }
613 
614 /** @refhal{nrf_twim_shorts_get} */
nrfy_twim_shorts_get(NRF_TWIM_Type const * p_reg)615 NRFY_STATIC_INLINE uint32_t nrfy_twim_shorts_get(NRF_TWIM_Type const * p_reg)
616 {
617     nrf_barrier_rw();
618     uint32_t shorts = nrf_twim_shorts_get(p_reg);
619     nrf_barrier_r();
620     return shorts;
621 }
622 
623 /** @refhal{nrf_twim_txd_amount_get} */
nrfy_twim_txd_amount_get(NRF_TWIM_Type const * p_reg)624 NRFY_STATIC_INLINE size_t nrfy_twim_txd_amount_get(NRF_TWIM_Type const * p_reg)
625 {
626     nrf_barrier_r();
627     size_t amount = nrf_twim_txd_amount_get(p_reg);
628     nrf_barrier_r();
629     return amount;
630 }
631 
632 /** @refhal{nrf_twim_rxd_amount_get} */
nrfy_twim_rxd_amount_get(NRF_TWIM_Type const * p_reg)633 NRFY_STATIC_INLINE size_t nrfy_twim_rxd_amount_get(NRF_TWIM_Type const * p_reg)
634 {
635     nrf_barrier_r();
636     size_t amount = nrf_twim_rxd_amount_get(p_reg);
637     nrf_barrier_r();
638     return amount;
639 }
640 
641 #if NRFY_TWIM_HAS_ARRAY_LIST
642 /** @refhal{nrf_twim_tx_list_enable} */
nrfy_twim_tx_list_enable(NRF_TWIM_Type * p_reg)643 NRFY_STATIC_INLINE void nrfy_twim_tx_list_enable(NRF_TWIM_Type * p_reg)
644 {
645     nrf_twim_tx_list_enable(p_reg);
646     nrf_barrier_w();
647 }
648 
649 /** @refhal{nrf_twim_tx_list_disable} */
nrfy_twim_tx_list_disable(NRF_TWIM_Type * p_reg)650 NRFY_STATIC_INLINE void nrfy_twim_tx_list_disable(NRF_TWIM_Type * p_reg)
651 {
652     nrf_twim_tx_list_disable(p_reg);
653     nrf_barrier_w();
654 }
655 
656 /** @refhal{nrf_twim_rx_list_enable} */
nrfy_twim_rx_list_enable(NRF_TWIM_Type * p_reg)657 NRFY_STATIC_INLINE void nrfy_twim_rx_list_enable(NRF_TWIM_Type * p_reg)
658 {
659     nrf_twim_rx_list_enable(p_reg);
660     nrf_barrier_w();
661 }
662 
663 /** @refhal{nrf_twim_rx_list_disable} */
nrfy_twim_rx_list_disable(NRF_TWIM_Type * p_reg)664 NRFY_STATIC_INLINE void nrfy_twim_rx_list_disable(NRF_TWIM_Type * p_reg)
665 {
666     nrf_twim_rx_list_disable(p_reg);
667     nrf_barrier_w();
668 }
669 #endif
670 
671 /** @} */
672 
__nrfy_internal_twim_event_enabled_clear(NRF_TWIM_Type * p_reg,uint32_t mask,nrf_twim_event_t event)673 NRFY_STATIC_INLINE void __nrfy_internal_twim_event_enabled_clear(NRF_TWIM_Type *  p_reg,
674                                                                  uint32_t         mask,
675                                                                  nrf_twim_event_t event)
676 {
677     if (mask & NRFY_EVENT_TO_INT_BITMASK(event))
678     {
679         nrf_twim_event_clear(p_reg, event);
680     }
681 }
682 
__nrfy_internal_twim_event_handle(NRF_TWIM_Type * p_reg,uint32_t mask,nrf_twim_event_t event,uint32_t * p_evt_mask)683 NRFY_STATIC_INLINE bool __nrfy_internal_twim_event_handle(NRF_TWIM_Type *  p_reg,
684                                                           uint32_t         mask,
685                                                           nrf_twim_event_t event,
686                                                           uint32_t *       p_evt_mask)
687 {
688     if ((mask & NRFY_EVENT_TO_INT_BITMASK(event)) && nrf_twim_event_check(p_reg, event))
689     {
690         nrf_twim_event_clear(p_reg, event);
691         if (p_evt_mask)
692         {
693             *p_evt_mask |= NRFY_EVENT_TO_INT_BITMASK(event);
694         }
695         return true;
696     }
697     return false;
698 }
699 
700 NRFY_STATIC_INLINE
__nrfy_internal_twim_events_process(NRF_TWIM_Type * p_reg,uint32_t mask,nrfy_twim_xfer_desc_t const * p_xfer)701 uint32_t __nrfy_internal_twim_events_process(NRF_TWIM_Type *               p_reg,
702                                              uint32_t                      mask,
703                                              nrfy_twim_xfer_desc_t const * p_xfer)
704 {
705     uint32_t evt_mask = 0;
706 
707     nrf_barrier_r();
708     (void)__nrfy_internal_twim_event_handle(p_reg, mask, NRF_TWIM_EVENT_SUSPENDED, &evt_mask);
709     (void)__nrfy_internal_twim_event_handle(p_reg, mask, NRF_TWIM_EVENT_STOPPED, &evt_mask);
710     (void)__nrfy_internal_twim_event_handle(p_reg, mask, NRF_TWIM_EVENT_ERROR, &evt_mask);
711     (void)__nrfy_internal_twim_event_handle(p_reg, mask, NRF_TWIM_EVENT_TXSTARTED, &evt_mask);
712     (void)__nrfy_internal_twim_event_handle(p_reg, mask, NRF_TWIM_EVENT_RXSTARTED, &evt_mask);
713     (void)__nrfy_internal_twim_event_handle(p_reg, mask, NRF_TWIM_EVENT_LASTTX, &evt_mask);
714     (void)__nrfy_internal_twim_event_handle(p_reg, mask, NRF_TWIM_EVENT_LASTRX, &evt_mask);
715 
716     if (p_xfer && (mask & NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_STOPPED)))
717     {
718         NRFY_CACHE_INV(p_xfer->p_buffer, p_xfer->length);
719     }
720     else if (p_xfer && (mask & NRFY_EVENT_TO_INT_BITMASK(NRF_TWIM_EVENT_LASTRX)))
721     {
722         NRFY_CACHE_INV(p_xfer->p_buffer, p_xfer->length);
723     }
724     nrf_barrier_w();
725     return evt_mask;
726 }
727 
728 #ifdef __cplusplus
729 }
730 #endif
731 
732 #endif // NRFY_TWIM_H__
733