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_SPI_ENABLED) 35 36 #if !(NRFX_CHECK(NRFX_SPI0_ENABLED) || NRFX_CHECK(NRFX_SPI1_ENABLED) || \ 37 NRFX_CHECK(NRFX_SPI2_ENABLED)) 38 #error "No enabled SPI instances. Check <nrfx_config.h>." 39 #endif 40 41 #include <nrfx_spi.h> 42 #include "prs/nrfx_prs.h" 43 #include <hal/nrf_gpio.h> 44 45 #define NRFX_LOG_MODULE SPI 46 #include <nrfx_log.h> 47 48 // Control block - driver instance local data. 49 typedef struct 50 { 51 nrfx_spi_evt_handler_t handler; 52 void * p_context; 53 nrfx_spi_evt_t evt; // Keep the struct that is ready for event handler. Less memcpy. 54 nrfx_drv_state_t state; 55 volatile bool transfer_in_progress; 56 57 // [no need for 'volatile' attribute for the following members, as they 58 // are not concurrently used in IRQ handlers and main line code] 59 uint8_t ss_pin; 60 uint8_t miso_pin; 61 uint8_t orc; 62 size_t bytes_transferred; 63 64 bool abort; 65 } spi_control_block_t; 66 static spi_control_block_t m_cb[NRFX_SPI_ENABLED_COUNT]; 67 68 69 nrfx_err_t nrfx_spi_init(nrfx_spi_t const * const p_instance, 70 nrfx_spi_config_t const * p_config, 71 nrfx_spi_evt_handler_t handler, 72 void * p_context) 73 { 74 NRFX_ASSERT(p_config); 75 spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; 76 nrfx_err_t err_code; 77 78 if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED) 79 { 80 err_code = NRFX_ERROR_INVALID_STATE; 81 NRFX_LOG_WARNING("Function: %s, error code: %s.", 82 __func__, 83 NRFX_LOG_ERROR_STRING_GET(err_code)); 84 return err_code; 85 } 86 87 #if NRFX_CHECK(NRFX_PRS_ENABLED) 88 static nrfx_irq_handler_t const irq_handlers[NRFX_SPI_ENABLED_COUNT] = { 89 #if NRFX_CHECK(NRFX_SPI0_ENABLED) 90 nrfx_spi_0_irq_handler, 91 #endif 92 #if NRFX_CHECK(NRFX_SPI1_ENABLED) 93 nrfx_spi_1_irq_handler, 94 #endif 95 #if NRFX_CHECK(NRFX_SPI2_ENABLED) 96 nrfx_spi_2_irq_handler, 97 #endif 98 }; 99 if (nrfx_prs_acquire(p_instance->p_reg, 100 irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS) 101 { 102 err_code = NRFX_ERROR_BUSY; 103 NRFX_LOG_WARNING("Function: %s, error code: %s.", 104 __func__, 105 NRFX_LOG_ERROR_STRING_GET(err_code)); 106 return err_code; 107 } 108 #endif // NRFX_CHECK(NRFX_PRS_ENABLED) 109 110 p_cb->handler = handler; 111 p_cb->p_context = p_context; 112 113 uint32_t mosi_pin; 114 uint32_t miso_pin; 115 // Configure pins used by the peripheral: 116 // - SCK - output with initial value corresponding with the SPI mode used: 117 // 0 - for modes 0 and 1 (CPOL = 0), 1 - for modes 2 and 3 (CPOL = 1); 118 // according to the reference manual guidelines this pin and its input 119 // buffer must always be connected for the SPI to work. 120 if (p_config->mode <= NRF_SPI_MODE_1) 121 { 122 nrf_gpio_pin_clear(p_config->sck_pin); 123 } 124 else 125 { 126 nrf_gpio_pin_set(p_config->sck_pin); 127 } 128 nrf_gpio_cfg(p_config->sck_pin, 129 NRF_GPIO_PIN_DIR_OUTPUT, 130 NRF_GPIO_PIN_INPUT_CONNECT, 131 NRF_GPIO_PIN_NOPULL, 132 NRF_GPIO_PIN_S0S1, 133 NRF_GPIO_PIN_NOSENSE); 134 // - MOSI (optional) - output with initial value 0, 135 if (p_config->mosi_pin != NRFX_SPI_PIN_NOT_USED) 136 { 137 mosi_pin = p_config->mosi_pin; 138 nrf_gpio_pin_clear(mosi_pin); 139 nrf_gpio_cfg_output(mosi_pin); 140 } 141 else 142 { 143 mosi_pin = NRF_SPI_PIN_NOT_CONNECTED; 144 } 145 // - MISO (optional) - input, 146 if (p_config->miso_pin != NRFX_SPI_PIN_NOT_USED) 147 { 148 miso_pin = p_config->miso_pin; 149 nrf_gpio_cfg_input(miso_pin, (nrf_gpio_pin_pull_t)NRFX_SPI_MISO_PULL_CFG); 150 } 151 else 152 { 153 miso_pin = NRF_SPI_PIN_NOT_CONNECTED; 154 } 155 m_cb[p_instance->drv_inst_idx].miso_pin = p_config->miso_pin; 156 // - Slave Select (optional) - output with initial value 1 (inactive). 157 if (p_config->ss_pin != NRFX_SPI_PIN_NOT_USED) 158 { 159 nrf_gpio_pin_set(p_config->ss_pin); 160 nrf_gpio_cfg_output(p_config->ss_pin); 161 } 162 m_cb[p_instance->drv_inst_idx].ss_pin = p_config->ss_pin; 163 164 NRF_SPI_Type * p_spi = p_instance->p_reg; 165 nrf_spi_pins_set(p_spi, p_config->sck_pin, mosi_pin, miso_pin); 166 nrf_spi_frequency_set(p_spi, p_config->frequency); 167 nrf_spi_configure(p_spi, p_config->mode, p_config->bit_order); 168 169 m_cb[p_instance->drv_inst_idx].orc = p_config->orc; 170 171 if (p_cb->handler) 172 { 173 nrf_spi_int_enable(p_spi, NRF_SPI_INT_READY_MASK); 174 } 175 176 nrf_spi_enable(p_spi); 177 178 if (p_cb->handler) 179 { 180 NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg), 181 p_config->irq_priority); 182 NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg)); 183 } 184 185 p_cb->transfer_in_progress = false; 186 p_cb->state = NRFX_DRV_STATE_INITIALIZED; 187 188 err_code = NRFX_SUCCESS; 189 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); 190 return err_code; 191 } 192 193 void nrfx_spi_uninit(nrfx_spi_t const * const p_instance) 194 { 195 spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; 196 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED); 197 198 if (p_cb->handler) 199 { 200 NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg)); 201 } 202 203 NRF_SPI_Type * p_spi = p_instance->p_reg; 204 if (p_cb->handler) 205 { 206 nrf_spi_int_disable(p_spi, NRF_SPI_ALL_INTS_MASK); 207 } 208 209 if (p_cb->miso_pin != NRFX_SPI_PIN_NOT_USED) 210 { 211 nrf_gpio_cfg_default(p_cb->miso_pin); 212 } 213 nrf_spi_disable(p_spi); 214 215 #if NRFX_CHECK(NRFX_PRS_ENABLED) 216 nrfx_prs_release(p_instance->p_reg); 217 #endif 218 219 p_cb->state = NRFX_DRV_STATE_UNINITIALIZED; 220 } 221 222 static void finish_transfer(spi_control_block_t * p_cb) 223 { 224 // If Slave Select signal is used, this is the time to deactivate it. 225 if (p_cb->ss_pin != NRFX_SPI_PIN_NOT_USED) 226 { 227 nrf_gpio_pin_set(p_cb->ss_pin); 228 } 229 230 // By clearing this flag before calling the handler we allow subsequent 231 // transfers to be started directly from the handler function. 232 p_cb->transfer_in_progress = false; 233 234 p_cb->evt.type = NRFX_SPI_EVENT_DONE; 235 p_cb->handler(&p_cb->evt, p_cb->p_context); 236 } 237 238 // This function is called from the IRQ handler or, in blocking mode, directly 239 // from the 'spi_xfer' function. 240 // It returns true as long as the transfer should be continued, otherwise (when 241 // there is nothing more to send/receive) it returns false. 242 static bool transfer_byte(NRF_SPI_Type * p_spi, spi_control_block_t * p_cb) 243 { 244 // Read the data byte received in this transfer (always, because no further 245 // READY event can be generated until the current byte is read out from the 246 // RXD register), and store it in the RX buffer (only when needed). 247 volatile uint8_t rx_data = nrf_spi_rxd_get(p_spi); 248 if (p_cb->bytes_transferred < p_cb->evt.xfer_desc.rx_length) 249 { 250 p_cb->evt.xfer_desc.p_rx_buffer[p_cb->bytes_transferred] = rx_data; 251 } 252 253 ++p_cb->bytes_transferred; 254 255 // Check if there are more bytes to send or receive and write proper data 256 // byte (next one from TX buffer or over-run character) to the TXD register 257 // when needed. 258 // NOTE - we've already used 'p_cb->bytes_transferred + 1' bytes from our 259 // buffers, because we take advantage of double buffering of TXD 260 // register (so in effect one byte is still being transmitted now); 261 // see how the transfer is started in the 'spi_xfer' function. 262 size_t bytes_used = p_cb->bytes_transferred + 1; 263 264 if (p_cb->abort) 265 { 266 if (bytes_used < p_cb->evt.xfer_desc.tx_length) 267 { 268 p_cb->evt.xfer_desc.tx_length = bytes_used; 269 } 270 if (bytes_used < p_cb->evt.xfer_desc.rx_length) 271 { 272 p_cb->evt.xfer_desc.rx_length = bytes_used; 273 } 274 } 275 276 if (bytes_used < p_cb->evt.xfer_desc.tx_length) 277 { 278 nrf_spi_txd_set(p_spi, p_cb->evt.xfer_desc.p_tx_buffer[bytes_used]); 279 return true; 280 } 281 else if (bytes_used < p_cb->evt.xfer_desc.rx_length) 282 { 283 nrf_spi_txd_set(p_spi, p_cb->orc); 284 return true; 285 } 286 287 return (p_cb->bytes_transferred < p_cb->evt.xfer_desc.tx_length || 288 p_cb->bytes_transferred < p_cb->evt.xfer_desc.rx_length); 289 } 290 291 static void spi_xfer(NRF_SPI_Type * p_spi, 292 spi_control_block_t * p_cb, 293 nrfx_spi_xfer_desc_t const * p_xfer_desc) 294 { 295 p_cb->bytes_transferred = 0; 296 nrf_spi_int_disable(p_spi, NRF_SPI_INT_READY_MASK); 297 298 nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY); 299 300 // Start the transfer by writing some byte to the TXD register; 301 // if TX buffer is not empty, take the first byte from this buffer, 302 // otherwise - use over-run character. 303 nrf_spi_txd_set(p_spi, 304 (p_xfer_desc->tx_length > 0 ? p_xfer_desc->p_tx_buffer[0] : p_cb->orc)); 305 306 // TXD register is double buffered, so next byte to be transmitted can 307 // be written immediately, if needed, i.e. if TX or RX transfer is to 308 // be more that 1 byte long. Again - if there is something more in TX 309 // buffer send it, otherwise use over-run character. 310 if (p_xfer_desc->tx_length > 1) 311 { 312 nrf_spi_txd_set(p_spi, p_xfer_desc->p_tx_buffer[1]); 313 } 314 else if (p_xfer_desc->rx_length > 1) 315 { 316 nrf_spi_txd_set(p_spi, p_cb->orc); 317 } 318 319 // For blocking mode (user handler not provided) wait here for READY 320 // events (indicating that the byte from TXD register was transmitted 321 // and a new incoming byte was moved to the RXD register) and continue 322 // transaction until all requested bytes are transferred. 323 // In non-blocking mode - IRQ service routine will do this stuff. 324 if (p_cb->handler) 325 { 326 nrf_spi_int_enable(p_spi, NRF_SPI_INT_READY_MASK); 327 } 328 else 329 { 330 do { 331 while (!nrf_spi_event_check(p_spi, NRF_SPI_EVENT_READY)) {} 332 nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY); 333 NRFX_LOG_DEBUG("SPI: Event: NRF_SPI_EVENT_READY."); 334 } while (transfer_byte(p_spi, p_cb)); 335 if (p_cb->ss_pin != NRFX_SPI_PIN_NOT_USED) 336 { 337 nrf_gpio_pin_set(p_cb->ss_pin); 338 } 339 } 340 } 341 342 nrfx_err_t nrfx_spi_xfer(nrfx_spi_t const * const p_instance, 343 nrfx_spi_xfer_desc_t const * p_xfer_desc, 344 uint32_t flags) 345 { 346 spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; 347 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED); 348 NRFX_ASSERT(p_xfer_desc->p_tx_buffer != NULL || p_xfer_desc->tx_length == 0); 349 NRFX_ASSERT(p_xfer_desc->p_rx_buffer != NULL || p_xfer_desc->rx_length == 0); 350 351 nrfx_err_t err_code = NRFX_SUCCESS; 352 353 if (p_cb->transfer_in_progress) 354 { 355 err_code = NRFX_ERROR_BUSY; 356 NRFX_LOG_WARNING("Function: %s, error code: %s.", 357 __func__, 358 NRFX_LOG_ERROR_STRING_GET(err_code)); 359 return err_code; 360 } 361 else 362 { 363 if (p_cb->handler) 364 { 365 p_cb->transfer_in_progress = true; 366 } 367 } 368 369 p_cb->evt.xfer_desc = *p_xfer_desc; 370 p_cb->abort = false; 371 372 if (p_cb->ss_pin != NRFX_SPI_PIN_NOT_USED) 373 { 374 nrf_gpio_pin_clear(p_cb->ss_pin); 375 } 376 if (flags) 377 { 378 p_cb->transfer_in_progress = false; 379 err_code = NRFX_ERROR_NOT_SUPPORTED; 380 } 381 else 382 { 383 spi_xfer(p_instance->p_reg, p_cb, p_xfer_desc); 384 } 385 NRFX_LOG_INFO("Function: %s, error code: %s.", 386 __func__, 387 NRFX_LOG_ERROR_STRING_GET(err_code)); 388 return err_code; 389 } 390 391 void nrfx_spi_abort(nrfx_spi_t const * p_instance) 392 { 393 spi_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; 394 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED); 395 p_cb->abort = true; 396 } 397 398 static void irq_handler(NRF_SPI_Type * p_spi, spi_control_block_t * p_cb) 399 { 400 NRFX_ASSERT(p_cb->handler); 401 402 nrf_spi_event_clear(p_spi, NRF_SPI_EVENT_READY); 403 NRFX_LOG_DEBUG("Event: NRF_SPI_EVENT_READY."); 404 405 if (!transfer_byte(p_spi, p_cb)) 406 { 407 finish_transfer(p_cb); 408 } 409 } 410 411 #if NRFX_CHECK(NRFX_SPI0_ENABLED) 412 void nrfx_spi_0_irq_handler(void) 413 { 414 irq_handler(NRF_SPI0, &m_cb[NRFX_SPI0_INST_IDX]); 415 } 416 #endif 417 418 #if NRFX_CHECK(NRFX_SPI1_ENABLED) 419 void nrfx_spi_1_irq_handler(void) 420 { 421 irq_handler(NRF_SPI1, &m_cb[NRFX_SPI1_INST_IDX]); 422 } 423 #endif 424 425 #if NRFX_CHECK(NRFX_SPI2_ENABLED) 426 void nrfx_spi_2_irq_handler(void) 427 { 428 irq_handler(NRF_SPI2, &m_cb[NRFX_SPI2_INST_IDX]); 429 } 430 #endif 431 432 #endif // NRFX_CHECK(NRFX_SPI_ENABLED) 433