1 /*
2  * Copyright (c) 2015 - 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 #include <nrfx.h>
35 
36 #if NRFX_CHECK(NRFX_TWIS_ENABLED)
37 
38 #if !NRFX_FEATURE_PRESENT(NRFX_TWIS, _ENABLED)
39 #error "No enabled TWIS instances. Check <nrfx_config.h>."
40 #endif
41 
42 #include <nrfx_twis.h>
43 #include "prs/nrfx_prs.h"
44 
45 #define NRFX_LOG_MODULE TWIS
46 #include <nrfx_log.h>
47 
48 #define EVT_TO_STR(event)                                             \
49     (event == NRF_TWIS_EVENT_STOPPED   ? "NRF_TWIS_EVENT_STOPPED"   : \
50     (event == NRF_TWIS_EVENT_ERROR     ? "NRF_TWIS_EVENT_ERROR"     : \
51     (event == NRF_TWIS_EVENT_RXSTARTED ? "NRF_TWIS_EVENT_RXSTARTED" : \
52     (event == NRF_TWIS_EVENT_TXSTARTED ? "NRF_TWIS_EVENT_TXSTARTED" : \
53     (event == NRF_TWIS_EVENT_WRITE     ? "NRF_TWIS_EVENT_WRITE"     : \
54     (event == NRF_TWIS_EVENT_READ      ? "NRF_TWIS_EVENT_READ"      : \
55                                          "UNKNOWN EVENT"))))))
56 
57 /**
58  * @brief Actual state of internal state machine
59  *
60  * Current substate of powered on state.
61  */
62 typedef enum
63 {
64     NRFX_TWIS_SUBSTATE_IDLE,          ///< No ongoing transmission
65     NRFX_TWIS_SUBSTATE_READ_WAITING,  ///< Read request received, waiting for data
66     NRFX_TWIS_SUBSTATE_READ_PENDING,  ///< Reading is actually pending (data sending)
67     NRFX_TWIS_SUBSTATE_WRITE_WAITING, ///< Write request received, waiting for data buffer
68     NRFX_TWIS_SUBSTATE_WRITE_PENDING, ///< Writing is actually pending (data receiving)
69 } nrfx_twis_substate_t;
70 
71 // Control block - driver instance local data.
72 typedef struct
73 {
74     nrfx_twis_event_handler_t       ev_handler;
75     // Internal copy of hardware errors flags merged with specific internal
76     // driver errors flags.
77     // This value can be changed in the interrupt and cleared in the main program.
78     // Always use Atomic load-store when updating this value in main loop.
79     volatile uint32_t               error;
80     nrfx_drv_state_t                state;
81     volatile nrfx_twis_substate_t   substate;
82 
83     volatile bool                   semaphore;
84     bool                            skip_gpio_cfg;
85 } twis_control_block_t;
86 static twis_control_block_t m_cb[NRFX_TWIS_ENABLED_COUNT];
87 
88 /**
89  * @brief Used interrupts mask
90  *
91  * Mask for all interrupts used by this library
92  */
93 static const uint32_t m_used_ints_mask = NRF_TWIS_INT_STOPPED_MASK   |
94                                          NRF_TWIS_INT_ERROR_MASK     |
95                                          NRF_TWIS_INT_RXSTARTED_MASK |
96                                          NRF_TWIS_INT_TXSTARTED_MASK |
97                                          NRF_TWIS_INT_WRITE_MASK     |
98                                          NRF_TWIS_INT_READ_MASK;
99 
100 /**
101  * @brief Clear all  events
102  *
103  * Function clears all actually pending events
104  */
nrfx_twis_clear_all_events(NRF_TWIS_Type * const p_reg)105 static void nrfx_twis_clear_all_events(NRF_TWIS_Type * const p_reg)
106 {
107     /* Clear all events */
108     nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_STOPPED);
109     nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_ERROR);
110     nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_RXSTARTED);
111     nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_TXSTARTED);
112     nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_WRITE);
113     nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_READ);
114 }
115 
116 /**
117  * @brief Reset all the registers to known state
118  *
119  * This function clears all registers that requires it to known state.
120  * TWIS is left disabled after this function.
121  * All events are cleared.
122  * @param[out] p_reg TWIS to reset register address
123  */
nrfx_twis_swreset(NRF_TWIS_Type * p_reg)124 static inline void nrfx_twis_swreset(NRF_TWIS_Type * p_reg)
125 {
126     /* Disable TWIS */
127     nrf_twis_disable(p_reg);
128 
129     /* Disable interrupt global for the instance */
130     NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_reg));
131 
132     /* Disable interrupts */
133     nrf_twis_int_disable(p_reg, ~0U);
134 }
135 
136 /**
137  * @brief Configure pin
138  *
139  * Function configures selected for work as SDA or SCL.
140  * @param pin Pin number to configure
141  */
nrfx_twis_config_pin(uint32_t pin,nrf_gpio_pin_pull_t pull)142 static inline void nrfx_twis_config_pin(uint32_t pin, nrf_gpio_pin_pull_t pull)
143 {
144     nrf_gpio_cfg(pin,
145                  NRF_GPIO_PIN_DIR_INPUT,
146                  NRF_GPIO_PIN_INPUT_DISCONNECT,
147                  pull,
148                  NRF_GPIO_PIN_S0D1,
149                  NRF_GPIO_PIN_NOSENSE);
150 }
151 
152 /**
153  * @brief Auxiliary function for getting event state on right bit possition
154  *
155  * This function calls @ref nrf_twis_event_get function but the the result
156  * is shifted to match INTEN register scheme.
157  *
158  * @param[in,out] p_reg TWIS to read  event from
159  * @param ev  Event code
160  *
161  * @return Selected event state shifted by @ref nrfx_event_to_bitpos
162  *
163  * @sa nrf_twis_event_get
164  * @sa nrfx_event_to_bitpos
165  */
nrfx_twis_event_bit_get(NRF_TWIS_Type * p_reg,nrf_twis_event_t ev)166 static inline uint32_t nrfx_twis_event_bit_get(NRF_TWIS_Type *  p_reg,
167                                                nrf_twis_event_t ev)
168 {
169     return (uint32_t)nrf_twis_event_get_and_clear(p_reg, ev) << nrfx_event_to_bitpos(ev);
170 }
171 
172 /**
173  * @brief Auxiliary function for checking event bit inside given flags value
174  *
175  * Function used here to check presence of the event inside given flags value.
176  * It transforms given event to bit possition and then checks if in given variable it is cleared.
177  *
178  * @param flags Flags to test
179  * @param ev Event code
180  *
181  * @retval true Flag for selected event is set
182  * @retval false Flag for selected event is cleared
183  */
nrfx_twis_check_bit(uint32_t flags,nrf_twis_event_t ev)184 static inline bool nrfx_twis_check_bit(uint32_t         flags,
185                                        nrf_twis_event_t ev)
186 {
187     return 0 != (flags & (1U << nrfx_event_to_bitpos(ev)));
188 }
189 
190 /**
191  * @brief Auxiliary function for clearing event bit in given flags value
192  *
193  * Function used to clear selected event bit.
194  *
195  * @param flags Flags to process
196  * @param ev    Event code to clear
197  *
198  * @return Value @em flags with cleared event bit that matches given @em ev
199  */
nrfx_twis_clear_bit(uint32_t flags,nrf_twis_event_t ev)200 static inline uint32_t nrfx_twis_clear_bit(uint32_t         flags,
201                                            nrf_twis_event_t ev)
202 {
203     return flags & ~(1U << nrfx_event_to_bitpos(ev));
204 }
205 
call_event_handler(twis_control_block_t const * p_cb,nrfx_twis_evt_t const * p_evt)206 static void call_event_handler(twis_control_block_t const * p_cb,
207                                nrfx_twis_evt_t const *      p_evt)
208 {
209     nrfx_twis_event_handler_t handler = p_cb->ev_handler;
210     if (handler != NULL)
211     {
212         handler(p_evt);
213     }
214 }
215 
216 /**
217  * @brief Auxiliary function for error processing
218  *
219  * Function called when in current substate the event apears and it cannot be processed.
220  * It should be called also on ERROR event.
221  * If given @em error parameter has zero value the @ref NRFX_TWIS_ERROR_UNEXPECTED_EVENT
222  * would be set.
223  *
224  * @param p_cb   Pointer to the driver instance control block.
225  * @param evt    What error event raport to event handler
226  * @param error  Error flags
227  */
nrfx_twis_process_error(twis_control_block_t * p_cb,nrfx_twis_evt_type_t evt,uint32_t error)228 static inline void nrfx_twis_process_error(twis_control_block_t * p_cb,
229                                            nrfx_twis_evt_type_t   evt,
230                                            uint32_t               error)
231 {
232     if (0 == error)
233     {
234         error = NRFX_TWIS_ERROR_UNEXPECTED_EVENT;
235     }
236     nrfx_twis_evt_t evdata;
237     evdata.type       = evt;
238     evdata.data.error = error;
239 
240     p_cb->error |= error;
241 
242     call_event_handler(p_cb, &evdata);
243 }
244 
irq_handler(NRF_TWIS_Type * p_reg,twis_control_block_t * p_cb)245 static void irq_handler(NRF_TWIS_Type * p_reg, twis_control_block_t * p_cb)
246 {
247     if (!NRFX_TWIS_NO_SYNC_MODE)
248     {
249         /* Exclude parallel processing of this function */
250         if (p_cb->semaphore)
251         {
252             return;
253         }
254         p_cb->semaphore = 1;
255     }
256 
257     /* Event data structure to be passed into event handler */
258     nrfx_twis_evt_t evdata;
259     /* Current substate copy  */
260     nrfx_twis_substate_t substate = p_cb->substate;
261     /* Event flags */
262     uint32_t ev = 0;
263 
264     /* Get all events */
265     ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_STOPPED);
266     ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_ERROR);
267     ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_RXSTARTED);
268     ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_TXSTARTED);
269     ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_WRITE);
270     ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_READ);
271 
272     /* State machine */
273     while (0 != ev)
274     {
275         switch (substate)
276         {
277         case NRFX_TWIS_SUBSTATE_IDLE:
278             if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
279             {
280                 /* Stopped event is always allowed in IDLE state - just ignore */
281                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
282             }
283             else if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ))
284             {
285                 evdata.type = NRFX_TWIS_EVT_READ_REQ;
286                 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED))
287                 {
288                     substate = NRFX_TWIS_SUBSTATE_READ_PENDING;
289                     evdata.data.buf_req = false;
290                 }
291                 else
292                 {
293                     substate = NRFX_TWIS_SUBSTATE_READ_WAITING;
294                     evdata.data.buf_req = true;
295                 }
296                 call_event_handler(p_cb, &evdata);
297                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_READ);
298                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
299                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE);
300                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
301             }
302             else if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE))
303             {
304                 evdata.type = NRFX_TWIS_EVT_WRITE_REQ;
305                 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED))
306                 {
307                     substate = NRFX_TWIS_SUBSTATE_WRITE_PENDING;
308                     evdata.data.buf_req = false;
309                 }
310                 else
311                 {
312                     substate = NRFX_TWIS_SUBSTATE_WRITE_WAITING;
313                     evdata.data.buf_req = true;
314                 }
315                 call_event_handler(p_cb, &evdata);
316                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_READ);
317                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
318                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE);
319                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
320             }
321             else
322             {
323                 nrfx_twis_process_error(p_cb,
324                                         NRFX_TWIS_EVT_GENERAL_ERROR,
325                                         nrf_twis_error_source_get_and_clear(p_reg));
326                 ev = 0;
327             }
328             break;
329         case NRFX_TWIS_SUBSTATE_READ_WAITING:
330             if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED) ||
331                 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE)     ||
332                 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ)      ||
333                 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
334             {
335                 substate = NRFX_TWIS_SUBSTATE_READ_PENDING;
336                 /* Any other bits requires further processing in PENDING substate */
337                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED);
338             }
339             else
340             {
341                 nrfx_twis_process_error(p_cb,
342                                         NRFX_TWIS_EVT_READ_ERROR,
343                                         nrf_twis_error_source_get_and_clear(p_reg));
344                 substate = NRFX_TWIS_SUBSTATE_IDLE;
345                 ev = 0;
346             }
347             break;
348         case NRFX_TWIS_SUBSTATE_READ_PENDING:
349             if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
350                 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ)  ||
351                 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
352             {
353                 evdata.type = NRFX_TWIS_EVT_READ_DONE;
354                 evdata.data.tx_amount = nrf_twis_tx_amount_get(p_reg);
355                 NRFX_LOG_INFO("Transfer tx_len:%d", evdata.data.tx_amount);
356                 NRFX_LOG_DEBUG("Tx data:");
357                 NRFX_LOG_HEXDUMP_DEBUG((uint8_t const *)nrf_twis_tx_buffer_get(p_reg),
358                                        evdata.data.tx_amount * sizeof(uint8_t));
359                 call_event_handler(p_cb, &evdata);
360                 /* Go to idle and repeat the state machine if READ or WRITE events detected.
361                  * This time READ or WRITE would be started */
362                 substate = NRFX_TWIS_SUBSTATE_IDLE;
363                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
364             }
365             else
366             {
367                 nrfx_twis_process_error(p_cb,
368                                         NRFX_TWIS_EVT_READ_ERROR,
369                                         nrf_twis_error_source_get_and_clear(p_reg));
370                 substate = NRFX_TWIS_SUBSTATE_IDLE;
371                 ev = 0;
372             }
373             break;
374         case NRFX_TWIS_SUBSTATE_WRITE_WAITING:
375             if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED) ||
376                 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE)     ||
377                 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ)      ||
378                 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
379             {
380                 substate = NRFX_TWIS_SUBSTATE_WRITE_PENDING;
381                 /* Any other bits requires further processing in PENDING substate */
382                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED);
383             }
384             else
385             {
386                 nrfx_twis_process_error(p_cb,
387                                         NRFX_TWIS_EVT_WRITE_ERROR,
388                                         nrf_twis_error_source_get_and_clear(p_reg));
389                 substate = NRFX_TWIS_SUBSTATE_IDLE;
390                 ev = 0;
391             }
392             break;
393         case NRFX_TWIS_SUBSTATE_WRITE_PENDING:
394             if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) ||
395                 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ)  ||
396                 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED))
397             {
398                 evdata.type = NRFX_TWIS_EVT_WRITE_DONE;
399                 evdata.data.rx_amount = nrf_twis_rx_amount_get(p_reg);
400                 call_event_handler(p_cb, &evdata);
401                 /* Go to idle and repeat the state machine if READ or WRITE events detected.
402                  * This time READ or WRITE would be started */
403                 substate = NRFX_TWIS_SUBSTATE_IDLE;
404                 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED);
405             }
406             else
407             {
408                 nrfx_twis_process_error(p_cb,
409                                         NRFX_TWIS_EVT_WRITE_ERROR,
410                                         nrf_twis_error_source_get_and_clear(p_reg));
411                 substate = NRFX_TWIS_SUBSTATE_IDLE;
412                 ev = 0;
413             }
414             break;
415         default:
416             substate = NRFX_TWIS_SUBSTATE_IDLE;
417             /* Do not clear any events and repeat the machine */
418             break;
419         }
420     }
421 
422     p_cb->substate = substate;
423     if (!NRFX_TWIS_NO_SYNC_MODE)
424     {
425         p_cb->semaphore = 0;
426     }
427 }
428 
nrfx_twis_preprocess_status(nrfx_twis_t const * p_instance)429 static inline void nrfx_twis_preprocess_status(nrfx_twis_t const * p_instance)
430 {
431     if (!NRFX_TWIS_NO_SYNC_MODE)
432     {
433         NRF_TWIS_Type *        p_reg = p_instance->p_reg;
434         twis_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
435         if (NULL == p_cb->ev_handler)
436         {
437             irq_handler(p_reg, p_cb);
438         }
439     }
440 }
441 
twis_configure(nrfx_twis_t const * p_instance,nrfx_twis_config_t const * p_config)442 static void twis_configure(nrfx_twis_t const *        p_instance,
443                            nrfx_twis_config_t const * p_config)
444 {
445     uint32_t addr_mask = 0;
446     if (0 == (p_config->addr[0] | p_config->addr[1]))
447     {
448         addr_mask = NRF_TWIS_CONFIG_ADDRESS0_MASK;
449     }
450     else
451     {
452         if (0 != p_config->addr[0])
453         {
454             addr_mask |= NRF_TWIS_CONFIG_ADDRESS0_MASK;
455         }
456         if (0 != p_config->addr[1])
457         {
458             addr_mask |= NRF_TWIS_CONFIG_ADDRESS1_MASK;
459         }
460     }
461 
462     if (!p_config->skip_psel_cfg)
463     {
464         nrf_twis_pins_set(p_instance->p_reg, p_config->scl_pin, p_config->sda_pin);
465     }
466 
467     nrf_twis_address_set(p_instance->p_reg, 0, (nrf_twis_address_t)p_config->addr[0]);
468     nrf_twis_address_set(p_instance->p_reg, 1, (nrf_twis_address_t)p_config->addr[1]);
469 
470     nrf_twis_config_address_set(p_instance->p_reg, (nrf_twis_config_addr_mask_t)addr_mask);
471 
472     if (m_cb[p_instance->drv_inst_idx].ev_handler)
473     {
474         /* Peripheral interrupt configure
475         * (note - interrupts still needs to be configured in INTEN register.
476         * This is done in enable function) */
477         NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
478                               p_config->interrupt_priority);
479         NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
480     }
481 }
482 
483 /* -------------------------------------------------------------------------
484  * Implementation of interface functions
485  *
486  */
487 
nrfx_twis_init(nrfx_twis_t const * p_instance,nrfx_twis_config_t const * p_config,nrfx_twis_event_handler_t event_handler)488 nrfx_err_t nrfx_twis_init(nrfx_twis_t const *        p_instance,
489                           nrfx_twis_config_t const * p_config,
490                           nrfx_twis_event_handler_t  event_handler)
491 {
492     NRFX_ASSERT(p_config);
493     nrfx_err_t err_code;
494 
495     NRF_TWIS_Type *        p_reg = p_instance->p_reg;
496     twis_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
497 
498     if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
499     {
500 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
501         err_code = NRFX_ERROR_ALREADY;
502 #else
503         err_code = NRFX_ERROR_INVALID_STATE;
504 #endif
505         NRFX_LOG_WARNING("Function: %s, error code: %s.",
506                          __func__,
507                          NRFX_LOG_ERROR_STRING_GET(err_code));
508         return err_code;
509     }
510 
511 #if NRFX_CHECK(NRFX_PRS_ENABLED)
512     static nrfx_irq_handler_t const irq_handlers[NRFX_TWIS_ENABLED_COUNT] = {
513         NRFX_INSTANCE_IRQ_HANDLERS_LIST(TWIS, twis)
514     };
515     if (nrfx_prs_acquire(p_reg,
516             irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
517     {
518         err_code = NRFX_ERROR_BUSY;
519         NRFX_LOG_WARNING("Function: %s, error code: %s.",
520                          __func__,
521                          NRFX_LOG_ERROR_STRING_GET(err_code));
522         return err_code;
523     }
524 #endif // NRFX_CHECK(NRFX_PRS_ENABLED)
525 
526     if (!NRFX_TWIS_ASSUME_INIT_AFTER_RESET_ONLY)
527     {
528         nrfx_twis_swreset(p_reg);
529     }
530 
531     p_cb->ev_handler = event_handler;
532     if (p_config)
533     {
534         p_cb->skip_gpio_cfg = p_config->skip_gpio_cfg;
535         if (!p_config->skip_gpio_cfg)
536         {
537             NRFX_ASSERT(p_config->scl_pin != p_config->sda_pin);
538             nrfx_twis_config_pin(p_config->scl_pin, p_config->scl_pull);
539             nrfx_twis_config_pin(p_config->sda_pin, p_config->sda_pull);
540 #if NRF_GPIO_HAS_CLOCKPIN &&  defined(NRF_TWIS_CLOCKPIN_SCL_NEEDED)
541             nrf_gpio_pin_clock_set(p_config->scl_pin, true);
542 #endif
543         }
544         twis_configure(p_instance, p_config);
545     }
546 
547     /* Clear semaphore */
548     if (!NRFX_TWIS_NO_SYNC_MODE)
549     {
550         p_cb->semaphore = 0;
551     }
552     /* Set internal instance variables */
553     p_cb->substate   = NRFX_TWIS_SUBSTATE_IDLE;
554     p_cb->state      = NRFX_DRV_STATE_INITIALIZED;
555     err_code = NRFX_SUCCESS;
556     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
557     return err_code;
558 }
559 
nrfx_twis_reconfigure(nrfx_twis_t const * p_instance,nrfx_twis_config_t const * p_config)560 nrfx_err_t nrfx_twis_reconfigure(nrfx_twis_t const *        p_instance,
561                                  nrfx_twis_config_t const * p_config)
562 {
563     NRFX_ASSERT(p_config);
564 
565     if (m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_UNINITIALIZED)
566     {
567         return NRFX_ERROR_INVALID_STATE;
568     }
569     if (nrfx_twis_is_busy(p_instance))
570     {
571         return NRFX_ERROR_BUSY;
572     }
573 
574     if (nrf_twis_enable_check(p_instance->p_reg))
575     {
576         nrf_twis_disable(p_instance->p_reg);
577         twis_configure(p_instance, p_config);
578         nrf_twis_enable(p_instance->p_reg);
579     }
580     else
581     {
582         twis_configure(p_instance, p_config);
583     }
584 
585     return NRFX_SUCCESS;
586 }
587 
nrfx_twis_uninit(nrfx_twis_t const * p_instance)588 void nrfx_twis_uninit(nrfx_twis_t const * p_instance)
589 {
590     NRF_TWIS_Type *        p_reg = p_instance->p_reg;
591     twis_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
592 
593     NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
594 
595     nrfx_twis_swreset(p_reg);
596 
597     if (!p_cb->skip_gpio_cfg)
598     {
599         nrf_gpio_cfg_default(nrf_twis_scl_pin_get(p_reg));
600         nrf_gpio_cfg_default(nrf_twis_sda_pin_get(p_reg));
601     }
602 
603 #if NRFX_CHECK(NRFX_PRS_ENABLED)
604     nrfx_prs_release(p_reg);
605 #endif
606 
607     /* Clear variables */
608     p_cb->ev_handler = NULL;
609     p_cb->state      = NRFX_DRV_STATE_UNINITIALIZED;
610     NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
611 }
612 
nrfx_twis_init_check(nrfx_twis_t const * p_instance)613 bool nrfx_twis_init_check(nrfx_twis_t const * p_instance)
614 {
615     twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
616 
617     return (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
618 }
619 
nrfx_twis_enable(nrfx_twis_t const * p_instance)620 void nrfx_twis_enable(nrfx_twis_t const * p_instance)
621 {
622     NRF_TWIS_Type *        p_reg = p_instance->p_reg;
623     twis_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
624 
625     NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
626 
627     nrfx_twis_clear_all_events(p_reg);
628 
629     /* Enable interrupts */
630     if (NULL != p_cb->ev_handler)
631     {
632         nrf_twis_int_enable(p_reg, m_used_ints_mask);
633     }
634 
635     nrf_twis_enable(p_reg);
636     p_cb->error    = 0;
637     p_cb->state    = NRFX_DRV_STATE_POWERED_ON;
638     p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE;
639 }
640 
nrfx_twis_disable(nrfx_twis_t const * p_instance)641 void nrfx_twis_disable(nrfx_twis_t const * p_instance)
642 {
643     NRF_TWIS_Type *        p_reg = p_instance->p_reg;
644     twis_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
645 
646     NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
647 
648     nrf_twis_int_disable(p_reg, m_used_ints_mask);
649 
650     nrf_twis_disable(p_reg);
651     p_cb->state = NRFX_DRV_STATE_INITIALIZED;
652 }
653 
654 /* ARM recommends not using the LDREX and STREX instructions in C code.
655  * This is because the compiler might generate loads and stores between
656  * LDREX and STREX, potentially clearing the exclusive monitor set by LDREX.
657  * This recommendation also applies to the byte, halfword, and doubleword
658  * variants LDREXB, STREXB, LDREXH, STREXH, LDREXD, and STREXD.
659  *
660  * This is the reason for the function below to be implemented in assembly.
661  */
662 #if defined (__CC_ARM )
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)663 static __ASM uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
664 {
665     mov   r3, r0
666     mov   r1, #0
667 nrfx_twis_error_get_and_clear_internal_try
668     ldrex r0, [r3]
669     strex r2, r1, [r3]
670     cmp   r2, r1                                     /* did this succeed?       */
671     bne   nrfx_twis_error_get_and_clear_internal_try /* no - try again          */
672     bx    lr
673 }
674 #elif defined ( __GNUC__ ) && defined(ISA_ARM)
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)675 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
676 {
677     uint32_t ret;
678     uint32_t temp;
679     __ASM volatile(
680         "   .syntax unified           \n"
681         "nrfx_twis_error_get_and_clear_internal_try:         \n"
682         "   ldrex %[ret], [%[perror]]                        \n"
683         "   strex %[temp], %[zero], [%[perror]]              \n"
684         "   cmp   %[temp], %[zero]                           \n"
685         "   bne   nrfx_twis_error_get_and_clear_internal_try \n"
686     : /* Output */
687         [ret]"=&l"(ret),
688         [temp]"=&l"(temp)
689     : /* Input */
690         [zero]"l"(0),
691         [perror]"l"(perror)
692     );
693     (void)temp;
694     return ret;
695 }
696 #elif defined ( __GNUC__ ) && defined(ISA_RISCV)
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)697 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
698 {
699     uint32_t error = *perror;
700     *perror = 0;
701     return error;
702 }
703 #elif defined ( __ICCARM__ )
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)704 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
705 {
706     uint32_t ret;
707     uint32_t temp;
708     __ASM volatile(
709         "1:         \n"
710         "   ldrex %[ret], [%[perror]]                           \n"
711         "   strex %[temp], %[zero], [%[perror]]                 \n"
712         "   cmp   %[temp], %[zero]                              \n"
713         "   bne.n 1b \n"
714     : /* Output */
715         [ret]"=&l"(ret),
716         [temp]"=&l"(temp)
717     : /* Input */
718         [zero]"l"(0),
719         [perror]"l"(perror)
720     );
721     (void)temp;
722     return ret;
723 }
724 #else
725     #error Unknown compiler
726 #endif
727 
nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance)728 uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance)
729 {
730     twis_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
731 
732     NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
733 
734     nrfx_twis_preprocess_status(p_instance);
735     /* Make sure that access to error member is atomic
736      * so there is no bit that is cleared if it is not copied to local variable already. */
737     return nrfx_twis_error_get_and_clear_internal(&p_cb->error);
738 }
739 
nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,void const * p_buf,size_t size)740 nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
741                                 void const *        p_buf,
742                                 size_t              size)
743 {
744     NRFX_ASSERT(p_buf);
745 
746     nrfx_err_t err_code;
747     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
748 
749     /* Check power state*/
750     if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
751     {
752         err_code = NRFX_ERROR_INVALID_STATE;
753         NRFX_LOG_WARNING("Function: %s, error code: %s.",
754                          __func__,
755                          NRFX_LOG_ERROR_STRING_GET(err_code));
756         return err_code;
757     }
758     /* Check data address */
759     if (!nrfx_is_in_ram(p_buf))
760     {
761         err_code = NRFX_ERROR_INVALID_ADDR;
762         NRFX_LOG_WARNING("Function: %s, error code: %s.",
763                          __func__,
764                          NRFX_LOG_ERROR_STRING_GET(err_code));
765         return err_code;
766     }
767     /* Check data size */
768     if (size > NRF_TWIS_RX_MAX_COUNT_SIZE)
769     {
770         err_code = NRFX_ERROR_INVALID_LENGTH;
771         NRFX_LOG_WARNING("Function: %s, error code: %s.",
772                          __func__,
773                          NRFX_LOG_ERROR_STRING_GET(err_code));
774         return err_code;
775     }
776 
777     nrf_twis_tx_prepare(p_instance->p_reg,
778                         (uint8_t const *)p_buf,
779                         size);
780     err_code = NRFX_SUCCESS;
781     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
782     return err_code;
783 }
784 
nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,void * p_buf,size_t size)785 nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
786                                 void *              p_buf,
787                                 size_t              size)
788 {
789     NRFX_ASSERT(p_buf);
790 
791     nrfx_err_t err_code;
792     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
793 
794     /* Check power state*/
795     if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
796     {
797         err_code = NRFX_ERROR_INVALID_STATE;
798         NRFX_LOG_WARNING("Function: %s, error code: %s.",
799                          __func__,
800                          NRFX_LOG_ERROR_STRING_GET(err_code));
801         return err_code;
802     }
803     /* Check data address */
804     if (!nrfx_is_in_ram(p_buf))
805     {
806         err_code = NRFX_ERROR_INVALID_ADDR;
807         NRFX_LOG_WARNING("Function: %s, error code: %s.",
808                          __func__,
809                          NRFX_LOG_ERROR_STRING_GET(err_code));
810         return err_code;
811     }
812     /* Check data size */
813     if (size > NRF_TWIS_TX_MAX_COUNT_SIZE)
814     {
815         err_code = NRFX_ERROR_INVALID_LENGTH;
816         NRFX_LOG_WARNING("Function: %s, error code: %s.",
817                          __func__,
818                          NRFX_LOG_ERROR_STRING_GET(err_code));
819         return err_code;
820     }
821 
822     nrf_twis_rx_prepare(p_instance->p_reg,
823                         (uint8_t *)p_buf,
824                         size);
825     err_code = NRFX_SUCCESS;
826     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
827     return err_code;
828 }
829 
nrfx_twis_is_busy(nrfx_twis_t const * p_instance)830 bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance)
831 {
832     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
833 
834     NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
835 
836     nrfx_twis_preprocess_status(p_instance);
837     return NRFX_TWIS_SUBSTATE_IDLE != p_cb->substate;
838 }
839 
nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance)840 bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance)
841 {
842     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
843 
844     NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
845 
846     nrfx_twis_preprocess_status(p_instance);
847     return NRFX_TWIS_SUBSTATE_READ_WAITING == p_cb->substate;
848 }
849 
nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance)850 bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance)
851 {
852     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
853 
854     NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
855 
856     nrfx_twis_preprocess_status(p_instance);
857     return NRFX_TWIS_SUBSTATE_WRITE_WAITING == p_cb->substate;
858 }
859 
nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance)860 bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance)
861 {
862     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
863 
864     NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
865 
866     nrfx_twis_preprocess_status(p_instance);
867     return NRFX_TWIS_SUBSTATE_READ_PENDING == p_cb->substate;
868 }
869 
nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance)870 bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance)
871 {
872     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
873 
874     NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON);
875 
876     nrfx_twis_preprocess_status(p_instance);
877     return NRFX_TWIS_SUBSTATE_WRITE_PENDING == p_cb->substate;
878 }
879 
880 NRFX_INSTANCE_IRQ_HANDLERS(TWIS, twis)
881 
882 #endif // NRFX_CHECK(NRFX_TWIS_ENABLED)
883