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 #ifndef NRFX_SPIM_H__ 33 #define NRFX_SPIM_H__ 34 35 #include <nrfx.h> 36 #include <hal/nrf_spim.h> 37 38 #ifdef __cplusplus 39 extern "C" { 40 #endif 41 42 /** 43 * @defgroup nrfx_spim SPIM driver 44 * @{ 45 * @ingroup nrf_spim 46 * @brief SPIM peripheral driver. 47 */ 48 49 /** 50 * @brief SPIM master driver instance data structure. 51 */ 52 typedef struct 53 { 54 NRF_SPIM_Type * p_reg; ///< Pointer to a structure with SPIM registers. 55 uint8_t drv_inst_idx; ///< Driver instance index. 56 } nrfx_spim_t; 57 58 enum { 59 #if NRFX_CHECK(NRFX_SPIM0_ENABLED) 60 NRFX_SPIM0_INST_IDX, 61 #endif 62 #if NRFX_CHECK(NRFX_SPIM1_ENABLED) 63 NRFX_SPIM1_INST_IDX, 64 #endif 65 #if NRFX_CHECK(NRFX_SPIM2_ENABLED) 66 NRFX_SPIM2_INST_IDX, 67 #endif 68 #if NRFX_CHECK(NRFX_SPIM3_ENABLED) 69 NRFX_SPIM3_INST_IDX, 70 #endif 71 NRFX_SPIM_ENABLED_COUNT 72 }; 73 74 /** 75 * @brief Macro for creating an SPIM master driver instance. 76 */ 77 #define NRFX_SPIM_INSTANCE(id) \ 78 { \ 79 .p_reg = NRFX_CONCAT_2(NRF_SPIM, id), \ 80 .drv_inst_idx = NRFX_CONCAT_3(NRFX_SPIM, id, _INST_IDX), \ 81 } 82 83 /** 84 * @brief This value can be provided instead of a pin number for signals MOSI, 85 * MISO, and Slave Select to specify that the given signal is not used and 86 * therefore does not need to be connected to a pin. 87 */ 88 #define NRFX_SPIM_PIN_NOT_USED 0xFF 89 90 /** 91 * @brief SPIM master driver instance configuration structure. 92 */ 93 typedef struct 94 { 95 uint8_t sck_pin; ///< SCK pin number. 96 uint8_t mosi_pin; ///< MOSI pin number (optional). 97 /**< Set to @ref NRFX_SPIM_PIN_NOT_USED 98 * if this signal is not needed. */ 99 uint8_t miso_pin; ///< MISO pin number (optional). 100 /**< Set to @ref NRFX_SPIM_PIN_NOT_USED 101 * if this signal is not needed. */ 102 uint8_t ss_pin; ///< Slave Select pin number (optional). 103 /**< Set to @ref NRFX_SPIM_PIN_NOT_USED 104 * if this signal is not needed. */ 105 bool ss_active_high; ///< Polarity of the Slave Select pin during transmission. 106 uint8_t irq_priority; ///< Interrupt priority. 107 uint8_t orc; ///< Over-run character. 108 /**< This character is used when all bytes from the TX buffer are sent, 109 but the transfer continues due to RX. */ 110 nrf_spim_frequency_t frequency; ///< SPI frequency. 111 nrf_spim_mode_t mode; ///< SPI mode. 112 nrf_spim_bit_order_t bit_order; ///< SPI bit order. 113 #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__) 114 uint8_t dcx_pin; ///< D/CX pin number (optional). 115 uint8_t rx_delay; ///< Sample delay for input serial data on MISO. 116 /**< The value specifies the delay, in number of 64 MHz clock cycles 117 * (15.625 ns), from the the sampling edge of SCK (leading edge for 118 * CONFIG.CPHA = 0, trailing edge for CONFIG.CPHA = 1) until 119 * the input serial data is sampled.*/ 120 bool use_hw_ss; ///< Indication to use software or hardware controlled Slave Select pin. 121 uint8_t ss_duration; ///< Slave Select duration before and after transmission. 122 /**< Minimum duration between the edge of CSN and the edge of SCK and minimum 123 * duration of CSN must stay inactive between transactions. 124 * The value is specified in number of 64 MHz clock cycles (15.625 ns). 125 * Supported only for hardware controlled Slave Select.*/ 126 #endif 127 } nrfx_spim_config_t; 128 129 #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__) 130 /** 131 * @brief SPIM master instance extended default configuration. 132 */ 133 #define NRFX_SPIM_DEFAULT_EXTENDED_CONFIG \ 134 .dcx_pin = NRFX_SPIM_PIN_NOT_USED, \ 135 .rx_delay = 0x02, \ 136 .ss_duration = 0x02, \ 137 .use_hw_ss = false, 138 #else 139 #define NRFX_SPIM_DEFAULT_EXTENDED_CONFIG 140 #endif 141 142 /** 143 * @brief SPIM master instance default configuration. 144 */ 145 #define NRFX_SPIM_DEFAULT_CONFIG \ 146 { \ 147 .sck_pin = NRFX_SPIM_PIN_NOT_USED, \ 148 .mosi_pin = NRFX_SPIM_PIN_NOT_USED, \ 149 .miso_pin = NRFX_SPIM_PIN_NOT_USED, \ 150 .ss_pin = NRFX_SPIM_PIN_NOT_USED, \ 151 .ss_active_high = false, \ 152 .irq_priority = NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY, \ 153 .orc = 0xFF, \ 154 .frequency = NRF_SPIM_FREQ_4M, \ 155 .mode = NRF_SPIM_MODE_0, \ 156 .bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST, \ 157 NRFX_SPIM_DEFAULT_EXTENDED_CONFIG \ 158 } 159 160 #define NRFX_SPIM_FLAG_TX_POSTINC (1UL << 0) /**< TX buffer address incremented after transfer. */ 161 #define NRFX_SPIM_FLAG_RX_POSTINC (1UL << 1) /**< RX buffer address incremented after transfer. */ 162 #define NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER (1UL << 2) /**< Interrupt after each transfer is suppressed, and the event handler is not called. */ 163 #define NRFX_SPIM_FLAG_HOLD_XFER (1UL << 3) /**< Set up the transfer but do not start it. */ 164 #define NRFX_SPIM_FLAG_REPEATED_XFER (1UL << 4) /**< Flag indicating that the transfer will be executed multiple times. */ 165 166 /** 167 * @brief Single transfer descriptor structure. 168 */ 169 typedef struct 170 { 171 uint8_t const * p_tx_buffer; ///< Pointer to TX buffer. 172 size_t tx_length; ///< TX buffer length. 173 uint8_t * p_rx_buffer; ///< Pointer to RX buffer. 174 size_t rx_length; ///< RX buffer length. 175 } nrfx_spim_xfer_desc_t; 176 177 /** 178 * @brief Macro for setting up single transfer descriptor. 179 * 180 * This macro is for internal use only. 181 */ 182 #define NRFX_SPIM_SINGLE_XFER(p_tx, tx_len, p_rx, rx_len) \ 183 { \ 184 .p_tx_buffer = (uint8_t const *)(p_tx), \ 185 .tx_length = (tx_len), \ 186 .p_rx_buffer = (p_rx), \ 187 .rx_length = (rx_len), \ 188 } 189 190 /** 191 * @brief Macro for setting duplex TX RX transfer. 192 */ 193 #define NRFX_SPIM_XFER_TRX(p_tx_buf, tx_length, p_rx_buf, rx_length) \ 194 NRFX_SPIM_SINGLE_XFER(p_tx_buf, tx_length, p_rx_buf, rx_length) 195 196 /** 197 * @brief Macro for setting TX transfer. 198 */ 199 #define NRFX_SPIM_XFER_TX(p_buf, length) \ 200 NRFX_SPIM_SINGLE_XFER(p_buf, length, NULL, 0) 201 202 /** 203 * @brief Macro for setting RX transfer. 204 */ 205 #define NRFX_SPIM_XFER_RX(p_buf, length) \ 206 NRFX_SPIM_SINGLE_XFER(NULL, 0, p_buf, length) 207 208 /** 209 * @brief SPIM master driver event types, passed to the handler routine provided 210 * during initialization. 211 */ 212 typedef enum 213 { 214 NRFX_SPIM_EVENT_DONE, ///< Transfer done. 215 } nrfx_spim_evt_type_t; 216 217 typedef struct 218 { 219 nrfx_spim_evt_type_t type; ///< Event type. 220 nrfx_spim_xfer_desc_t xfer_desc; ///< Transfer details. 221 } nrfx_spim_evt_t; 222 223 /** 224 * @brief SPIM master driver event handler type. 225 */ 226 typedef void (* nrfx_spim_evt_handler_t)(nrfx_spim_evt_t const * p_event, 227 void * p_context); 228 229 /** 230 * @brief Function for initializing the SPI master driver instance. 231 * 232 * This function configures and enables the specified peripheral. 233 * 234 * @param[in] p_instance Pointer to the driver instance structure. 235 * @param[in] p_config Pointer to the structure with initial configuration. 236 * 237 * @param handler Event handler provided by the user. If NULL, transfers 238 * will be performed in blocking mode. 239 * @param p_context Context passed to event handler. 240 * 241 * @retval NRFX_SUCCESS If initialization was successful. 242 * @retval NRFX_ERROR_INVALID_STATE If the driver was already initialized. 243 * @retval NRFX_ERROR_BUSY If some other peripheral with the same 244 * instance ID is already in use. This is 245 * possible only if @ref nrfx_prs module 246 * is enabled. 247 * @retval NRFX_ERROR_NOT_SUPPORTED If requested configuration is not supported 248 * by the SPIM instance. 249 */ 250 nrfx_err_t nrfx_spim_init(nrfx_spim_t const * const p_instance, 251 nrfx_spim_config_t const * p_config, 252 nrfx_spim_evt_handler_t handler, 253 void * p_context); 254 255 /** 256 * @brief Function for uninitializing the SPI master driver instance. 257 * 258 * @param[in] p_instance Pointer to the driver instance structure. 259 */ 260 void nrfx_spim_uninit(nrfx_spim_t const * const p_instance); 261 262 /** 263 * @brief Function for starting the SPI data transfer. 264 * 265 * Additional options are provided using the @c flags parameter: 266 * 267 * - @ref NRFX_SPIM_FLAG_TX_POSTINC and @ref NRFX_SPIM_FLAG_RX_POSTINC<span></span>: 268 * Post-incrementation of buffer addresses. Supported only by SPIM. 269 * - @ref NRFX_SPIM_FLAG_HOLD_XFER<span></span>: Driver is not starting the transfer. Use this 270 * flag if the transfer is triggered externally by PPI. Supported only by SPIM. Use 271 * @ref nrfx_spim_start_task_get to get the address of the start task. 272 * - @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER<span></span>: No user event handler after transfer 273 * completion. This also means no interrupt at the end of the transfer. Supported only by SPIM. 274 * If @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER is used, the driver does not set the instance into 275 * busy state, so you must ensure that the next transfers are set up when SPIM is not active. 276 * @ref nrfx_spim_end_event_get function can be used to detect end of transfer. Option can be used 277 * together with @ref NRFX_SPIM_FLAG_REPEATED_XFER to prepare a sequence of SPI transfers 278 * without interruptions. 279 * - @ref NRFX_SPIM_FLAG_REPEATED_XFER<span></span>: Prepare for repeated transfers. You can set 280 * up a number of transfers that will be triggered externally (for example by PPI). An example is 281 * a TXRX transfer with the options @ref NRFX_SPIM_FLAG_RX_POSTINC, 282 * @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER, and @ref NRFX_SPIM_FLAG_REPEATED_XFER. After the 283 * transfer is set up, a set of transfers can be triggered by PPI that will read, for example, 284 * the same register of an external component and put it into a RAM buffer without any interrupts. 285 * @ref nrfx_spim_end_event_get can be used to get the address of the END event, which can be 286 * used to count the number of transfers. If @ref NRFX_SPIM_FLAG_REPEATED_XFER is used, 287 * the driver does not set the instance into busy state, so you must ensure that the next 288 * transfers are set up when SPIM is not active. Supported only by SPIM. 289 * 290 * @note Peripherals using EasyDMA (including SPIM) require the transfer buffers 291 * to be placed in the Data RAM region. If this condition is not met, 292 * this function will fail with the error code NRFX_ERROR_INVALID_ADDR. 293 * 294 * @param p_instance Pointer to the driver instance structure. 295 * @param p_xfer_desc Pointer to the transfer descriptor. 296 * @param flags Transfer options (0 for default settings). 297 * 298 * @retval NRFX_SUCCESS If the procedure was successful. 299 * @retval NRFX_ERROR_BUSY If the driver is not ready for a new transfer. 300 * @retval NRFX_ERROR_NOT_SUPPORTED If the provided parameters are not supported. 301 * @retval NRFX_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data 302 * RAM region. 303 */ 304 nrfx_err_t nrfx_spim_xfer(nrfx_spim_t const * const p_instance, 305 nrfx_spim_xfer_desc_t const * p_xfer_desc, 306 uint32_t flags); 307 308 #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__) 309 /** 310 * @brief Function for starting the SPI data transfer with DCX control. 311 * 312 * See @ref nrfx_spim_xfer for description of additional options of transfer 313 * provided by the @c flags parameter. 314 * 315 * @note Peripherals that use EasyDMA (including SPIM) require the transfer buffers 316 * to be placed in the Data RAM region. If this condition is not met, 317 * this function will fail with the error code NRFX_ERROR_INVALID_ADDR. 318 * 319 * @param p_instance Pointer to the driver instance structure. 320 * @param p_xfer_desc Pointer to the transfer descriptor. 321 * @param flags Transfer options (0 for default settings). 322 * @param cmd_length Length of the command bytes preceding the data 323 * bytes. The DCX line will be low during transmission 324 * of command bytes and high during transmission of data bytes. 325 * Maximum value available for dividing the transmitted bytes 326 * into command bytes and data bytes is @ref NRF_SPIM_DCX_CNT_ALL_CMD - 1. 327 * The @ref NRF_SPIM_DCX_CNT_ALL_CMD value passed as the 328 * @c cmd_length parameter causes all transmitted bytes 329 * to be marked as command bytes. 330 * 331 * @retval NRFX_SUCCESS If the procedure was successful. 332 * @retval NRFX_ERROR_BUSY If the driver is not ready for a new transfer. 333 * @retval NRFX_ERROR_NOT_SUPPORTED If the provided parameters are not supported. 334 * @retval NRFX_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data 335 * RAM region. 336 */ 337 nrfx_err_t nrfx_spim_xfer_dcx(nrfx_spim_t const * const p_instance, 338 nrfx_spim_xfer_desc_t const * p_xfer_desc, 339 uint32_t flags, 340 uint8_t cmd_length); 341 #endif 342 343 /** 344 * @brief Function for returning the address of a SPIM start task. 345 * 346 * This function should be used if @ref nrfx_spim_xfer was called with the flag @ref NRFX_SPIM_FLAG_HOLD_XFER. 347 * In that case, the transfer is not started by the driver, but it must be started externally by PPI. 348 * 349 * @param[in] p_instance Pointer to the driver instance structure. 350 * 351 * @return Start task address. 352 */ 353 uint32_t nrfx_spim_start_task_get(nrfx_spim_t const * p_instance); 354 355 /** 356 * @brief Function for returning the address of a END SPIM event. 357 * 358 * The END event can be used to detect the end of a transfer 359 * if the @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER option is used. 360 * 361 * @param[in] p_instance Pointer to the driver instance structure. 362 * 363 * @return END event address. 364 */ 365 uint32_t nrfx_spim_end_event_get(nrfx_spim_t const * p_instance); 366 367 /** 368 * @brief Function for aborting ongoing transfer. 369 * 370 * @param[in] p_instance Pointer to the driver instance structure. 371 */ 372 void nrfx_spim_abort(nrfx_spim_t const * p_instance); 373 374 375 void nrfx_spim_0_irq_handler(void); 376 void nrfx_spim_1_irq_handler(void); 377 void nrfx_spim_2_irq_handler(void); 378 void nrfx_spim_3_irq_handler(void); 379 380 381 /** @} */ 382 383 #ifdef __cplusplus 384 } 385 #endif 386 387 #endif // NRFX_SPIM_H__ 388