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_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 "UNKNOWN ERROR")))
55
56 #define EVT_TO_STR_TWIM(event) \
57 (event == NRF_TWIM_EVENT_STOPPED ? "NRF_TWIM_EVENT_STOPPED" : \
58 (event == NRF_TWIM_EVENT_ERROR ? "NRF_TWIM_EVENT_ERROR" : \
59 (event == NRF_TWIM_EVENT_SUSPENDED ? "NRF_TWIM_EVENT_SUSPENDED" : \
60 (event == NRF_TWIM_EVENT_RXSTARTED ? "NRF_TWIM_EVENT_RXSTARTED" : \
61 (event == NRF_TWIM_EVENT_TXSTARTED ? "NRF_TWIM_EVENT_TXSTARTED" : \
62 (event == NRF_TWIM_EVENT_LASTRX ? "NRF_TWIM_EVENT_LASTRX" : \
63 (event == NRF_TWIM_EVENT_LASTTX ? "NRF_TWIM_EVENT_LASTTX" : \
64 "UNKNOWN ERROR")))))))
65
66 #define TRANSFER_TO_STR(type) \
67 (type == NRFX_TWIM_XFER_TX ? "XFER_TX" : \
68 (type == NRFX_TWIM_XFER_RX ? "XFER_RX" : \
69 (type == NRFX_TWIM_XFER_TXRX ? "XFER_TXRX" : \
70 (type == NRFX_TWIM_XFER_TXTX ? "XFER_TXTX" : \
71 "UNKNOWN TRANSFER TYPE"))))
72
73 #define TWIM_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 TWIMX_LENGTH_VALIDATE(peripheral, drv_inst_idx, len1, len2) \
81 (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
82 NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, len1, len2))
83
84 #if NRFX_CHECK(NRFX_TWIM0_ENABLED)
85 #define TWIM0_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM0, __VA_ARGS__)
86 #else
87 #define TWIM0_LENGTH_VALIDATE(...) 0
88 #endif
89
90 #if NRFX_CHECK(NRFX_TWIM1_ENABLED)
91 #define TWIM1_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM1, __VA_ARGS__)
92 #else
93 #define TWIM1_LENGTH_VALIDATE(...) 0
94 #endif
95
96 #if NRFX_CHECK(NRFX_TWIM2_ENABLED)
97 #define TWIM2_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM2, __VA_ARGS__)
98 #else
99 #define TWIM2_LENGTH_VALIDATE(...) 0
100 #endif
101
102 #if NRFX_CHECK(NRFX_TWIM3_ENABLED)
103 #define TWIM3_LENGTH_VALIDATE(...) TWIMX_LENGTH_VALIDATE(TWIM3, __VA_ARGS__)
104 #else
105 #define TWIM3_LENGTH_VALIDATE(...) 0
106 #endif
107
108 #define TWIM_LENGTH_VALIDATE(drv_inst_idx, len1, len2) \
109 (TWIM0_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
110 TWIM1_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
111 TWIM2_LENGTH_VALIDATE(drv_inst_idx, len1, len2) || \
112 TWIM3_LENGTH_VALIDATE(drv_inst_idx, len1, len2))
113
114 // Control block - driver instance local data.
115 typedef struct
116 {
117 nrfx_twim_evt_handler_t handler;
118 void * p_context;
119 volatile uint32_t int_mask;
120 nrfx_twim_xfer_desc_t xfer_desc;
121 uint32_t flags;
122 uint8_t * p_curr_buf;
123 size_t curr_length;
124 bool curr_no_stop;
125 nrfx_drv_state_t state;
126 bool error;
127 volatile bool busy;
128 bool repeated;
129 uint8_t bytes_transferred;
130 bool hold_bus_uninit;
131 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
132 nrf_twim_frequency_t bus_frequency;
133 #endif
134 } twim_control_block_t;
135
136 static twim_control_block_t m_cb[NRFX_TWIM_ENABLED_COUNT];
137
twi_process_error(uint32_t errorsrc)138 static nrfx_err_t twi_process_error(uint32_t errorsrc)
139 {
140 nrfx_err_t ret = NRFX_ERROR_INTERNAL;
141
142 if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
143 {
144 ret = NRFX_ERROR_DRV_TWI_ERR_ANACK;
145 }
146
147 if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
148 {
149 ret = NRFX_ERROR_DRV_TWI_ERR_DNACK;
150 }
151
152 return ret;
153 }
154
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)155 nrfx_err_t nrfx_twim_init(nrfx_twim_t const * p_instance,
156 nrfx_twim_config_t const * p_config,
157 nrfx_twim_evt_handler_t event_handler,
158 void * p_context)
159 {
160 NRFX_ASSERT(p_config);
161 NRFX_ASSERT(p_config->scl != p_config->sda);
162 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
163 nrfx_err_t err_code;
164
165 if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
166 {
167 err_code = NRFX_ERROR_INVALID_STATE;
168 NRFX_LOG_WARNING("Function: %s, error code: %s.",
169 __func__,
170 NRFX_LOG_ERROR_STRING_GET(err_code));
171 return err_code;
172 }
173
174 #if NRFX_CHECK(NRFX_PRS_ENABLED)
175 static nrfx_irq_handler_t const irq_handlers[NRFX_TWIM_ENABLED_COUNT] = {
176 #if NRFX_CHECK(NRFX_TWIM0_ENABLED)
177 nrfx_twim_0_irq_handler,
178 #endif
179 #if NRFX_CHECK(NRFX_TWIM1_ENABLED)
180 nrfx_twim_1_irq_handler,
181 #endif
182 #if NRFX_CHECK(NRFX_TWIM2_ENABLED)
183 nrfx_twim_2_irq_handler,
184 #endif
185 #if NRFX_CHECK(NRFX_TWIM3_ENABLED)
186 nrfx_twim_3_irq_handler,
187 #endif
188 };
189 if (nrfx_prs_acquire(p_instance->p_twim,
190 irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
191 {
192 err_code = NRFX_ERROR_BUSY;
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 #endif // NRFX_CHECK(NRFX_PRS_ENABLED)
199
200 p_cb->handler = event_handler;
201 p_cb->p_context = p_context;
202 p_cb->int_mask = 0;
203 p_cb->repeated = false;
204 p_cb->busy = false;
205 p_cb->hold_bus_uninit = p_config->hold_bus_uninit;
206 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
207 p_cb->bus_frequency = (nrf_twim_frequency_t)p_config->frequency;
208 #endif
209
210 /* To secure correct signal levels on the pins used by the TWI
211 master when the system is in OFF mode, and when the TWI master is
212 disabled, these pins must be configured in the GPIO peripheral.
213 */
214 TWIM_PIN_INIT(p_config->scl);
215 TWIM_PIN_INIT(p_config->sda);
216
217 NRF_TWIM_Type * p_twim = p_instance->p_twim;
218 nrf_twim_pins_set(p_twim, p_config->scl, p_config->sda);
219 nrf_twim_frequency_set(p_twim,
220 (nrf_twim_frequency_t)p_config->frequency);
221
222 if (p_cb->handler)
223 {
224 NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_twim),
225 p_config->interrupt_priority);
226 NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_twim));
227 }
228
229 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
230
231 err_code = NRFX_SUCCESS;
232 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
233 return err_code;
234 }
235
nrfx_twim_uninit(nrfx_twim_t const * p_instance)236 void nrfx_twim_uninit(nrfx_twim_t const * p_instance)
237 {
238 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
239 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
240
241 if (p_cb->handler)
242 {
243 NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_twim));
244 }
245 nrfx_twim_disable(p_instance);
246
247 #if NRFX_CHECK(NRFX_PRS_ENABLED)
248 nrfx_prs_release(p_instance->p_twim);
249 #endif
250
251 if (!p_cb->hold_bus_uninit)
252 {
253 nrf_gpio_cfg_default(p_instance->p_twim->PSEL.SCL);
254 nrf_gpio_cfg_default(p_instance->p_twim->PSEL.SDA);
255 }
256
257 p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
258 NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
259 }
260
nrfx_twim_enable(nrfx_twim_t const * p_instance)261 void nrfx_twim_enable(nrfx_twim_t const * p_instance)
262 {
263 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
264 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
265
266 nrf_twim_enable(p_instance->p_twim);
267
268 p_cb->state = NRFX_DRV_STATE_POWERED_ON;
269 NRFX_LOG_INFO("Instance enabled: %d.", p_instance->drv_inst_idx);
270 }
271
nrfx_twim_disable(nrfx_twim_t const * p_instance)272 void nrfx_twim_disable(nrfx_twim_t const * p_instance)
273 {
274 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
275 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
276
277 NRF_TWIM_Type * p_twim = p_instance->p_twim;
278 p_cb->int_mask = 0;
279 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
280 nrf_twim_shorts_disable(p_twim, NRF_TWIM_ALL_SHORTS_MASK);
281 nrf_twim_disable(p_twim);
282
283 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
284 NRFX_LOG_INFO("Instance disabled: %d.", p_instance->drv_inst_idx);
285 }
286
287
nrfx_twim_is_busy(nrfx_twim_t const * p_instance)288 bool nrfx_twim_is_busy(nrfx_twim_t const * p_instance)
289 {
290 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
291 return p_cb->busy;
292 }
293
294
twim_list_enable_handle(NRF_TWIM_Type * p_twim,uint32_t flags)295 __STATIC_INLINE void twim_list_enable_handle(NRF_TWIM_Type * p_twim, uint32_t flags)
296 {
297 if (NRFX_TWIM_FLAG_TX_POSTINC & flags)
298 {
299 nrf_twim_tx_list_enable(p_twim);
300 }
301 else
302 {
303 nrf_twim_tx_list_disable(p_twim);
304 }
305
306 if (NRFX_TWIM_FLAG_RX_POSTINC & flags)
307 {
308 nrf_twim_rx_list_enable(p_twim);
309 }
310 else
311 {
312 nrf_twim_rx_list_disable(p_twim);
313 }
314 }
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)315 __STATIC_INLINE nrfx_err_t twim_xfer(twim_control_block_t * p_cb,
316 NRF_TWIM_Type * p_twim,
317 nrfx_twim_xfer_desc_t const * p_xfer_desc,
318 uint32_t flags)
319 {
320 nrfx_err_t err_code = NRFX_SUCCESS;
321 nrf_twim_task_t start_task = NRF_TWIM_TASK_STARTTX;
322 nrf_twim_event_t evt_to_wait = NRF_TWIM_EVENT_STOPPED;
323
324 if (!nrfx_is_in_ram(p_xfer_desc->p_primary_buf))
325 {
326 err_code = NRFX_ERROR_INVALID_ADDR;
327 NRFX_LOG_WARNING("Function: %s, error code: %s.",
328 __func__,
329 NRFX_LOG_ERROR_STRING_GET(err_code));
330 return err_code;
331 }
332 /* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */
333 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
334 if (p_cb->busy)
335 {
336 nrf_twim_int_enable(p_twim, p_cb->int_mask);
337 err_code = NRFX_ERROR_BUSY;
338 NRFX_LOG_WARNING("Function: %s, error code: %s.",
339 __func__,
340 NRFX_LOG_ERROR_STRING_GET(err_code));
341 return err_code;
342 }
343 else
344 {
345 p_cb->busy = ((NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER & flags) ||
346 (NRFX_TWIM_FLAG_REPEATED_XFER & flags)) ? false: true;
347 }
348
349 p_cb->xfer_desc = *p_xfer_desc;
350 p_cb->repeated = (flags & NRFX_TWIM_FLAG_REPEATED_XFER) ? true : false;
351 nrf_twim_address_set(p_twim, p_xfer_desc->address);
352
353 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
354 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
355
356 twim_list_enable_handle(p_twim, flags);
357 switch (p_xfer_desc->type)
358 {
359 case NRFX_TWIM_XFER_TXTX:
360 NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_REPEATED_XFER));
361 NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_HOLD_XFER));
362 NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER));
363 if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf))
364 {
365 err_code = NRFX_ERROR_INVALID_ADDR;
366 NRFX_LOG_WARNING("Function: %s, error code: %s.",
367 __func__,
368 NRFX_LOG_ERROR_STRING_GET(err_code));
369 return err_code;
370 }
371 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
372 nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
373 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
374 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
375 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
376 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
377 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
378 while (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
379 {}
380 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_TXSTARTED));
381 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
382 nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
383 p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK | NRF_TWIM_INT_ERROR_MASK;
384 break;
385 case NRFX_TWIM_XFER_TXRX:
386 nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
387 if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf))
388 {
389 err_code = NRFX_ERROR_INVALID_ADDR;
390 NRFX_LOG_WARNING("Function: %s, error code: %s.",
391 __func__,
392 NRFX_LOG_ERROR_STRING_GET(err_code));
393 return err_code;
394 }
395 nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length);
396 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STARTRX_MASK |
397 NRF_TWIM_SHORT_LASTRX_STOP_MASK);
398 p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
399 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
400 break;
401 case NRFX_TWIM_XFER_TX:
402 nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
403 if (NRFX_TWIM_FLAG_TX_NO_STOP & flags)
404 {
405 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK);
406 p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK | NRF_TWIM_INT_ERROR_MASK;
407 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
408 evt_to_wait = NRF_TWIM_EVENT_SUSPENDED;
409 }
410 else
411 {
412 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
413 p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
414 }
415 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
416 break;
417 case NRFX_TWIM_XFER_RX:
418 nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length);
419 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTRX_STOP_MASK);
420 p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
421 start_task = NRF_TWIM_TASK_STARTRX;
422 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
423 break;
424 default:
425 err_code = NRFX_ERROR_INVALID_PARAM;
426 break;
427 }
428
429 if (!(flags & NRFX_TWIM_FLAG_HOLD_XFER) && (p_xfer_desc->type != NRFX_TWIM_XFER_TXTX))
430 {
431 nrf_twim_task_trigger(p_twim, start_task);
432 }
433
434 if (p_cb->handler)
435 {
436 if (flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER)
437 {
438 p_cb->int_mask = NRF_TWIM_INT_ERROR_MASK;
439 }
440 nrf_twim_int_enable(p_twim, p_cb->int_mask);
441
442 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
443 if ((flags & NRFX_TWIM_FLAG_HOLD_XFER) && ((p_xfer_desc->type == NRFX_TWIM_XFER_TX) ||
444 (p_xfer_desc->type == NRFX_TWIM_XFER_TXRX)))
445 {
446 p_cb->flags = flags;
447 twim_list_enable_handle(p_twim, 0);
448 p_twim->FREQUENCY = 0;
449 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
450 nrf_twim_int_enable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
451 }
452 #endif
453 }
454 else
455 {
456 while (!nrf_twim_event_check(p_twim, evt_to_wait))
457 {
458 if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
459 {
460 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));
461 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
462 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
463 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
464 evt_to_wait = NRF_TWIM_EVENT_STOPPED;
465 }
466 }
467
468 uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim);
469
470 p_cb->busy = false;
471
472 if (errorsrc)
473 {
474 err_code = twi_process_error(errorsrc);
475 }
476 }
477 return err_code;
478 }
479
480
nrfx_twim_xfer(nrfx_twim_t const * p_instance,nrfx_twim_xfer_desc_t const * p_xfer_desc,uint32_t flags)481 nrfx_err_t nrfx_twim_xfer(nrfx_twim_t const * p_instance,
482 nrfx_twim_xfer_desc_t const * p_xfer_desc,
483 uint32_t flags)
484 {
485 NRFX_ASSERT(TWIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
486 p_xfer_desc->primary_length,
487 p_xfer_desc->secondary_length));
488
489 nrfx_err_t err_code = NRFX_SUCCESS;
490 twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
491
492 // TXRX and TXTX transfers are supported only in non-blocking mode.
493 NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXRX)));
494 NRFX_ASSERT( !((p_cb->handler == NULL) && (p_xfer_desc->type == NRFX_TWIM_XFER_TXTX)));
495
496 NRFX_LOG_INFO("Transfer type: %s.", TRANSFER_TO_STR(p_xfer_desc->type));
497 NRFX_LOG_INFO("Transfer buffers length: primary: %d, secondary: %d.",
498 p_xfer_desc->primary_length,
499 p_xfer_desc->secondary_length);
500 NRFX_LOG_DEBUG("Primary buffer data:");
501 NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_primary_buf,
502 p_xfer_desc->primary_length * sizeof(p_xfer_desc->p_primary_buf[0]));
503 NRFX_LOG_DEBUG("Secondary buffer data:");
504 NRFX_LOG_HEXDUMP_DEBUG(p_xfer_desc->p_secondary_buf,
505 p_xfer_desc->secondary_length * sizeof(p_xfer_desc->p_secondary_buf[0]));
506
507 err_code = twim_xfer(p_cb, (NRF_TWIM_Type *)p_instance->p_twim, p_xfer_desc, flags);
508 NRFX_LOG_WARNING("Function: %s, error code: %s.",
509 __func__,
510 NRFX_LOG_ERROR_STRING_GET(err_code));
511 return err_code;
512 }
513
nrfx_twim_tx(nrfx_twim_t const * p_instance,uint8_t address,uint8_t const * p_data,size_t length,bool no_stop)514 nrfx_err_t nrfx_twim_tx(nrfx_twim_t const * p_instance,
515 uint8_t address,
516 uint8_t const * p_data,
517 size_t length,
518 bool no_stop)
519 {
520 nrfx_twim_xfer_desc_t xfer = NRFX_TWIM_XFER_DESC_TX(address, (uint8_t*)p_data, length);
521
522 return nrfx_twim_xfer(p_instance, &xfer, no_stop ? NRFX_TWIM_FLAG_TX_NO_STOP : 0);
523 }
524
nrfx_twim_rx(nrfx_twim_t const * p_instance,uint8_t address,uint8_t * p_data,size_t length)525 nrfx_err_t nrfx_twim_rx(nrfx_twim_t const * p_instance,
526 uint8_t address,
527 uint8_t * p_data,
528 size_t length)
529 {
530 nrfx_twim_xfer_desc_t xfer = NRFX_TWIM_XFER_DESC_RX(address, p_data, length);
531 return nrfx_twim_xfer(p_instance, &xfer, 0);
532 }
533
nrfx_twim_start_task_get(nrfx_twim_t const * p_instance,nrfx_twim_xfer_type_t xfer_type)534 uint32_t nrfx_twim_start_task_get(nrfx_twim_t const * p_instance,
535 nrfx_twim_xfer_type_t xfer_type)
536 {
537 return (uint32_t)nrf_twim_task_address_get(p_instance->p_twim,
538 (xfer_type != NRFX_TWIM_XFER_RX) ? NRF_TWIM_TASK_STARTTX : NRF_TWIM_TASK_STARTRX);
539 }
540
nrfx_twim_stopped_event_get(nrfx_twim_t const * p_instance)541 uint32_t nrfx_twim_stopped_event_get(nrfx_twim_t const * p_instance)
542 {
543 return (uint32_t)nrf_twim_event_address_get(p_instance->p_twim, NRF_TWIM_EVENT_STOPPED);
544 }
545
twim_irq_handler(NRF_TWIM_Type * p_twim,twim_control_block_t * p_cb)546 static void twim_irq_handler(NRF_TWIM_Type * p_twim, twim_control_block_t * p_cb)
547 {
548
549 #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
550 /* Handle only workaround case. Can be used without TWIM handler in IRQs. */
551 if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED))
552 {
553 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED);
554 nrf_twim_int_disable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK);
555 if (p_twim->FREQUENCY == 0)
556 {
557 // Set enable to zero to reset TWIM internal state.
558 nrf_twim_disable(p_twim);
559 nrf_twim_enable(p_twim);
560
561 // Set proper frequency.
562 nrf_twim_frequency_set(p_twim, p_cb->bus_frequency);
563 twim_list_enable_handle(p_twim, p_cb->flags);
564
565 // Start proper transmission.
566 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
567 return;
568 }
569 }
570 #endif
571
572 NRFX_ASSERT(p_cb->handler);
573
574 if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
575 {
576 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);
577 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR));
578 if (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
579 {
580 nrf_twim_int_disable(p_twim, p_cb->int_mask);
581 p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK;
582 nrf_twim_int_enable(p_twim, p_cb->int_mask);
583
584 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
585 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);
586 return;
587 }
588 }
589
590 nrfx_twim_evt_t event;
591
592 if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
593 {
594 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_STOPPED));
595 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
596 event.xfer_desc = p_cb->xfer_desc;
597 if (p_cb->error)
598 {
599
600 event.xfer_desc.primary_length = (p_cb->xfer_desc.type == NRFX_TWIM_XFER_RX) ?
601 nrf_twim_rxd_amount_get(p_twim) : nrf_twim_txd_amount_get(p_twim);
602 event.xfer_desc.secondary_length = (p_cb->xfer_desc.type == NRFX_TWIM_XFER_TXRX) ?
603 nrf_twim_rxd_amount_get(p_twim) : nrf_twim_txd_amount_get(p_twim);
604
605 }
606 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX);
607 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTRX);
608 if (!p_cb->repeated || p_cb->error)
609 {
610 nrf_twim_shorts_set(p_twim, 0);
611 p_cb->int_mask = 0;
612 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
613 }
614 }
615 else
616 {
617 nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);
618 NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_SUSPENDED));
619 if (p_cb->xfer_desc.type == NRFX_TWIM_XFER_TX)
620 {
621 event.xfer_desc = p_cb->xfer_desc;
622 if (!p_cb->repeated)
623 {
624 nrf_twim_shorts_set(p_twim, 0);
625 p_cb->int_mask = 0;
626 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
627 }
628 }
629 else
630 {
631 nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK);
632 p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK;
633 nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK);
634 nrf_twim_int_enable(p_twim, p_cb->int_mask);
635 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX);
636 nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
637 return;
638 }
639 }
640
641 uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim);
642 if (errorsrc & NRF_TWIM_ERROR_ADDRESS_NACK)
643 {
644 event.type = NRFX_TWIM_EVT_ADDRESS_NACK;
645 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_ADDRESS_NACK));
646 }
647 else if (errorsrc & NRF_TWIM_ERROR_DATA_NACK)
648 {
649 event.type = NRFX_TWIM_EVT_DATA_NACK;
650 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DATA_NACK));
651 }
652 else
653 {
654 event.type = NRFX_TWIM_EVT_DONE;
655 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRFX_TWIM_EVT_DONE));
656 }
657
658 if (!p_cb->repeated)
659 {
660 p_cb->busy = false;
661 }
662 p_cb->handler(&event, p_cb->p_context);
663 }
664
665 #if NRFX_CHECK(NRFX_TWIM0_ENABLED)
nrfx_twim_0_irq_handler(void)666 void nrfx_twim_0_irq_handler(void)
667 {
668 twim_irq_handler(NRF_TWIM0, &m_cb[NRFX_TWIM0_INST_IDX]);
669 }
670 #endif
671
672 #if NRFX_CHECK(NRFX_TWIM1_ENABLED)
nrfx_twim_1_irq_handler(void)673 void nrfx_twim_1_irq_handler(void)
674 {
675 twim_irq_handler(NRF_TWIM1, &m_cb[NRFX_TWIM1_INST_IDX]);
676 }
677 #endif
678
679 #if NRFX_CHECK(NRFX_TWIM2_ENABLED)
nrfx_twim_2_irq_handler(void)680 void nrfx_twim_2_irq_handler(void)
681 {
682 twim_irq_handler(NRF_TWIM2, &m_cb[NRFX_TWIM2_INST_IDX]);
683 }
684 #endif
685
686 #if NRFX_CHECK(NRFX_TWIM3_ENABLED)
nrfx_twim_3_irq_handler(void)687 void nrfx_twim_3_irq_handler(void)
688 {
689 twim_irq_handler(NRF_TWIM3, &m_cb[NRFX_TWIM3_INST_IDX]);
690 }
691 #endif
692
693 #endif // NRFX_CHECK(NRFX_TWIM_ENABLED)
694