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_TWIS_ENABLED) 35 36 #if !(NRFX_CHECK(NRFX_TWIS0_ENABLED) || \ 37 NRFX_CHECK(NRFX_TWIS1_ENABLED) || \ 38 NRFX_CHECK(NRFX_TWIS2_ENABLED) || \ 39 NRFX_CHECK(NRFX_TWIS3_ENABLED)) 40 #error "No enabled TWIS instances. Check <nrfx_config.h>." 41 #endif 42 43 #include <nrfx_twis.h> 44 #include "prs/nrfx_prs.h" 45 46 #define NRFX_LOG_MODULE TWIS 47 #include <nrfx_log.h> 48 49 #define EVT_TO_STR(event) \ 50 (event == NRF_TWIS_EVENT_STOPPED ? "NRF_TWIS_EVENT_STOPPED" : \ 51 (event == NRF_TWIS_EVENT_ERROR ? "NRF_TWIS_EVENT_ERROR" : \ 52 (event == NRF_TWIS_EVENT_RXSTARTED ? "NRF_TWIS_EVENT_RXSTARTED" : \ 53 (event == NRF_TWIS_EVENT_TXSTARTED ? "NRF_TWIS_EVENT_TXSTARTED" : \ 54 (event == NRF_TWIS_EVENT_WRITE ? "NRF_TWIS_EVENT_WRITE" : \ 55 (event == NRF_TWIS_EVENT_READ ? "NRF_TWIS_EVENT_READ" : \ 56 "UNKNOWN EVENT")))))) 57 58 59 /** 60 * @brief Actual state of internal state machine 61 * 62 * Current substate of powered on state. 63 */ 64 typedef enum 65 { 66 NRFX_TWIS_SUBSTATE_IDLE, ///< No ongoing transmission 67 NRFX_TWIS_SUBSTATE_READ_WAITING, ///< Read request received, waiting for data 68 NRFX_TWIS_SUBSTATE_READ_PENDING, ///< Reading is actually pending (data sending) 69 NRFX_TWIS_SUBSTATE_WRITE_WAITING, ///< Write request received, waiting for data buffer 70 NRFX_TWIS_SUBSTATE_WRITE_PENDING, ///< Writing is actually pending (data receiving) 71 } nrfx_twis_substate_t; 72 73 // Control block - driver instance local data. 74 typedef struct 75 { 76 nrfx_twis_event_handler_t ev_handler; 77 // Internal copy of hardware errors flags merged with specific internal 78 // driver errors flags. 79 // This value can be changed in the interrupt and cleared in the main program. 80 // Always use Atomic load-store when updating this value in main loop. 81 volatile uint32_t error; 82 nrfx_drv_state_t state; 83 volatile nrfx_twis_substate_t substate; 84 85 volatile bool semaphore; 86 } twis_control_block_t; 87 static twis_control_block_t m_cb[NRFX_TWIS_ENABLED_COUNT]; 88 89 /** 90 * @brief Used interrupts mask 91 * 92 * Mask for all interrupts used by this library 93 */ 94 static const uint32_t m_used_ints_mask = NRF_TWIS_INT_STOPPED_MASK | 95 NRF_TWIS_INT_ERROR_MASK | 96 NRF_TWIS_INT_RXSTARTED_MASK | 97 NRF_TWIS_INT_TXSTARTED_MASK | 98 NRF_TWIS_INT_WRITE_MASK | 99 NRF_TWIS_INT_READ_MASK; 100 101 /** 102 * @brief Clear all events 103 * 104 * Function clears all actually pending events 105 */ 106 static void nrfx_twis_clear_all_events(NRF_TWIS_Type * const p_reg) 107 { 108 /* Clear all events */ 109 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_STOPPED); 110 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_ERROR); 111 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_RXSTARTED); 112 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_TXSTARTED); 113 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_WRITE); 114 nrf_twis_event_clear(p_reg, NRF_TWIS_EVENT_READ); 115 } 116 117 /** 118 * @brief Reset all the registers to known state 119 * 120 * This function clears all registers that requires it to known state. 121 * TWIS is left disabled after this function. 122 * All events are cleared. 123 * @param[out] p_reg TWIS to reset register address 124 */ 125 static inline void nrfx_twis_swreset(NRF_TWIS_Type * p_reg) 126 { 127 /* Disable TWIS */ 128 nrf_twis_disable(p_reg); 129 130 /* Disconnect pins */ 131 nrf_twis_pins_set(p_reg, ~0U, ~0U); 132 133 /* Disable interrupt global for the instance */ 134 NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_reg)); 135 136 /* Disable interrupts */ 137 nrf_twis_int_disable(p_reg, ~0U); 138 } 139 140 /** 141 * @brief Configure pin 142 * 143 * Function configures selected for work as SDA or SCL. 144 * @param pin Pin number to configure 145 */ 146 static inline void nrfx_twis_config_pin(uint32_t pin, nrf_gpio_pin_pull_t pull) 147 { 148 nrf_gpio_cfg(pin, 149 NRF_GPIO_PIN_DIR_INPUT, 150 NRF_GPIO_PIN_INPUT_DISCONNECT, 151 pull, 152 NRF_GPIO_PIN_S0D1, 153 NRF_GPIO_PIN_NOSENSE); 154 } 155 156 /** 157 * @brief Auxiliary function for getting event state on right bit possition 158 * 159 * This function calls @ref nrf_twis_event_get function but the the result 160 * is shifted to match INTEN register scheme. 161 * 162 * @param[in,out] p_reg TWIS to read event from 163 * @param ev Event code 164 * 165 * @return Selected event state shifted by @ref nrfx_event_to_bitpos 166 * 167 * @sa nrf_twis_event_get 168 * @sa nrfx_event_to_bitpos 169 */ 170 static inline uint32_t nrfx_twis_event_bit_get(NRF_TWIS_Type * p_reg, 171 nrf_twis_event_t ev) 172 { 173 return (uint32_t)nrf_twis_event_get_and_clear(p_reg, ev) << nrfx_event_to_bitpos(ev); 174 } 175 176 /** 177 * @brief Auxiliary function for checking event bit inside given flags value 178 * 179 * Function used here to check presence of the event inside given flags value. 180 * It transforms given event to bit possition and then checks if in given variable it is cleared. 181 * 182 * @param flags Flags to test 183 * @param ev Event code 184 * 185 * @retval true Flag for selected event is set 186 * @retval false Flag for selected event is cleared 187 */ 188 static inline bool nrfx_twis_check_bit(uint32_t flags, 189 nrf_twis_event_t ev) 190 { 191 return 0 != (flags & (1U << nrfx_event_to_bitpos(ev))); 192 } 193 194 /** 195 * @brief Auxiliary function for clearing event bit in given flags value 196 * 197 * Function used to clear selected event bit. 198 * 199 * @param flags Flags to process 200 * @param ev Event code to clear 201 * 202 * @return Value @em flags with cleared event bit that matches given @em ev 203 */ 204 static inline uint32_t nrfx_twis_clear_bit(uint32_t flags, 205 nrf_twis_event_t ev) 206 { 207 return flags & ~(1U << nrfx_event_to_bitpos(ev)); 208 } 209 210 static void call_event_handler(twis_control_block_t const * p_cb, 211 nrfx_twis_evt_t const * p_evt) 212 { 213 nrfx_twis_event_handler_t handler = p_cb->ev_handler; 214 if (handler != NULL) 215 { 216 handler(p_evt); 217 } 218 } 219 220 /** 221 * @brief Auxiliary function for error processing 222 * 223 * Function called when in current substate the event apears and it cannot be processed. 224 * It should be called also on ERROR event. 225 * If given @em error parameter has zero value the @ref NRFX_TWIS_ERROR_UNEXPECTED_EVENT 226 * would be set. 227 * 228 * @param p_cb Pointer to the driver instance control block. 229 * @param evt What error event raport to event handler 230 * @param error Error flags 231 */ 232 static inline void nrfx_twis_process_error(twis_control_block_t * p_cb, 233 nrfx_twis_evt_type_t evt, 234 uint32_t error) 235 { 236 if (0 == error) 237 { 238 error = NRFX_TWIS_ERROR_UNEXPECTED_EVENT; 239 } 240 nrfx_twis_evt_t evdata; 241 evdata.type = evt; 242 evdata.data.error = error; 243 244 p_cb->error |= error; 245 246 call_event_handler(p_cb, &evdata); 247 } 248 249 static void nrfx_twis_state_machine(NRF_TWIS_Type * p_reg, 250 twis_control_block_t * p_cb) 251 { 252 if (!NRFX_TWIS_NO_SYNC_MODE) 253 { 254 /* Exclude parallel processing of this function */ 255 if (p_cb->semaphore) 256 { 257 return; 258 } 259 p_cb->semaphore = 1; 260 } 261 262 /* Event data structure to be passed into event handler */ 263 nrfx_twis_evt_t evdata; 264 /* Current substate copy */ 265 nrfx_twis_substate_t substate = p_cb->substate; 266 /* Event flags */ 267 uint32_t ev = 0; 268 269 /* Get all events */ 270 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_STOPPED); 271 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_ERROR); 272 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_RXSTARTED); 273 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_TXSTARTED); 274 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_WRITE); 275 ev |= nrfx_twis_event_bit_get(p_reg, NRF_TWIS_EVENT_READ); 276 277 /* State machine */ 278 while (0 != ev) 279 { 280 switch (substate) 281 { 282 case NRFX_TWIS_SUBSTATE_IDLE: 283 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED)) 284 { 285 /* Stopped event is always allowed in IDLE state - just ignore */ 286 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED); 287 } 288 else if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ)) 289 { 290 evdata.type = NRFX_TWIS_EVT_READ_REQ; 291 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED)) 292 { 293 substate = NRFX_TWIS_SUBSTATE_READ_PENDING; 294 evdata.data.buf_req = false; 295 } 296 else 297 { 298 substate = NRFX_TWIS_SUBSTATE_READ_WAITING; 299 evdata.data.buf_req = true; 300 } 301 call_event_handler(p_cb, &evdata); 302 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_READ); 303 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED); 304 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE); 305 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED); 306 } 307 else if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE)) 308 { 309 evdata.type = NRFX_TWIS_EVT_WRITE_REQ; 310 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED)) 311 { 312 substate = NRFX_TWIS_SUBSTATE_WRITE_PENDING; 313 evdata.data.buf_req = false; 314 } 315 else 316 { 317 substate = NRFX_TWIS_SUBSTATE_WRITE_WAITING; 318 evdata.data.buf_req = true; 319 } 320 call_event_handler(p_cb, &evdata); 321 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_READ); 322 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED); 323 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_WRITE); 324 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED); 325 } 326 else 327 { 328 nrfx_twis_process_error(p_cb, 329 NRFX_TWIS_EVT_GENERAL_ERROR, 330 nrf_twis_error_source_get_and_clear(p_reg)); 331 ev = 0; 332 } 333 break; 334 case NRFX_TWIS_SUBSTATE_READ_WAITING: 335 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_TXSTARTED) || 336 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) || 337 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) || 338 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED)) 339 { 340 substate = NRFX_TWIS_SUBSTATE_READ_PENDING; 341 /* Any other bits requires further processing in PENDING substate */ 342 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_TXSTARTED); 343 } 344 else 345 { 346 nrfx_twis_process_error(p_cb, 347 NRFX_TWIS_EVT_READ_ERROR, 348 nrf_twis_error_source_get_and_clear(p_reg)); 349 substate = NRFX_TWIS_SUBSTATE_IDLE; 350 ev = 0; 351 } 352 break; 353 case NRFX_TWIS_SUBSTATE_READ_PENDING: 354 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) || 355 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) || 356 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED)) 357 { 358 evdata.type = NRFX_TWIS_EVT_READ_DONE; 359 evdata.data.tx_amount = nrf_twis_tx_amount_get(p_reg); 360 NRFX_LOG_INFO("Transfer tx_len:%d", evdata.data.tx_amount); 361 NRFX_LOG_DEBUG("Tx data:"); 362 NRFX_LOG_HEXDUMP_DEBUG((uint8_t const *)p_reg->TXD.PTR, 363 evdata.data.tx_amount * sizeof(uint8_t)); 364 call_event_handler(p_cb, &evdata); 365 /* Go to idle and repeat the state machine if READ or WRITE events detected. 366 * This time READ or WRITE would be started */ 367 substate = NRFX_TWIS_SUBSTATE_IDLE; 368 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED); 369 } 370 else 371 { 372 nrfx_twis_process_error(p_cb, 373 NRFX_TWIS_EVT_READ_ERROR, 374 nrf_twis_error_source_get_and_clear(p_reg)); 375 substate = NRFX_TWIS_SUBSTATE_IDLE; 376 ev = 0; 377 } 378 break; 379 case NRFX_TWIS_SUBSTATE_WRITE_WAITING: 380 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_RXSTARTED) || 381 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) || 382 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) || 383 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED)) 384 { 385 substate = NRFX_TWIS_SUBSTATE_WRITE_PENDING; 386 /* Any other bits requires further processing in PENDING substate */ 387 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_RXSTARTED); 388 } 389 else 390 { 391 nrfx_twis_process_error(p_cb, 392 NRFX_TWIS_EVT_WRITE_ERROR, 393 nrf_twis_error_source_get_and_clear(p_reg)); 394 substate = NRFX_TWIS_SUBSTATE_IDLE; 395 ev = 0; 396 } 397 break; 398 case NRFX_TWIS_SUBSTATE_WRITE_PENDING: 399 if (nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_WRITE) || 400 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_READ) || 401 nrfx_twis_check_bit(ev, NRF_TWIS_EVENT_STOPPED)) 402 { 403 evdata.type = NRFX_TWIS_EVT_WRITE_DONE; 404 evdata.data.rx_amount = nrf_twis_rx_amount_get(p_reg); 405 call_event_handler(p_cb, &evdata); 406 /* Go to idle and repeat the state machine if READ or WRITE events detected. 407 * This time READ or WRITE would be started */ 408 substate = NRFX_TWIS_SUBSTATE_IDLE; 409 ev = nrfx_twis_clear_bit(ev, NRF_TWIS_EVENT_STOPPED); 410 } 411 else 412 { 413 nrfx_twis_process_error(p_cb, 414 NRFX_TWIS_EVT_WRITE_ERROR, 415 nrf_twis_error_source_get_and_clear(p_reg)); 416 substate = NRFX_TWIS_SUBSTATE_IDLE; 417 ev = 0; 418 } 419 break; 420 default: 421 substate = NRFX_TWIS_SUBSTATE_IDLE; 422 /* Do not clear any events and repeat the machine */ 423 break; 424 } 425 } 426 427 p_cb->substate = substate; 428 if (!NRFX_TWIS_NO_SYNC_MODE) 429 { 430 p_cb->semaphore = 0; 431 } 432 } 433 434 435 static inline void nrfx_twis_preprocess_status(nrfx_twis_t const * p_instance) 436 { 437 if (!NRFX_TWIS_NO_SYNC_MODE) 438 { 439 NRF_TWIS_Type * p_reg = p_instance->p_reg; 440 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; 441 if (NULL == p_cb->ev_handler) 442 { 443 nrfx_twis_state_machine(p_reg, p_cb); 444 } 445 } 446 } 447 448 449 /* ------------------------------------------------------------------------- 450 * Implementation of interface functions 451 * 452 */ 453 454 455 nrfx_err_t nrfx_twis_init(nrfx_twis_t const * p_instance, 456 nrfx_twis_config_t const * p_config, 457 nrfx_twis_event_handler_t event_handler) 458 { 459 NRFX_ASSERT(p_config); 460 NRFX_ASSERT(p_config->scl != p_config->sda); 461 nrfx_err_t err_code; 462 463 NRF_TWIS_Type * p_reg = p_instance->p_reg; 464 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; 465 466 if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED) 467 { 468 err_code = NRFX_ERROR_INVALID_STATE; 469 NRFX_LOG_WARNING("Function: %s, error code: %s.", 470 __func__, 471 NRFX_LOG_ERROR_STRING_GET(err_code)); 472 return err_code; 473 } 474 475 #if NRFX_CHECK(NRFX_PRS_ENABLED) 476 static nrfx_irq_handler_t const irq_handlers[NRFX_TWIS_ENABLED_COUNT] = { 477 #if NRFX_CHECK(NRFX_TWIS0_ENABLED) 478 nrfx_twis_0_irq_handler, 479 #endif 480 #if NRFX_CHECK(NRFX_TWIS1_ENABLED) 481 nrfx_twis_1_irq_handler, 482 #endif 483 #if NRFX_CHECK(NRFX_TWIS2_ENABLED) 484 nrfx_twis_2_irq_handler, 485 #endif 486 #if NRFX_CHECK(NRFX_TWIS3_ENABLED) 487 nrfx_twis_3_irq_handler, 488 #endif 489 }; 490 if (nrfx_prs_acquire(p_reg, 491 irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS) 492 { 493 err_code = NRFX_ERROR_BUSY; 494 NRFX_LOG_WARNING("Function: %s, error code: %s.", 495 __func__, 496 NRFX_LOG_ERROR_STRING_GET(err_code)); 497 return err_code; 498 } 499 #endif // NRFX_CHECK(NRFX_PRS_ENABLED) 500 501 if (!NRFX_TWIS_ASSUME_INIT_AFTER_RESET_ONLY) 502 { 503 nrfx_twis_swreset(p_reg); 504 } 505 506 nrfx_twis_config_pin(p_config->scl, p_config->scl_pull); 507 nrfx_twis_config_pin(p_config->sda, p_config->sda_pull); 508 509 nrf_twis_config_addr_mask_t addr_mask = (nrf_twis_config_addr_mask_t)0; 510 if (0 == (p_config->addr[0] | p_config->addr[1])) 511 { 512 addr_mask = NRF_TWIS_CONFIG_ADDRESS0_MASK; 513 } 514 else 515 { 516 if (0 != p_config->addr[0]) 517 { 518 addr_mask |= NRF_TWIS_CONFIG_ADDRESS0_MASK; 519 } 520 if (0 != p_config->addr[1]) 521 { 522 addr_mask |= NRF_TWIS_CONFIG_ADDRESS1_MASK; 523 } 524 } 525 526 /* Peripheral interrupt configure 527 * (note - interrupts still needs to be configured in INTEN register. 528 * This is done in enable function) */ 529 NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_reg), 530 p_config->interrupt_priority); 531 NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_reg)); 532 533 /* Configure */ 534 nrf_twis_pins_set (p_reg, p_config->scl, p_config->sda); 535 nrf_twis_address_set (p_reg, 0, p_config->addr[0]); 536 nrf_twis_address_set (p_reg, 1, p_config->addr[1]); 537 nrf_twis_config_address_set(p_reg, addr_mask); 538 539 /* Clear semaphore */ 540 if (!NRFX_TWIS_NO_SYNC_MODE) 541 { 542 p_cb->semaphore = 0; 543 } 544 /* Set internal instance variables */ 545 p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE; 546 p_cb->ev_handler = event_handler; 547 p_cb->state = NRFX_DRV_STATE_INITIALIZED; 548 err_code = NRFX_SUCCESS; 549 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); 550 return err_code; 551 } 552 553 554 void nrfx_twis_uninit(nrfx_twis_t const * p_instance) 555 { 556 NRF_TWIS_Type * p_reg = p_instance->p_reg; 557 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; 558 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED); 559 560 TWIS_PSEL_Type psel = p_reg->PSEL; 561 562 nrfx_twis_swreset(p_reg); 563 564 /* Clear pins state if */ 565 if (!(TWIS_PSEL_SCL_CONNECT_Msk & psel.SCL)) 566 { 567 nrf_gpio_cfg_default(psel.SCL); 568 } 569 if (!(TWIS_PSEL_SDA_CONNECT_Msk & psel.SDA)) 570 { 571 nrf_gpio_cfg_default(psel.SDA); 572 } 573 574 #if NRFX_CHECK(NRFX_PRS_ENABLED) 575 nrfx_prs_release(p_reg); 576 #endif 577 578 /* Clear variables */ 579 p_cb->ev_handler = NULL; 580 p_cb->state = NRFX_DRV_STATE_UNINITIALIZED; 581 } 582 583 584 void nrfx_twis_enable(nrfx_twis_t const * p_instance) 585 { 586 NRF_TWIS_Type * p_reg = p_instance->p_reg; 587 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; 588 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED); 589 590 nrfx_twis_clear_all_events(p_reg); 591 592 /* Enable interrupts */ 593 if (NULL != p_cb->ev_handler) 594 { 595 nrf_twis_int_enable(p_reg, m_used_ints_mask); 596 } 597 598 nrf_twis_enable(p_reg); 599 p_cb->error = 0; 600 p_cb->state = NRFX_DRV_STATE_POWERED_ON; 601 p_cb->substate = NRFX_TWIS_SUBSTATE_IDLE; 602 } 603 604 605 void nrfx_twis_disable(nrfx_twis_t const * p_instance) 606 { 607 NRF_TWIS_Type * p_reg = p_instance->p_reg; 608 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; 609 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED); 610 611 nrf_twis_int_disable(p_reg, m_used_ints_mask); 612 613 nrf_twis_disable(p_reg); 614 p_cb->state = NRFX_DRV_STATE_INITIALIZED; 615 } 616 617 /* ARM recommends not using the LDREX and STREX instructions in C code. 618 * This is because the compiler might generate loads and stores between 619 * LDREX and STREX, potentially clearing the exclusive monitor set by LDREX. 620 * This recommendation also applies to the byte, halfword, and doubleword 621 * variants LDREXB, STREXB, LDREXH, STREXH, LDREXD, and STREXD. 622 * 623 * This is the reason for the function below to be implemented in assembly. 624 */ 625 //lint -save -e578 626 #if defined (__CC_ARM ) 627 static __ASM uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror) 628 { 629 mov r3, r0 630 mov r1, #0 631 nrfx_twis_error_get_and_clear_internal_try 632 ldrex r0, [r3] 633 strex r2, r1, [r3] 634 cmp r2, r1 /* did this succeed? */ 635 bne nrfx_twis_error_get_and_clear_internal_try /* no - try again */ 636 bx lr 637 } 638 #elif defined ( __GNUC__ ) 639 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror) 640 { 641 uint32_t ret; 642 uint32_t temp; 643 __ASM volatile( 644 " .syntax unified \n" 645 "nrfx_twis_error_get_and_clear_internal_try: \n" 646 " ldrex %[ret], [%[perror]] \n" 647 " strex %[temp], %[zero], [%[perror]] \n" 648 " cmp %[temp], %[zero] \n" 649 " bne nrfx_twis_error_get_and_clear_internal_try \n" 650 : /* Output */ 651 [ret]"=&l"(ret), 652 [temp]"=&l"(temp) 653 : /* Input */ 654 [zero]"l"(0), 655 [perror]"l"(perror) 656 ); 657 (void)temp; 658 return ret; 659 } 660 #elif defined ( __ICCARM__ ) 661 static uint32_t nrfx_twis_error_get_and_clear_internal(uint32_t volatile * perror) 662 { 663 uint32_t ret; 664 uint32_t temp; 665 __ASM volatile( 666 "1: \n" 667 " ldrex %[ret], [%[perror]] \n" 668 " strex %[temp], %[zero], [%[perror]] \n" 669 " cmp %[temp], %[zero] \n" 670 " bne.n 1b \n" 671 : /* Output */ 672 [ret]"=&l"(ret), 673 [temp]"=&l"(temp) 674 : /* Input */ 675 [zero]"l"(0), 676 [perror]"l"(perror) 677 ); 678 (void)temp; 679 return ret; 680 } 681 #else 682 #error Unknown compiler 683 #endif 684 //lint -restore 685 686 uint32_t nrfx_twis_error_get_and_clear(nrfx_twis_t const * p_instance) 687 { 688 nrfx_twis_preprocess_status(p_instance); 689 /* Make sure that access to error member is atomic 690 * so there is no bit that is cleared if it is not copied to local variable already. */ 691 twis_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; 692 return nrfx_twis_error_get_and_clear_internal(&p_cb->error); 693 } 694 695 696 nrfx_err_t nrfx_twis_tx_prepare(nrfx_twis_t const * p_instance, 697 void const * p_buf, 698 size_t size) 699 { 700 nrfx_err_t err_code; 701 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx]; 702 703 /* Check power state*/ 704 if (p_cb->state != NRFX_DRV_STATE_POWERED_ON) 705 { 706 err_code = NRFX_ERROR_INVALID_STATE; 707 NRFX_LOG_WARNING("Function: %s, error code: %s.", 708 __func__, 709 NRFX_LOG_ERROR_STRING_GET(err_code)); 710 return err_code; 711 } 712 /* Check data address */ 713 if (!nrfx_is_in_ram(p_buf)) 714 { 715 err_code = NRFX_ERROR_INVALID_ADDR; 716 NRFX_LOG_WARNING("Function: %s, error code: %s.", 717 __func__, 718 NRFX_LOG_ERROR_STRING_GET(err_code)); 719 return err_code; 720 } 721 /* Check data size */ 722 if ((size & TWIS_TXD_MAXCNT_MAXCNT_Msk) != size) 723 { 724 err_code = NRFX_ERROR_INVALID_LENGTH; 725 NRFX_LOG_WARNING("Function: %s, error code: %s.", 726 __func__, 727 NRFX_LOG_ERROR_STRING_GET(err_code)); 728 return err_code; 729 } 730 731 nrf_twis_tx_prepare(p_instance->p_reg, 732 (uint8_t const *)p_buf, 733 (nrf_twis_amount_t)size); 734 err_code = NRFX_SUCCESS; 735 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); 736 return err_code; 737 } 738 739 740 nrfx_err_t nrfx_twis_rx_prepare(nrfx_twis_t const * p_instance, 741 void * p_buf, 742 size_t size) 743 { 744 nrfx_err_t err_code; 745 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx]; 746 747 /* Check power state*/ 748 if (p_cb->state != NRFX_DRV_STATE_POWERED_ON) 749 { 750 err_code = NRFX_ERROR_INVALID_STATE; 751 NRFX_LOG_WARNING("Function: %s, error code: %s.", 752 __func__, 753 NRFX_LOG_ERROR_STRING_GET(err_code)); 754 return err_code; 755 } 756 /* Check data address */ 757 if (!nrfx_is_in_ram(p_buf)) 758 { 759 err_code = NRFX_ERROR_INVALID_ADDR; 760 NRFX_LOG_WARNING("Function: %s, error code: %s.", 761 __func__, 762 NRFX_LOG_ERROR_STRING_GET(err_code)); 763 return err_code; 764 } 765 /* Check data size */ 766 if ((size & TWIS_RXD_MAXCNT_MAXCNT_Msk) != size) 767 { 768 err_code = NRFX_ERROR_INVALID_LENGTH; 769 NRFX_LOG_WARNING("Function: %s, error code: %s.", 770 __func__, 771 NRFX_LOG_ERROR_STRING_GET(err_code)); 772 return err_code; 773 } 774 775 nrf_twis_rx_prepare(p_instance->p_reg, 776 (uint8_t *)p_buf, 777 (nrf_twis_amount_t)size); 778 err_code = NRFX_SUCCESS; 779 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); 780 return err_code; 781 } 782 783 784 bool nrfx_twis_is_busy(nrfx_twis_t const * p_instance) 785 { 786 nrfx_twis_preprocess_status(p_instance); 787 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx]; 788 return NRFX_TWIS_SUBSTATE_IDLE != p_cb->substate; 789 } 790 791 bool nrfx_twis_is_waiting_tx_buff(nrfx_twis_t const * p_instance) 792 { 793 nrfx_twis_preprocess_status(p_instance); 794 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx]; 795 return NRFX_TWIS_SUBSTATE_READ_WAITING == p_cb->substate; 796 } 797 798 bool nrfx_twis_is_waiting_rx_buff(nrfx_twis_t const * p_instance) 799 { 800 nrfx_twis_preprocess_status(p_instance); 801 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx]; 802 return NRFX_TWIS_SUBSTATE_WRITE_WAITING == p_cb->substate; 803 } 804 805 bool nrfx_twis_is_pending_tx(nrfx_twis_t const * p_instance) 806 { 807 nrfx_twis_preprocess_status(p_instance); 808 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx]; 809 return NRFX_TWIS_SUBSTATE_READ_PENDING == p_cb->substate; 810 } 811 812 bool nrfx_twis_is_pending_rx(nrfx_twis_t const * p_instance) 813 { 814 nrfx_twis_preprocess_status(p_instance); 815 twis_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx]; 816 return NRFX_TWIS_SUBSTATE_WRITE_PENDING == p_cb->substate; 817 } 818 819 820 #if NRFX_CHECK(NRFX_TWIS0_ENABLED) 821 void nrfx_twis_0_irq_handler(void) 822 { 823 nrfx_twis_state_machine(NRF_TWIS0, &m_cb[NRFX_TWIS0_INST_IDX]); 824 } 825 #endif 826 827 #if NRFX_CHECK(NRFX_TWIS1_ENABLED) 828 void nrfx_twis_1_irq_handler(void) 829 { 830 nrfx_twis_state_machine(NRF_TWIS1, &m_cb[NRFX_TWIS1_INST_IDX]); 831 } 832 #endif 833 834 #if NRFX_CHECK(NRFX_TWIS2_ENABLED) 835 void nrfx_twis_2_irq_handler(void) 836 { 837 nrfx_twis_state_machine(NRF_TWIS2, &m_cb[NRFX_TWIS2_INST_IDX]); 838 } 839 #endif 840 841 #if NRFX_CHECK(NRFX_TWIS3_ENABLED) 842 void nrfx_twis_3_irq_handler(void) 843 { 844 nrfx_twis_state_machine(NRF_TWIS3, &m_cb[NRFX_TWIS3_INST_IDX]); 845 } 846 #endif 847 848 #endif // NRFX_CHECK(NRFX_TWIS_ENABLED) 849