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