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