xref: /nrf52832-nimble/nordic/nrfx/drivers/src/nrfx_twi.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_TWI_ENABLED)
35 
36 #if !(NRFX_CHECK(NRFX_TWI0_ENABLED) || NRFX_CHECK(NRFX_TWI1_ENABLED))
37 #error "No enabled TWI instances. Check <nrfx_config.h>."
38 #endif
39 
40 #include <nrfx_twi.h>
41 #include <hal/nrf_gpio.h>
42 #include "prs/nrfx_prs.h"
43 
44 #define NRFX_LOG_MODULE TWI
45 #include <nrfx_log.h>
46 
47 #define EVT_TO_STR(event)                                      \
48     (event == NRFX_TWI_EVT_DONE         ? "EVT_DONE"         : \
49     (event == NRFX_TWI_EVT_ADDRESS_NACK ? "EVT_ADDRESS_NACK" : \
50     (event == NRFX_TWI_EVT_DATA_NACK    ? "EVT_DATA_NACK"    : \
51                                           "UNKNOWN ERROR")))
52 
53 #define EVT_TO_STR_TWI(event)                                       \
54     (event == NRF_TWI_EVENT_STOPPED   ? "NRF_TWI_EVENT_STOPPED"   : \
55     (event == NRF_TWI_EVENT_RXDREADY  ? "NRF_TWI_EVENT_RXDREADY"  : \
56     (event == NRF_TWI_EVENT_TXDSENT   ? "NRF_TWI_EVENT_TXDSENT"   : \
57     (event == NRF_TWI_EVENT_ERROR     ? "NRF_TWI_EVENT_ERROR"     : \
58     (event == NRF_TWI_EVENT_BB        ? "NRF_TWI_EVENT_BB"        : \
59     (event == NRF_TWI_EVENT_SUSPENDED ? "NRF_TWI_EVENT_SUSPENDED" : \
60                                         "UNKNOWN ERROR"))))))
61 
62 #define TRANSFER_TO_STR(type)                   \
63     (type == NRFX_TWI_XFER_TX   ? "XFER_TX"   : \
64     (type == NRFX_TWI_XFER_RX   ? "XFER_RX"   : \
65     (type == NRFX_TWI_XFER_TXRX ? "XFER_TXRX" : \
66     (type == NRFX_TWI_XFER_TXTX ? "XFER_TXTX" : \
67                                   "UNKNOWN TRANSFER TYPE"))))
68 
69 #define TWI_PIN_INIT(_pin) nrf_gpio_cfg((_pin),                     \
70                                         NRF_GPIO_PIN_DIR_INPUT,     \
71                                         NRF_GPIO_PIN_INPUT_CONNECT, \
72                                         NRF_GPIO_PIN_PULLUP,        \
73                                         NRF_GPIO_PIN_S0D1,          \
74                                         NRF_GPIO_PIN_NOSENSE)
75 
76 #define HW_TIMEOUT      100000
77 
78 // Control block - driver instance local data.
79 typedef struct
80 {
81     nrfx_twi_evt_handler_t  handler;
82     void *                  p_context;
83     volatile uint32_t       int_mask;
84     nrfx_twi_xfer_desc_t    xfer_desc;
85     uint32_t                flags;
86     uint8_t *               p_curr_buf;
87     size_t                  curr_length;
88     bool                    curr_no_stop;
89     nrfx_drv_state_t        state;
90     bool                    error;
91     volatile bool           busy;
92     bool                    repeated;
93     size_t                  bytes_transferred;
94     bool                    hold_bus_uninit;
95 } twi_control_block_t;
96 
97 static twi_control_block_t m_cb[NRFX_TWI_ENABLED_COUNT];
98 
twi_process_error(uint32_t errorsrc)99 static nrfx_err_t twi_process_error(uint32_t errorsrc)
100 {
101     nrfx_err_t ret = NRFX_ERROR_INTERNAL;
102 
103     if (errorsrc & NRF_TWI_ERROR_OVERRUN)
104     {
105         ret = NRFX_ERROR_DRV_TWI_ERR_OVERRUN;
106     }
107 
108     if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK)
109     {
110         ret = NRFX_ERROR_DRV_TWI_ERR_ANACK;
111     }
112 
113     if (errorsrc & NRF_TWI_ERROR_DATA_NACK)
114     {
115         ret = NRFX_ERROR_DRV_TWI_ERR_DNACK;
116     }
117 
118     return ret;
119 }
120 
121 
122 
nrfx_twi_init(nrfx_twi_t const * p_instance,nrfx_twi_config_t const * p_config,nrfx_twi_evt_handler_t event_handler,void * p_context)123 nrfx_err_t nrfx_twi_init(nrfx_twi_t const *        p_instance,
124                          nrfx_twi_config_t const * p_config,
125                          nrfx_twi_evt_handler_t    event_handler,
126                          void *                    p_context)
127 {
128     NRFX_ASSERT(p_config);
129     NRFX_ASSERT(p_config->scl != p_config->sda);
130     twi_control_block_t * p_cb  = &m_cb[p_instance->drv_inst_idx];
131     nrfx_err_t err_code;
132 
133     if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
134     {
135         err_code = NRFX_ERROR_INVALID_STATE;
136         NRFX_LOG_WARNING("Function: %s, error code: %s.",
137                          __func__,
138                          NRFX_LOG_ERROR_STRING_GET(err_code));
139         return err_code;
140     }
141 
142 #if NRFX_CHECK(NRFX_PRS_ENABLED)
143     static nrfx_irq_handler_t const irq_handlers[NRFX_TWI_ENABLED_COUNT] = {
144         #if NRFX_CHECK(NRFX_TWI0_ENABLED)
145         nrfx_twi_0_irq_handler,
146         #endif
147         #if NRFX_CHECK(NRFX_TWI1_ENABLED)
148         nrfx_twi_1_irq_handler,
149         #endif
150     };
151     if (nrfx_prs_acquire(p_instance->p_twi,
152             irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
153     {
154         err_code = NRFX_ERROR_BUSY;
155         NRFX_LOG_WARNING("Function: %s, error code: %s.",
156                          __func__,
157                          NRFX_LOG_ERROR_STRING_GET(err_code));
158         return err_code;
159     }
160 #endif // NRFX_CHECK(NRFX_PRS_ENABLED)
161 
162     p_cb->handler         = event_handler;
163     p_cb->p_context       = p_context;
164     p_cb->int_mask        = 0;
165     p_cb->repeated        = false;
166     p_cb->busy            = false;
167     p_cb->hold_bus_uninit = p_config->hold_bus_uninit;
168 
169     /* To secure correct signal levels on the pins used by the TWI
170        master when the system is in OFF mode, and when the TWI master is
171        disabled, these pins must be configured in the GPIO peripheral.
172     */
173     TWI_PIN_INIT(p_config->scl);
174     TWI_PIN_INIT(p_config->sda);
175 
176     NRF_TWI_Type * p_twi = p_instance->p_twi;
177     nrf_twi_pins_set(p_twi, p_config->scl, p_config->sda);
178     nrf_twi_frequency_set(p_twi,
179         (nrf_twi_frequency_t)p_config->frequency);
180 
181     if (p_cb->handler)
182     {
183         NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_twi),
184             p_config->interrupt_priority);
185         NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_twi));
186     }
187 
188     p_cb->state = NRFX_DRV_STATE_INITIALIZED;
189 
190     err_code = NRFX_SUCCESS;
191     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
192     return err_code;
193 }
194 
nrfx_twi_uninit(nrfx_twi_t const * p_instance)195 void nrfx_twi_uninit(nrfx_twi_t const * p_instance)
196 {
197     twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
198     NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
199 
200     if (p_cb->handler)
201     {
202         NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_twi));
203     }
204     nrfx_twi_disable(p_instance);
205 
206 #if NRFX_CHECK(NRFX_PRS_ENABLED)
207     nrfx_prs_release(p_instance->p_twi);
208 #endif
209 
210     if (!p_cb->hold_bus_uninit)
211     {
212         nrf_gpio_cfg_default(p_instance->p_twi->PSELSCL);
213         nrf_gpio_cfg_default(p_instance->p_twi->PSELSDA);
214     }
215 
216     p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
217     NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
218 }
219 
nrfx_twi_enable(nrfx_twi_t const * p_instance)220 void nrfx_twi_enable(nrfx_twi_t const * p_instance)
221 {
222     twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
223     NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
224 
225     NRF_TWI_Type * p_twi = p_instance->p_twi;
226     nrf_twi_enable(p_twi);
227 
228     p_cb->state = NRFX_DRV_STATE_POWERED_ON;
229     NRFX_LOG_INFO("Instance enabled: %d.", p_instance->drv_inst_idx);
230 }
231 
nrfx_twi_disable(nrfx_twi_t const * p_instance)232 void nrfx_twi_disable(nrfx_twi_t const * p_instance)
233 {
234     twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
235     NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
236 
237     NRF_TWI_Type * p_twi = p_instance->p_twi;
238     nrf_twi_int_disable(p_twi, NRF_TWI_ALL_INTS_MASK);
239     nrf_twi_shorts_disable(p_twi, NRF_TWI_ALL_SHORTS_MASK);
240     nrf_twi_disable(p_twi);
241 
242     p_cb->state = NRFX_DRV_STATE_INITIALIZED;
243     NRFX_LOG_INFO("Instance disabled: %d.", p_instance->drv_inst_idx);
244 }
245 
twi_send_byte(NRF_TWI_Type * p_twi,uint8_t const * p_data,size_t length,size_t * p_bytes_transferred,bool no_stop)246 static bool twi_send_byte(NRF_TWI_Type  * p_twi,
247                           uint8_t const * p_data,
248                           size_t          length,
249                           size_t        * p_bytes_transferred,
250                           bool            no_stop)
251 {
252     if (*p_bytes_transferred < length)
253     {
254         nrf_twi_txd_set(p_twi, p_data[*p_bytes_transferred]);
255         ++(*p_bytes_transferred);
256     }
257     else
258     {
259         if (no_stop)
260         {
261             nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_SUSPEND);
262             return false;
263         }
264         else
265         {
266             nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
267         }
268     }
269     return true;
270 }
271 
twi_receive_byte(NRF_TWI_Type * p_twi,uint8_t * p_data,size_t length,size_t * p_bytes_transferred)272 static void twi_receive_byte(NRF_TWI_Type * p_twi,
273                              uint8_t      * p_data,
274                              size_t         length,
275                              size_t       * p_bytes_transferred)
276 {
277     if (*p_bytes_transferred < length)
278     {
279         p_data[*p_bytes_transferred] = nrf_twi_rxd_get(p_twi);
280 
281         ++(*p_bytes_transferred);
282 
283         if (*p_bytes_transferred == length - 1)
284         {
285             nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK);
286         }
287         else if (*p_bytes_transferred == length)
288         {
289             return;
290         }
291 
292         nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
293     }
294 }
295 
twi_transfer(NRF_TWI_Type * p_twi,bool * p_error,size_t * p_bytes_transferred,uint8_t * p_data,size_t length,bool no_stop)296 static bool twi_transfer(NRF_TWI_Type  * p_twi,
297                          bool          * p_error,
298                          size_t        * p_bytes_transferred,
299                          uint8_t       * p_data,
300                          size_t          length,
301                          bool            no_stop)
302 {
303     bool do_stop_check = ((*p_error) || ((*p_bytes_transferred) == length));
304 
305     if (*p_error)
306     {
307         nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
308         nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
309         nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
310     }
311     else if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
312     {
313         nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
314         NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR));
315         nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
316         *p_error = true;
317     }
318     else
319     {
320         if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_TXDSENT))
321         {
322             nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
323             NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_TXDSENT));
324             if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
325             {
326                 nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
327                 NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR));
328                 nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
329                 *p_error = true;
330             }
331             else
332             {
333                 if (!twi_send_byte(p_twi, p_data, length, p_bytes_transferred, no_stop))
334                 {
335                     return false;
336                 }
337             }
338         }
339         else if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_RXDREADY))
340         {
341             nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
342             NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_RXDREADY));
343             if (nrf_twi_event_check(p_twi, NRF_TWI_EVENT_ERROR))
344             {
345                 NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_ERROR));
346                 nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
347                 nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STOP);
348                 *p_error = true;
349             }
350             else
351             {
352                 twi_receive_byte(p_twi, p_data, length, p_bytes_transferred);
353             }
354         }
355     }
356 
357     if (do_stop_check && nrf_twi_event_check(p_twi, NRF_TWI_EVENT_STOPPED))
358     {
359         nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
360         NRFX_LOG_DEBUG("TWI: Event: %s.", EVT_TO_STR_TWI(NRF_TWI_EVENT_STOPPED));
361         return false;
362     }
363 
364     return true;
365 }
366 
twi_tx_start_transfer(twi_control_block_t * p_cb,NRF_TWI_Type * p_twi,uint8_t const * p_data,size_t length,bool no_stop)367 static nrfx_err_t twi_tx_start_transfer(twi_control_block_t * p_cb,
368                                         NRF_TWI_Type *        p_twi,
369                                         uint8_t const *       p_data,
370                                         size_t                length,
371                                         bool                  no_stop)
372 {
373     nrfx_err_t ret_code = NRFX_SUCCESS;
374     volatile int32_t hw_timeout;
375 
376     hw_timeout = HW_TIMEOUT;
377 
378     nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
379     nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
380     nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
381     nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
382     nrf_twi_shorts_set(p_twi, 0);
383 
384     p_cb->bytes_transferred = 0;
385     p_cb->error             = false;
386 
387     // In case TWI is suspended resume its operation.
388     nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
389     nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTTX);
390 
391     (void)twi_send_byte(p_twi, p_data, length, &p_cb->bytes_transferred, no_stop);
392 
393     if (p_cb->handler)
394     {
395         p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK   |
396                          NRF_TWI_INT_ERROR_MASK     |
397                          NRF_TWI_INT_TXDSENT_MASK   |
398                          NRF_TWI_INT_RXDREADY_MASK;
399         nrf_twi_int_enable(p_twi, p_cb->int_mask);
400     }
401     else
402     {
403         while ((hw_timeout > 0) &&
404                twi_transfer(p_twi,
405                             &p_cb->error,
406                             &p_cb->bytes_transferred,
407                             (uint8_t *)p_data,
408                             length,
409                             no_stop))
410         {
411             hw_timeout--;
412         }
413 
414         if (p_cb->error)
415         {
416             uint32_t errorsrc =  nrf_twi_errorsrc_get_and_clear(p_twi);
417 
418             if (errorsrc)
419             {
420                 ret_code = twi_process_error(errorsrc);
421             }
422         }
423 
424         if (hw_timeout <= 0)
425         {
426             nrf_twi_disable(p_twi);
427             nrf_twi_enable(p_twi);
428             ret_code = NRFX_ERROR_INTERNAL;
429         }
430 
431     }
432     return ret_code;
433 }
434 
twi_rx_start_transfer(twi_control_block_t * p_cb,NRF_TWI_Type * p_twi,uint8_t const * p_data,size_t length)435 static nrfx_err_t twi_rx_start_transfer(twi_control_block_t * p_cb,
436                                         NRF_TWI_Type *        p_twi,
437                                         uint8_t const *       p_data,
438                                         size_t                length)
439 {
440     nrfx_err_t ret_code = NRFX_SUCCESS;
441     volatile int32_t hw_timeout;
442 
443     hw_timeout = HW_TIMEOUT;
444 
445     nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_STOPPED);
446     nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_ERROR);
447     nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_TXDSENT);
448     nrf_twi_event_clear(p_twi, NRF_TWI_EVENT_RXDREADY);
449 
450     p_cb->bytes_transferred = 0;
451     p_cb->error             = false;
452 
453     if (length == 1)
454     {
455         nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_STOP_MASK);
456     }
457     else
458     {
459         nrf_twi_shorts_set(p_twi, NRF_TWI_SHORT_BB_SUSPEND_MASK);
460     }
461     // In case TWI is suspended resume its operation.
462     nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
463     nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_STARTRX);
464 
465     if (p_cb->handler)
466     {
467         p_cb->int_mask = NRF_TWI_INT_STOPPED_MASK   |
468                         NRF_TWI_INT_ERROR_MASK     |
469                         NRF_TWI_INT_TXDSENT_MASK   |
470                         NRF_TWI_INT_RXDREADY_MASK;
471         nrf_twi_int_enable(p_twi, p_cb->int_mask);
472     }
473     else
474     {
475         while ((hw_timeout > 0) &&
476                twi_transfer(p_twi,
477                             &p_cb->error,
478                             &p_cb->bytes_transferred,
479                             (uint8_t*)p_data,
480                             length,
481                             false))
482         {
483                hw_timeout--;
484         }
485 
486         if (p_cb->error)
487         {
488             uint32_t errorsrc =  nrf_twi_errorsrc_get_and_clear(p_twi);
489 
490             if (errorsrc)
491             {
492                 ret_code = twi_process_error(errorsrc);
493             }
494         }
495         if (hw_timeout <= 0)
496         {
497             nrf_twi_disable(p_twi);
498             nrf_twi_enable(p_twi);
499             ret_code = NRFX_ERROR_INTERNAL;
500         }
501     }
502     return ret_code;
503 }
504 
twi_xfer(twi_control_block_t * p_cb,NRF_TWI_Type * p_twi,nrfx_twi_xfer_desc_t const * p_xfer_desc,uint32_t flags)505 __STATIC_INLINE nrfx_err_t twi_xfer(twi_control_block_t        * p_cb,
506                                     NRF_TWI_Type               * p_twi,
507                                     nrfx_twi_xfer_desc_t const * p_xfer_desc,
508                                     uint32_t                     flags)
509 {
510 
511     nrfx_err_t err_code = NRFX_SUCCESS;
512 
513     /* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */
514     nrf_twi_int_disable(p_twi, NRF_TWI_ALL_INTS_MASK);
515 
516     if (p_cb->busy)
517     {
518         nrf_twi_int_enable(p_twi, p_cb->int_mask);
519         err_code = NRFX_ERROR_BUSY;
520         NRFX_LOG_WARNING("Function: %s, error code: %s.",
521                          __func__,
522                          NRFX_LOG_ERROR_STRING_GET(err_code));
523         return err_code;
524     }
525     else
526     {
527         p_cb->busy = (NRFX_TWI_FLAG_NO_XFER_EVT_HANDLER & flags) ? false : true;
528     }
529 
530     p_cb->flags       = flags;
531     p_cb->xfer_desc   = *p_xfer_desc;
532     p_cb->curr_length = p_xfer_desc->primary_length;
533     p_cb->p_curr_buf  = p_xfer_desc->p_primary_buf;
534     nrf_twi_address_set(p_twi, p_xfer_desc->address);
535 
536     if (p_xfer_desc->type != NRFX_TWI_XFER_RX)
537     {
538         p_cb->curr_no_stop = ((p_xfer_desc->type == NRFX_TWI_XFER_TX) &&
539                              !(flags & NRFX_TWI_FLAG_TX_NO_STOP)) ? false : true;
540 
541         err_code = twi_tx_start_transfer(p_cb,
542                                          p_twi,
543                                          p_xfer_desc->p_primary_buf,
544                                          p_xfer_desc->primary_length,
545                                          p_cb->curr_no_stop);
546     }
547     else
548     {
549         p_cb->curr_no_stop = false;
550 
551         err_code = twi_rx_start_transfer(p_cb,
552                                          p_twi,
553                                          p_xfer_desc->p_primary_buf,
554                                          p_xfer_desc->primary_length);
555     }
556     if (p_cb->handler == NULL)
557     {
558         p_cb->busy = false;
559     }
560     return err_code;
561 }
562 
nrfx_twi_is_busy(nrfx_twi_t const * p_instance)563 bool nrfx_twi_is_busy(nrfx_twi_t const * p_instance)
564 {
565     twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
566     return p_cb->busy;
567 }
568 
nrfx_twi_xfer(nrfx_twi_t const * p_instance,nrfx_twi_xfer_desc_t const * p_xfer_desc,uint32_t flags)569 nrfx_err_t nrfx_twi_xfer(nrfx_twi_t           const * p_instance,
570                          nrfx_twi_xfer_desc_t const * p_xfer_desc,
571                          uint32_t                     flags)
572 {
573 
574     nrfx_err_t err_code = NRFX_SUCCESS;
575     twi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
576 
577     // TXRX and TXTX transfers are supported only in non-blocking mode.
578     NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWI_XFER_TXRX)));
579     NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWI_XFER_TXTX)));
580 
581     NRFX_LOG_INFO("Transfer type: %s.", TRANSFER_TO_STR(p_xfer_desc->type));
582     NRFX_LOG_INFO("Transfer buffers length: primary: %d, secondary: %d.",
583                   p_xfer_desc->primary_length,
584                   p_xfer_desc->secondary_length);
585     NRFX_LOG_DEBUG("Primary buffer data:");
586     NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_primary_buf,
587                            p_xfer_desc->primary_length * sizeof(p_xfer_desc->p_primary_buf[0]));
588     NRFX_LOG_DEBUG("Secondary buffer data:");
589     NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_secondary_buf,
590                            p_xfer_desc->secondary_length * sizeof(p_xfer_desc->p_secondary_buf[0]));
591 
592     err_code = twi_xfer(p_cb, (NRF_TWI_Type  *)p_instance->p_twi, p_xfer_desc, flags);
593     NRFX_LOG_WARNING("Function: %s, error code: %s.",
594                      __func__,
595                      NRFX_LOG_ERROR_STRING_GET(err_code));
596     return err_code;
597 }
598 
nrfx_twi_tx(nrfx_twi_t const * p_instance,uint8_t address,uint8_t const * p_data,size_t length,bool no_stop)599 nrfx_err_t nrfx_twi_tx(nrfx_twi_t const * p_instance,
600                        uint8_t            address,
601                        uint8_t    const * p_data,
602                        size_t             length,
603                        bool               no_stop)
604 {
605     nrfx_twi_xfer_desc_t xfer = NRFX_TWI_XFER_DESC_TX(address, (uint8_t*)p_data, length);
606 
607     return nrfx_twi_xfer(p_instance, &xfer, no_stop ? NRFX_TWI_FLAG_TX_NO_STOP : 0);
608 }
609 
nrfx_twi_rx(nrfx_twi_t const * p_instance,uint8_t address,uint8_t * p_data,size_t length)610 nrfx_err_t nrfx_twi_rx(nrfx_twi_t const * p_instance,
611                        uint8_t            address,
612                        uint8_t *          p_data,
613                        size_t             length)
614 {
615     nrfx_twi_xfer_desc_t xfer = NRFX_TWI_XFER_DESC_RX(address, p_data, length);
616     return nrfx_twi_xfer(p_instance, &xfer, 0);
617 }
618 
nrfx_twi_data_count_get(nrfx_twi_t const * const p_instance)619 size_t nrfx_twi_data_count_get(nrfx_twi_t const * const p_instance)
620 {
621     return m_cb[p_instance->drv_inst_idx].bytes_transferred;
622 }
623 
nrfx_twi_stopped_event_get(nrfx_twi_t const * p_instance)624 uint32_t nrfx_twi_stopped_event_get(nrfx_twi_t const * p_instance)
625 {
626     return (uint32_t)nrf_twi_event_address_get(p_instance->p_twi, NRF_TWI_EVENT_STOPPED);
627 }
628 
twi_irq_handler(NRF_TWI_Type * p_twi,twi_control_block_t * p_cb)629 static void twi_irq_handler(NRF_TWI_Type * p_twi, twi_control_block_t * p_cb)
630 {
631     NRFX_ASSERT(p_cb->handler);
632 
633     if (twi_transfer(p_twi,
634                      &p_cb->error,
635                      &p_cb->bytes_transferred,
636                      p_cb->p_curr_buf,
637                      p_cb->curr_length,
638                      p_cb->curr_no_stop ))
639     {
640         return;
641     }
642 
643     if (!p_cb->error &&
644         ((p_cb->xfer_desc.type == NRFX_TWI_XFER_TXRX) ||
645          (p_cb->xfer_desc.type == NRFX_TWI_XFER_TXTX)) &&
646         p_cb->p_curr_buf == p_cb->xfer_desc.p_primary_buf)
647     {
648         p_cb->p_curr_buf   = p_cb->xfer_desc.p_secondary_buf;
649         p_cb->curr_length  = p_cb->xfer_desc.secondary_length;
650         p_cb->curr_no_stop = (p_cb->flags & NRFX_TWI_FLAG_TX_NO_STOP);
651 
652         if (p_cb->xfer_desc.type == NRFX_TWI_XFER_TXTX)
653         {
654             (void)twi_tx_start_transfer(p_cb,
655                                         p_twi,
656                                         p_cb->p_curr_buf,
657                                         p_cb->curr_length,
658                                         p_cb->curr_no_stop);
659         }
660         else
661         {
662             (void)twi_rx_start_transfer(p_cb, p_twi, p_cb->p_curr_buf, p_cb->curr_length);
663         }
664     }
665     else
666     {
667         nrfx_twi_evt_t event;
668         event.xfer_desc = p_cb->xfer_desc;
669 
670         if (p_cb->error)
671         {
672             uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(p_twi);
673             if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK)
674             {
675                 event.type = NRFX_TWI_EVT_ADDRESS_NACK;
676                 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWI_EVT_ADDRESS_NACK));
677             }
678             else if (errorsrc & NRF_TWI_ERROR_DATA_NACK)
679             {
680                 event.type = NRFX_TWI_EVT_DATA_NACK;
681                 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWI_EVT_DATA_NACK));
682             }
683         }
684         else
685         {
686             event.type = NRFX_TWI_EVT_DONE;
687             NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWI_EVT_DONE));
688         }
689 
690         p_cb->busy = false;
691 
692         if (!(NRFX_TWI_FLAG_NO_XFER_EVT_HANDLER & p_cb->flags))
693         {
694             p_cb->handler(&event, p_cb->p_context);
695         }
696     }
697 
698 }
699 
700 #if NRFX_CHECK(NRFX_TWI0_ENABLED)
nrfx_twi_0_irq_handler(void)701 void nrfx_twi_0_irq_handler(void)
702 {
703     twi_irq_handler(NRF_TWI0, &m_cb[NRFX_TWI0_INST_IDX]);
704 }
705 #endif
706 
707 #if NRFX_CHECK(NRFX_TWI1_ENABLED)
nrfx_twi_1_irq_handler(void)708 void nrfx_twi_1_irq_handler(void)
709 {
710     twi_irq_handler(NRF_TWI1, &m_cb[NRFX_TWI1_INST_IDX]);
711 }
712 #endif
713 
714 #endif // NRFX_CHECK(NRFX_TWI_ENABLED)
715