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