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