xref: /nrf52832-nimble/nordic/nrfx/drivers/src/nrfx_twis.c (revision 150812a83cab50279bd772ef6db1bfaf255f2c5b)
1 /*
2  * Copyright (c) 2015 - 2018, 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     TWIS_PSEL_Type psel = p_reg->PSEL;
561 
562     nrfx_twis_swreset(p_reg);
563 
564     /* Clear pins state if */
565     if (!(TWIS_PSEL_SCL_CONNECT_Msk & psel.SCL))
566     {
567         nrf_gpio_cfg_default(psel.SCL);
568     }
569     if (!(TWIS_PSEL_SDA_CONNECT_Msk & psel.SDA))
570     {
571         nrf_gpio_cfg_default(psel.SDA);
572     }
573 
574 #if NRFX_CHECK(NRFX_PRS_ENABLED)
575     nrfx_prs_release(p_reg);
576 #endif
577 
578     /* Clear variables */
579     p_cb->ev_handler = NULL;
580     p_cb->state      = NRFX_DRV_STATE_UNINITIALIZED;
581 }
582 
583 
nrfx_twis_enable(nrfx_twis_t const * p_instance)584 void nrfx_twis_enable(nrfx_twis_t const * p_instance)
585 {
586     NRF_TWIS_Type *        p_reg = p_instance->p_reg;
587     twis_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
588     NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
589 
590     nrfx_twis_clear_all_events(p_reg);
591 
592     /* Enable interrupts */
593     if (NULL != p_cb->ev_handler)
594     {
595         nrf_twis_int_enable(p_reg, m_used_ints_mask);
596     }
597 
598     nrf_twis_enable(p_reg);
599     p_cb->error    = 0;
600     p_cb->state    = NRFX_DRV_STATE_POWERED_ON;
601     p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE;
602 }
603 
604 
nrfx_twis_disable(nrfx_twis_t const * p_instance)605 void nrfx_twis_disable(nrfx_twis_t const * p_instance)
606 {
607     NRF_TWIS_Type *        p_reg = p_instance->p_reg;
608     twis_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
609     NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
610 
611     nrf_twis_int_disable(p_reg, m_used_ints_mask);
612 
613     nrf_twis_disable(p_reg);
614     p_cb->state = NRFX_DRV_STATE_INITIALIZED;
615 }
616 
617 /* ARM recommends not using the LDREX and STREX instructions in C code.
618  * This is because the compiler might generate loads and stores between
619  * LDREX and STREX, potentially clearing the exclusive monitor set by LDREX.
620  * This recommendation also applies to the byte, halfword, and doubleword
621  * variants LDREXB, STREXB, LDREXH, STREXH, LDREXD, and STREXD.
622  *
623  * This is the reason for the function below to be implemented in assembly.
624  */
625 //lint -save -e578
626 #if defined (__CC_ARM )
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)627 static __ASM uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
628 {
629     mov   r3, r0
630     mov   r1, #0
631 nrfx_twis_error_get_and_clear_internal_try
632     ldrex r0, [r3]
633     strex r2, r1, [r3]
634     cmp   r2, r1                                     /* did this succeed?       */
635     bne   nrfx_twis_error_get_and_clear_internal_try /* no - try again          */
636     bx    lr
637 }
638 #elif defined ( __GNUC__ )
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)639 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
640 {
641     uint32_t ret;
642     uint32_t temp;
643     __ASM volatile(
644         "   .syntax unified           \n"
645         "nrfx_twis_error_get_and_clear_internal_try:         \n"
646         "   ldrex %[ret], [%[perror]]                        \n"
647         "   strex %[temp], %[zero], [%[perror]]              \n"
648         "   cmp   %[temp], %[zero]                           \n"
649         "   bne   nrfx_twis_error_get_and_clear_internal_try \n"
650     : /* Output */
651         [ret]"=&l"(ret),
652         [temp]"=&l"(temp)
653     : /* Input */
654         [zero]"l"(0),
655         [perror]"l"(perror)
656     );
657     (void)temp;
658     return ret;
659 }
660 #elif defined ( __ICCARM__ )
nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)661 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror)
662 {
663     uint32_t ret;
664     uint32_t temp;
665     __ASM volatile(
666         "1:         \n"
667         "   ldrex %[ret], [%[perror]]                           \n"
668         "   strex %[temp], %[zero], [%[perror]]                 \n"
669         "   cmp   %[temp], %[zero]                              \n"
670         "   bne.n 1b \n"
671     : /* Output */
672         [ret]"=&l"(ret),
673         [temp]"=&l"(temp)
674     : /* Input */
675         [zero]"l"(0),
676         [perror]"l"(perror)
677     );
678     (void)temp;
679     return ret;
680 }
681 #else
682     #error Unknown compiler
683 #endif
684 //lint -restore
685 
nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance)686 uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance)
687 {
688     nrfx_twis_preprocess_status(p_instance);
689     /* Make sure that access to error member is atomic
690      * so there is no bit that is cleared if it is not copied to local variable already. */
691     twis_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
692     return nrfx_twis_error_get_and_clear_internal(&p_cb->error);
693 }
694 
695 
nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,void const * p_buf,size_t size)696 nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance,
697                                 void const *        p_buf,
698                                 size_t              size)
699 {
700     nrfx_err_t err_code;
701     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
702 
703     /* Check power state*/
704     if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
705     {
706         err_code = NRFX_ERROR_INVALID_STATE;
707         NRFX_LOG_WARNING("Function: %s, error code: %s.",
708                          __func__,
709                          NRFX_LOG_ERROR_STRING_GET(err_code));
710         return err_code;
711     }
712     /* Check data address */
713     if (!nrfx_is_in_ram(p_buf))
714     {
715         err_code = NRFX_ERROR_INVALID_ADDR;
716         NRFX_LOG_WARNING("Function: %s, error code: %s.",
717                          __func__,
718                          NRFX_LOG_ERROR_STRING_GET(err_code));
719         return err_code;
720     }
721     /* Check data size */
722     if ((size & TWIS_TXD_MAXCNT_MAXCNT_Msk) != size)
723     {
724         err_code = NRFX_ERROR_INVALID_LENGTH;
725         NRFX_LOG_WARNING("Function: %s, error code: %s.",
726                          __func__,
727                          NRFX_LOG_ERROR_STRING_GET(err_code));
728         return err_code;
729     }
730 
731     nrf_twis_tx_prepare(p_instance->p_reg,
732                         (uint8_t const *)p_buf,
733                         (nrf_twis_amount_t)size);
734     err_code = NRFX_SUCCESS;
735     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
736     return err_code;
737 }
738 
739 
nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,void * p_buf,size_t size)740 nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance,
741                                 void *              p_buf,
742                                 size_t              size)
743 {
744     nrfx_err_t err_code;
745     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
746 
747     /* Check power state*/
748     if (p_cb->state != NRFX_DRV_STATE_POWERED_ON)
749     {
750         err_code = NRFX_ERROR_INVALID_STATE;
751         NRFX_LOG_WARNING("Function: %s, error code: %s.",
752                          __func__,
753                          NRFX_LOG_ERROR_STRING_GET(err_code));
754         return err_code;
755     }
756     /* Check data address */
757     if (!nrfx_is_in_ram(p_buf))
758     {
759         err_code = NRFX_ERROR_INVALID_ADDR;
760         NRFX_LOG_WARNING("Function: %s, error code: %s.",
761                          __func__,
762                          NRFX_LOG_ERROR_STRING_GET(err_code));
763         return err_code;
764     }
765     /* Check data size */
766     if ((size & TWIS_RXD_MAXCNT_MAXCNT_Msk) != size)
767     {
768         err_code = NRFX_ERROR_INVALID_LENGTH;
769         NRFX_LOG_WARNING("Function: %s, error code: %s.",
770                          __func__,
771                          NRFX_LOG_ERROR_STRING_GET(err_code));
772         return err_code;
773     }
774 
775     nrf_twis_rx_prepare(p_instance->p_reg,
776                         (uint8_t *)p_buf,
777                         (nrf_twis_amount_t)size);
778     err_code = NRFX_SUCCESS;
779     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
780     return err_code;
781 }
782 
783 
nrfx_twis_is_busy(nrfx_twis_t const * p_instance)784 bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance)
785 {
786     nrfx_twis_preprocess_status(p_instance);
787     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
788     return NRFX_TWIS_SUBSTATE_IDLE != p_cb->substate;
789 }
790 
nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance)791 bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance)
792 {
793     nrfx_twis_preprocess_status(p_instance);
794     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
795     return NRFX_TWIS_SUBSTATE_READ_WAITING == p_cb->substate;
796 }
797 
nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance)798 bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance)
799 {
800     nrfx_twis_preprocess_status(p_instance);
801     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
802     return NRFX_TWIS_SUBSTATE_WRITE_WAITING == p_cb->substate;
803 }
804 
nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance)805 bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance)
806 {
807     nrfx_twis_preprocess_status(p_instance);
808     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
809     return NRFX_TWIS_SUBSTATE_READ_PENDING == p_cb->substate;
810 }
811 
nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance)812 bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance)
813 {
814     nrfx_twis_preprocess_status(p_instance);
815     twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
816     return NRFX_TWIS_SUBSTATE_WRITE_PENDING == p_cb->substate;
817 }
818 
819 
820 #if NRFX_CHECK(NRFX_TWIS0_ENABLED)
nrfx_twis_0_irq_handler(void)821 void nrfx_twis_0_irq_handler(void)
822 {
823     nrfx_twis_state_machine(NRF_TWIS0, &m_cb[NRFX_TWIS0_INST_IDX]);
824 }
825 #endif
826 
827 #if NRFX_CHECK(NRFX_TWIS1_ENABLED)
nrfx_twis_1_irq_handler(void)828 void nrfx_twis_1_irq_handler(void)
829 {
830     nrfx_twis_state_machine(NRF_TWIS1, &m_cb[NRFX_TWIS1_INST_IDX]);
831 }
832 #endif
833 
834 #if NRFX_CHECK(NRFX_TWIS2_ENABLED)
nrfx_twis_2_irq_handler(void)835 void nrfx_twis_2_irq_handler(void)
836 {
837     nrfx_twis_state_machine(NRF_TWIS2, &m_cb[NRFX_TWIS2_INST_IDX]);
838 }
839 #endif
840 
841 #if NRFX_CHECK(NRFX_TWIS3_ENABLED)
nrfx_twis_3_irq_handler(void)842 void nrfx_twis_3_irq_handler(void)
843 {
844     nrfx_twis_state_machine(NRF_TWIS3, &m_cb[NRFX_TWIS3_INST_IDX]);
845 }
846 #endif
847 
848 #endif // NRFX_CHECK(NRFX_TWIS_ENABLED)
849