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