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