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 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 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 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 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 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 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 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 } 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 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 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 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 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 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 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) 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) 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) 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) 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