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_TWIM_ENABLED)
35
36 #if !(NRFX_CHECK(NRFX_TWIM0_ENABLED) || \
37 NRFX_CHECK(NRFX_TWIM1_ENABLED) || \
38 NRFX_CHECK(NRFX_TWIM2_ENABLED) || \
39 NRFX_CHECK(NRFX_TWIM3_ENABLED))
40 #error "No enabled TWIM instances. Check <nrfx_config.h>."
41 #endif
42
43 #include <nrfx_twim.h>
44 #include <hal/nrf_gpio.h>
45 #include "prs/nrfx_prs.h"
46
47 #define NRFX_LOG_MODULE TWIM
48 #include <nrfx_log.h>
49
50 #define EVT_TO_STR(event) \
51 (event == NRFX_TWIM_EVT_DONE ? "EVT_DONE" : \
52 (event == NRFX_TWIM_EVT_ADDRESS_NACK ? "EVT_ADDRESS_NACK" : \
53 (event == NRFX_TWIM_EVT_DATA_NACK ? "EVT_DATA_NACK" : \
54 (event == NRFX_TWIM_EVT_OVERRUN ? "EVT_OVERRUN" : \
55 (event == NRFX_TWIM_EVT_BUS_ERROR ? "EVT_BUS_ERROR" : \
56 "UNKNOWN ERROR")))))
57
58 #define EVT_TO_STR_TWIM(event) \
59 (event == NRF_TWIM_EVENT_STOPPED ? "NRF_TWIM_EVENT_STOPPED" : \
60 (event == NRF_TWIM_EVENT_ERROR ? "NRF_TWIM_EVENT_ERROR" : \
61 (event == NRF_TWIM_EVENT_SUSPENDED ? "NRF_TWIM_EVENT_SUSPENDED" : \
62 (event == NRF_TWIM_EVENT_RXSTARTED ? "NRF_TWIM_EVENT_RXSTARTED" : \
63 (event == NRF_TWIM_EVENT_TXSTARTED ? "NRF_TWIM_EVENT_TXSTARTED" : \
64 (event == NRF_TWIM_EVENT_LASTRX ? "NRF_TWIM_EVENT_LASTRX" : \
65 (event == NRF_TWIM_EVENT_LASTTX ? "NRF_TWIM_EVENT_LASTTX" : \
66 "UNKNOWN ERROR")))))))
67
68 #define TRANSFER_TO_STR(type) \
69 (type == NRFX_TWIM_XFER_TX ? "XFER_TX" : \
70 (type == NRFX_TWIM_XFER_RX ? "XFER_RX" : \
71 (type == NRFX_TWIM_XFER_TXRX ? "XFER_TXRX" : \
72 (type == NRFX_TWIM_XFER_TXTX ? "XFER_TXTX" : \
73 "UNKNOWN TRANSFER TYPE"))))
74
75 #define TWIM_PIN_INIT(_pin) nrf_gpio_cfg((_pin), \
76 NRF_GPIO_PIN_DIR_INPUT, \
77 NRF_GPIO_PIN_INPUT_CONNECT, \
78 NRF_GPIO_PIN_PULLUP, \
79 NRF_GPIO_PIN_S0D1, \
80 NRF_GPIO_PIN_NOSENSE)
81
82 #define TWIMX_LENGTH_VALIDATE(peripheral, drv_inst_idx, len1, len2) \
83 (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
84 NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, len1, len2))
85
86 #if NRFX_CHECK(NRFX_TWIM0_ENABLED)
87 #define TWIM0_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM0, __VA_ARGS__)
88 #else
89 #define TWIM0_LENGTH_VALIDATE(...) 0
90 #endif
91
92 #if NRFX_CHECK(NRFX_TWIM1_ENABLED)
93 #define TWIM1_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM1, __VA_ARGS__)
94 #else
95 #define TWIM1_LENGTH_VALIDATE(...) 0
96 #endif
97
98 #if NRFX_CHECK(NRFX_TWIM2_ENABLED)
99 #define TWIM2_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM2, __VA_ARGS__)
100 #else
101 #define TWIM2_LENGTH_VALIDATE(...) 0
102 #endif
103
104 #if NRFX_CHECK(NRFX_TWIM3_ENABLED)
105 #define TWIM3_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM3, __VA_ARGS__)
106 #else
107 #define TWIM3_LENGTH_VALIDATE(...) 0
108 #endif
109
110 #define TWIM_LENGTH_VALIDATE(drv_inst_idx, len1, len2) \
111 (TWIM0_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
112 TWIM1_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
113 TWIM2_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
114 TWIM3_LENGTH_VALIDATE(drv_inst_idx, len1, len2))
115
116 // Control block - driver instance local data.
117 typedef struct
118 {
119 nrfx_twim_evt_handler_t handler;
120 void * p_context;
121 volatile uint32_t int_mask;
122 nrfx_twim_xfer_desc_t xfer_desc;
123 uint32_t flags;
124 uint8_t * p_curr_buf;
125 size_t curr_length;
126 bool curr_no_stop;
127 nrfx_drv_state_t state;
128 bool error;
129 volatile bool busy;
130 bool repeated;
131 uint8_t bytes_transferred;
132 bool hold_bus_uninit;
133 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
134 nrf_twim_frequency_t bus_frequency;
135 #endif
136 } twim_control_block_t;
137
138 static twim_control_block_t m_cb[NRFX_TWIM_ENABLED_COUNT];
139
twi_process_error(uint32_t errorsrc)140 static nrfx_err_t twi_process_error(uint32_t errorsrc)
141 {
142 nrfx_err_t ret = NRFX_ERROR_INTERNAL;
143
144 if (errorsrc & NRF_TWIM_ERROR_OVERRUN)
145 {
146 ret = NRFX_ERROR_DRV_TWI_ERR_OVERRUN;
147 }
148
149 if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
150 {
151 ret = NRFX_ERROR_DRV_TWI_ERR_ANACK;
152 }
153
154 if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
155 {
156 ret = NRFX_ERROR_DRV_TWI_ERR_DNACK;
157 }
158
159 return ret;
160 }
161
xfer_completeness_check(NRF_TWIM_Type * p_twim,twim_control_block_t const * p_cb)162 static bool xfer_completeness_check(NRF_TWIM_Type * p_twim, twim_control_block_t const * p_cb)
163 {
164 // If the actual number of transferred bytes is not equal to what was requested,
165 // but there was no error signaled by the peripheral, this means that something
166 // unexpected, like a premature STOP condition, was received on the bus.
167 // In such case the peripheral has to be disabled and re-enabled, so that its
168 // internal state machine is reinitialized.
169
170 bool transfer_complete = true;
171 switch (p_cb->xfer_desc.type)
172 {
173 case NRFX_TWIM_XFER_TXTX:
174 // int_mask variable is used to determine which length should be checked
175 // against number of bytes latched in EasyDMA.
176 // NRF_TWIM_INT_SUSPENDED_MASK is configured only in first TX of TXTX transfer.
177 if (((p_cb->int_mask & NRF_TWIM_INT_SUSPENDED_MASK) &&
178 (nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.primary_length)) ||
179 (!(p_cb->int_mask & NRF_TWIM_INT_SUSPENDED_MASK) &&
180 (nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.secondary_length)))
181 {
182 transfer_complete = false;
183 }
184 break;
185 case NRFX_TWIM_XFER_TXRX:
186 if ((nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.primary_length) ||
187 (nrf_twim_rxd_amount_get(p_twim) != p_cb->xfer_desc.secondary_length))
188 {
189 transfer_complete = false;
190 }
191 break;
192 case NRFX_TWIM_XFER_TX:
193 if (nrf_twim_txd_amount_get(p_twim) != p_cb->xfer_desc.primary_length)
194 {
195 transfer_complete = false;
196 }
197 break;
198 case NRFX_TWIM_XFER_RX:
199 if (nrf_twim_rxd_amount_get(p_twim) != p_cb->xfer_desc.primary_length)
200 {
201 transfer_complete = false;
202 }
203 break;
204 default:
205 break;
206 }
207
208 if (!transfer_complete)
209 {
210 nrf_twim_disable(p_twim);
211 nrf_twim_enable(p_twim);
212 }
213
214 return transfer_complete;
215 }
216
nrfx_twim_init(nrfx_twim_t const * p_instance,nrfx_twim_config_t const * p_config,nrfx_twim_evt_handler_t event_handler,void * p_context)217 nrfx_err_t nrfx_twim_init(nrfx_twim_t const * p_instance,
218 nrfx_twim_config_t const * p_config,
219 nrfx_twim_evt_handler_t event_handler,
220 void * p_context)
221 {
222 NRFX_ASSERT(p_config);
223 NRFX_ASSERT(p_config->scl != p_config->sda);
224 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
225 nrfx_err_t err_code;
226
227 if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
228 {
229 err_code = NRFX_ERROR_INVALID_STATE;
230 NRFX_LOG_WARNING("Function: %s, error code: %s.",
231 __func__,
232 NRFX_LOG_ERROR_STRING_GET(err_code));
233 return err_code;
234 }
235
236 #if NRFX_CHECK(NRFX_PRS_ENABLED)
237 static nrfx_irq_handler_t const irq_handlers[NRFX_TWIM_ENABLED_COUNT] = {
238 #if NRFX_CHECK(NRFX_TWIM0_ENABLED)
239 nrfx_twim_0_irq_handler,
240 #endif
241 #if NRFX_CHECK(NRFX_TWIM1_ENABLED)
242 nrfx_twim_1_irq_handler,
243 #endif
244 #if NRFX_CHECK(NRFX_TWIM2_ENABLED)
245 nrfx_twim_2_irq_handler,
246 #endif
247 #if NRFX_CHECK(NRFX_TWIM3_ENABLED)
248 nrfx_twim_3_irq_handler,
249 #endif
250 };
251 if (nrfx_prs_acquire(p_instance->p_twim,
252 irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
253 {
254 err_code = NRFX_ERROR_BUSY;
255 NRFX_LOG_WARNING("Function: %s, error code: %s.",
256 __func__,
257 NRFX_LOG_ERROR_STRING_GET(err_code));
258 return err_code;
259 }
260 #endif // NRFX_CHECK(NRFX_PRS_ENABLED)
261
262 p_cb->handler = event_handler;
263 p_cb->p_context = p_context;
264 p_cb->int_mask = 0;
265 p_cb->repeated = false;
266 p_cb->busy = false;
267 p_cb->hold_bus_uninit = p_config->hold_bus_uninit;
268 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
269 p_cb->bus_frequency = (nrf_twim_frequency_t)p_config->frequency;
270 #endif
271
272 /* To secure correct signal levels on the pins used by the TWI
273 master when the system is in OFF mode, and when the TWI master is
274 disabled, these pins must be configured in the GPIO peripheral.
275 */
276 TWIM_PIN_INIT(p_config->scl);
277 TWIM_PIN_INIT(p_config->sda);
278
279 NRF_TWIM_Type * p_twim = p_instance->p_twim;
280 nrf_twim_pins_set(p_twim, p_config->scl, p_config->sda);
281 nrf_twim_frequency_set(p_twim,
282 (nrf_twim_frequency_t)p_config->frequency);
283
284 if (p_cb->handler)
285 {
286 NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_twim),
287 p_config->interrupt_priority);
288 NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_twim));
289 }
290
291 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
292
293 err_code = NRFX_SUCCESS;
294 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
295 return err_code;
296 }
297
nrfx_twim_uninit(nrfx_twim_t const * p_instance)298 void nrfx_twim_uninit(nrfx_twim_t const * p_instance)
299 {
300 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
301 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
302
303 if (p_cb->handler)
304 {
305 NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_twim));
306 }
307 nrfx_twim_disable(p_instance);
308
309 #if NRFX_CHECK(NRFX_PRS_ENABLED)
310 nrfx_prs_release(p_instance->p_twim);
311 #endif
312
313 if (!p_cb->hold_bus_uninit)
314 {
315 nrf_gpio_cfg_default(nrf_twim_scl_pin_get(p_instance->p_twim));
316 nrf_gpio_cfg_default(nrf_twim_sda_pin_get(p_instance->p_twim));
317 }
318
319 p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
320 NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
321 }
322
nrfx_twim_enable(nrfx_twim_t const * p_instance)323 void nrfx_twim_enable(nrfx_twim_t const * p_instance)
324 {
325 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
326 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
327
328 nrf_twim_enable(p_instance->p_twim);
329
330 p_cb->state = NRFX_DRV_STATE_POWERED_ON;
331 NRFX_LOG_INFO("Instance enabled: %d.", p_instance->drv_inst_idx);
332 }
333
nrfx_twim_disable(nrfx_twim_t const * p_instance)334 void nrfx_twim_disable(nrfx_twim_t const * p_instance)
335 {
336 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
337 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
338
339 NRF_TWIM_Type * p_twim = p_instance->p_twim;
340 p_cb->int_mask = 0;
341 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
342 nrf_twim_shorts_disable(p_twim, NRF_TWIM_ALL_SHORTS_MASK);
343 nrf_twim_disable(p_twim);
344
345 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
346 NRFX_LOG_INFO("Instance disabled: %d.", p_instance->drv_inst_idx);
347 }
348
349
nrfx_twim_is_busy(nrfx_twim_t const * p_instance)350 bool nrfx_twim_is_busy(nrfx_twim_t const * p_instance)
351 {
352 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
353 return p_cb->busy;
354 }
355
356
twim_list_enable_handle(NRF_TWIM_Type * p_twim,uint32_t flags)357 static void twim_list_enable_handle(NRF_TWIM_Type * p_twim, uint32_t flags)
358 {
359 if (NRFX_TWIM_FLAG_TX_POSTINC & flags)
360 {
361 nrf_twim_tx_list_enable(p_twim);
362 }
363 else
364 {
365 nrf_twim_tx_list_disable(p_twim);
366 }
367
368 if (NRFX_TWIM_FLAG_RX_POSTINC & flags)
369 {
370 nrf_twim_rx_list_enable(p_twim);
371 }
372 else
373 {
374 nrf_twim_rx_list_disable(p_twim);
375 }
376 }
twim_xfer(twim_control_block_t * p_cb,NRF_TWIM_Type * p_twim,nrfx_twim_xfer_desc_t const * p_xfer_desc,uint32_t flags)377 static nrfx_err_t twim_xfer(twim_control_block_t * p_cb,
378 NRF_TWIM_Type * p_twim,
379 nrfx_twim_xfer_desc_t const * p_xfer_desc,
380 uint32_t flags)
381 {
382 nrfx_err_t err_code = NRFX_SUCCESS;
383 nrf_twim_task_t start_task = NRF_TWIM_TASK_STARTTX;
384 p_cb->error = false;
385
386 if (!nrfx_is_in_ram(p_xfer_desc->p_primary_buf))
387 {
388 err_code = NRFX_ERROR_INVALID_ADDR;
389 NRFX_LOG_WARNING("Function: %s, error code: %s.",
390 __func__,
391 NRFX_LOG_ERROR_STRING_GET(err_code));
392 return err_code;
393 }
394 /* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */
395 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
396 if (p_cb->busy)
397 {
398 nrf_twim_int_enable(p_twim, p_cb->int_mask);
399 err_code = NRFX_ERROR_BUSY;
400 NRFX_LOG_WARNING("Function: %s, error code: %s.",
401 __func__,
402 NRFX_LOG_ERROR_STRING_GET(err_code));
403 return err_code;
404 }
405 else
406 {
407 p_cb->busy = ((NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER & flags) ||
408 (NRFX_TWIM_FLAG_REPEATED_XFER & flags)) ? false: true;
409 }
410
411 p_cb->xfer_desc = *p_xfer_desc;
412 p_cb->repeated = (flags & NRFX_TWIM_FLAG_REPEATED_XFER) ? true : false;
413 p_cb->flags = flags;
414 nrf_twim_address_set(p_twim, p_xfer_desc->address);
415
416 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
417 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
418 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
419 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
420
421 twim_list_enable_handle(p_twim, flags);
422 switch (p_xfer_desc->type)
423 {
424 case NRFX_TWIM_XFER_TXTX:
425 NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_REPEATED_XFER));
426 NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_HOLD_XFER));
427 NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER));
428 if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf))
429 {
430 err_code = NRFX_ERROR_INVALID_ADDR;
431 NRFX_LOG_WARNING("Function: %s, error code: %s.",
432 __func__,
433 NRFX_LOG_ERROR_STRING_GET(err_code));
434 return err_code;
435 }
436 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
437 nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
438 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
439 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
440 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
441 while (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
442 {}
443 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_TXSTARTED));
444 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
445 nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
446 p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK;
447 break;
448 case NRFX_TWIM_XFER_TXRX:
449 nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
450 if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf))
451 {
452 err_code = NRFX_ERROR_INVALID_ADDR;
453 NRFX_LOG_WARNING("Function: %s, error code: %s.",
454 __func__,
455 NRFX_LOG_ERROR_STRING_GET(err_code));
456 return err_code;
457 }
458 nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
459 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STARTRX_MASK |
460 NRF_TWIM_SHORT_LASTRX_STOP_MASK);
461 p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
462 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
463 break;
464 case NRFX_TWIM_XFER_TX:
465 nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
466 if (NRFX_TWIM_FLAG_TX_NO_STOP & flags)
467 {
468 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
469 p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK;
470 }
471 else
472 {
473 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
474 p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
475 }
476 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
477 break;
478 case NRFX_TWIM_XFER_RX:
479 nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
480 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTRX_STOP_MASK);
481 p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
482 start_task = NRF_TWIM_TASK_STARTRX;
483 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
484 break;
485 default:
486 err_code = NRFX_ERROR_INVALID_PARAM;
487 break;
488 }
489
490 if (!(flags & NRFX_TWIM_FLAG_HOLD_XFER) && (p_xfer_desc->type != NRFX_TWIM_XFER_TXTX))
491 {
492 nrf_twim_task_trigger(p_twim, start_task);
493 }
494
495 if (p_cb->handler)
496 {
497 if (flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER)
498 {
499 p_cb->int_mask = 0;
500 }
501
502 if (!(flags & NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK))
503 {
504 p_cb->int_mask |= NRF_TWIM_INT_STOPPED_MASK;
505 }
506
507 // Interrupts for ERROR are implicitly enabled, regardless of driver configuration.
508 p_cb->int_mask |= NRF_TWIM_INT_ERROR_MASK;
509 nrf_twim_int_enable(p_twim, p_cb->int_mask);
510
511 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
512 if ((flags & NRFX_TWIM_FLAG_HOLD_XFER) && (p_xfer_desc->type != NRFX_TWIM_XFER_RX))
513 {
514 twim_list_enable_handle(p_twim, 0);
515 p_twim->FREQUENCY = 0;
516 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
517 nrf_twim_int_enable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
518 }
519 else
520 {
521 nrf_twim_frequency_set(p_twim, p_cb->bus_frequency);
522 }
523 #endif
524 }
525 else
526 {
527 bool transmission_finished = false;
528 do {
529 if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_SUSPENDED))
530 {
531 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_SUSPENDED));
532 transmission_finished = true;
533 }
534
535 if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
536 {
537 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
538 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_STOPPED));
539 transmission_finished = true;
540 }
541
542 if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
543 {
544 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
545 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));
546
547 bool lasttx_triggered = nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_LASTTX);
548 uint32_t shorts_mask = nrf_twim_shorts_get(p_twim);
549
550 if (!(lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_STOP_MASK)))
551 {
552 // Unless LASTTX event arrived and LASTTX_STOP shortcut is active,
553 // triggering of STOP task in case of error has to be done manually.
554 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
555 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
556
557 // Mark transmission as not finished yet,
558 // as STOPPED event is expected to arrive.
559 // If LASTTX_SUSPENDED shortcut is active,
560 // NACK has been received on last byte sent
561 // and SUSPENDED event happened to be checked before ERROR,
562 // transmission will be marked as finished.
563 // In such case this flag has to be overwritten.
564 transmission_finished = false;
565 }
566
567 if (lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK))
568 {
569 // When STOP task was triggered just before SUSPEND task has taken effect,
570 // SUSPENDED event may not arrive.
571 // However if SUSPENDED arrives it always arrives after ERROR.
572 // Therefore SUSPENDED has to be cleared
573 // so it does not cause premature termination of busy loop
574 // waiting for STOPPED event to arrive.
575 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
576
577 // Mark transmission as not finished yet,
578 // for same reasons as above.
579 transmission_finished = false;
580 }
581 }
582 } while (!transmission_finished);
583
584 uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim);
585
586 p_cb->busy = false;
587
588 if (errorsrc)
589 {
590 err_code = twi_process_error(errorsrc);
591 }
592 else
593 {
594 if (!(flags & NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK) &&
595 !xfer_completeness_check(p_twim, p_cb))
596 {
597 err_code = NRFX_ERROR_INTERNAL;
598 }
599 }
600 }
601 return err_code;
602 }
603
604
nrfx_twim_xfer(nrfx_twim_t const * p_instance,nrfx_twim_xfer_desc_t const * p_xfer_desc,uint32_t flags)605 nrfx_err_t nrfx_twim_xfer(nrfx_twim_t const * p_instance,
606 nrfx_twim_xfer_desc_t const * p_xfer_desc,
607 uint32_t flags)
608 {
609 NRFX_ASSERT(TWIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
610 p_xfer_desc->primary_length,
611 p_xfer_desc->secondary_length));
612
613 nrfx_err_t err_code = NRFX_SUCCESS;
614 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
615
616 // TXRX and TXTX transfers are supported only in non-blocking mode.
617 NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXRX)));
618 NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXTX)));
619
620 NRFX_LOG_INFO("Transfer type: %s.", TRANSFER_TO_STR(p_xfer_desc->type));
621 NRFX_LOG_INFO("Transfer buffers length: primary: %d, secondary: %d.",
622 p_xfer_desc->primary_length,
623 p_xfer_desc->secondary_length);
624 NRFX_LOG_DEBUG("Primary buffer data:");
625 NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_primary_buf,
626 p_xfer_desc->primary_length * sizeof(p_xfer_desc->p_primary_buf[0]));
627 NRFX_LOG_DEBUG("Secondary buffer data:");
628 NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_secondary_buf,
629 p_xfer_desc->secondary_length * sizeof(p_xfer_desc->p_secondary_buf[0]));
630
631 err_code = twim_xfer(p_cb, (NRF_TWIM_Type *)p_instance->p_twim, p_xfer_desc, flags);
632 NRFX_LOG_WARNING("Function: %s, error code: %s.",
633 __func__,
634 NRFX_LOG_ERROR_STRING_GET(err_code));
635 return err_code;
636 }
637
nrfx_twim_start_task_get(nrfx_twim_t const * p_instance,nrfx_twim_xfer_type_t xfer_type)638 uint32_t nrfx_twim_start_task_get(nrfx_twim_t const * p_instance,
639 nrfx_twim_xfer_type_t xfer_type)
640 {
641 return nrf_twim_task_address_get(p_instance->p_twim,
642 (xfer_type != NRFX_TWIM_XFER_RX) ? NRF_TWIM_TASK_STARTTX : NRF_TWIM_TASK_STARTRX);
643 }
644
nrfx_twim_stopped_event_get(nrfx_twim_t const * p_instance)645 uint32_t nrfx_twim_stopped_event_get(nrfx_twim_t const * p_instance)
646 {
647 return nrf_twim_event_address_get(p_instance->p_twim, NRF_TWIM_EVENT_STOPPED);
648 }
649
twim_irq_handler(NRF_TWIM_Type * p_twim,twim_control_block_t * p_cb)650 static void twim_irq_handler(NRF_TWIM_Type * p_twim, twim_control_block_t * p_cb)
651 {
652
653 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
654 /* Handle only workaround case. Can be used without TWIM handler in IRQs. */
655 if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
656 {
657 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
658 nrf_twim_int_disable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
659 if (p_twim->FREQUENCY == 0)
660 {
661 // Set enable to zero to reset TWIM internal state.
662 nrf_twim_disable(p_twim);
663 nrf_twim_enable(p_twim);
664
665 // Set proper frequency.
666 nrf_twim_frequency_set(p_twim, p_cb->bus_frequency);
667 twim_list_enable_handle(p_twim, p_cb->flags);
668
669 // Start proper transmission.
670 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
671 return;
672 }
673 }
674 #endif
675
676 NRFX_ASSERT(p_cb->handler);
677
678 if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
679 {
680 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
681 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));
682 if (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
683 {
684 nrf_twim_int_disable(p_twim, p_cb->int_mask);
685 p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
686 nrf_twim_int_enable(p_twim, p_cb->int_mask);
687
688 if (!(nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_LASTTX) &&
689 (nrf_twim_shorts_get(p_twim) & NRF_TWIM_SHORT_LASTTX_STOP_MASK)))
690 {
691 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
692 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
693 }
694
695 p_cb->error = true;
696 return;
697 }
698 }
699
700 nrfx_twim_evt_t event;
701
702 if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
703 {
704 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_STOPPED));
705 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
706
707 if (!(p_cb->flags & NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK) && !p_cb->error)
708 {
709 p_cb->error = !xfer_completeness_check(p_twim, p_cb);
710 }
711
712 // Further processing of STOPPED event is valid only if NO_XFER_EVT_HANDLER
713 // setting is not used.
714 if (!(p_cb->flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER))
715 {
716 event.xfer_desc = p_cb->xfer_desc;
717 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
718 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTRX);
719 if (!p_cb->repeated || p_cb->error)
720 {
721 nrf_twim_shorts_set(p_twim, 0);
722 p_cb->int_mask = 0;
723 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
724
725 // At this point interrupt handler should not be invoked again for current transfer.
726 // If STOPPED arrived during ERROR processing,
727 // its pending interrupt should be ignored.
728 // Otherwise spurious NRFX_TWIM_EVT_DONE or NRFX_TWIM_EVT_BUS_ERROR
729 // would be passed to user's handler.
730 NRFX_IRQ_PENDING_CLEAR(nrfx_get_irq_number(p_twim));
731 }
732 }
733
734 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
735 else if (p_cb->xfer_desc.type != NRFX_TWIM_XFER_RX)
736 {
737 /* Add Anomaly 109 workaround for each potential repeated transfer starting from TX. */
738 twim_list_enable_handle(p_twim, 0);
739 p_twim->FREQUENCY = 0;
740 nrf_twim_int_enable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
741 }
742 #endif
743 }
744 else
745 {
746 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
747 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_SUSPENDED));
748 if (p_cb->xfer_desc.type == NRFX_TWIM_XFER_TX)
749 {
750 event.xfer_desc = p_cb->xfer_desc;
751 if (!p_cb->repeated)
752 {
753 nrf_twim_shorts_set(p_twim, 0);
754 p_cb->int_mask = 0;
755 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
756
757 // At this point interrupt handler should not be invoked again for current transfer.
758 // If STOPPED arrived during SUSPENDED processing,
759 // its pending interrupt should be ignored.
760 // Otherwise spurious NRFX_TWIM_EVT_DONE or NRFX_TWIM_EVT_BUS_ERROR
761 // would be passed to user's handler.
762 NRFX_IRQ_PENDING_CLEAR(nrfx_get_irq_number(p_twim));
763 }
764 }
765 else
766 {
767 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
768 p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
769 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
770 nrf_twim_int_enable(p_twim, p_cb->int_mask);
771 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
772 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
773 return;
774 }
775 }
776
777 uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim);
778 if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
779 {
780 event.type = NRFX_TWIM_EVT_ADDRESS_NACK;
781 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_ADDRESS_NACK));
782 }
783 else if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
784 {
785 event.type = NRFX_TWIM_EVT_DATA_NACK;
786 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DATA_NACK));
787 }
788 else if (errorsrc & NRF_TWIM_ERROR_OVERRUN)
789 {
790 event.type = NRFX_TWIM_EVT_OVERRUN;
791 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_OVERRUN));
792 }
793 else if (p_cb->error)
794 {
795 event.type = NRFX_TWIM_EVT_BUS_ERROR;
796 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_BUS_ERROR));
797 }
798 else
799 {
800 event.type = NRFX_TWIM_EVT_DONE;
801 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DONE));
802 }
803
804 if (!p_cb->repeated)
805 {
806 p_cb->busy = false;
807 }
808
809 if (!(p_cb->flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER) || p_cb->error)
810 {
811 p_cb->handler(&event, p_cb->p_context);
812 }
813 }
814
815 #if NRFX_CHECK(NRFX_TWIM0_ENABLED)
nrfx_twim_0_irq_handler(void)816 void nrfx_twim_0_irq_handler(void)
817 {
818 twim_irq_handler(NRF_TWIM0, &m_cb[NRFX_TWIM0_INST_IDX]);
819 }
820 #endif
821
822 #if NRFX_CHECK(NRFX_TWIM1_ENABLED)
nrfx_twim_1_irq_handler(void)823 void nrfx_twim_1_irq_handler(void)
824 {
825 twim_irq_handler(NRF_TWIM1, &m_cb[NRFX_TWIM1_INST_IDX]);
826 }
827 #endif
828
829 #if NRFX_CHECK(NRFX_TWIM2_ENABLED)
nrfx_twim_2_irq_handler(void)830 void nrfx_twim_2_irq_handler(void)
831 {
832 twim_irq_handler(NRF_TWIM2, &m_cb[NRFX_TWIM2_INST_IDX]);
833 }
834 #endif
835
836 #if NRFX_CHECK(NRFX_TWIM3_ENABLED)
nrfx_twim_3_irq_handler(void)837 void nrfx_twim_3_irq_handler(void)
838 {
839 twim_irq_handler(NRF_TWIM3, &m_cb[NRFX_TWIM3_INST_IDX]);
840 }
841 #endif
842
843 #endif // NRFX_CHECK(NRFX_TWIM_ENABLED)
844