1 /* 2 * Copyright (c) 2015 - 2025, Nordic Semiconductor ASA 3 * All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, this 11 * list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the copyright holder nor the names of its 18 * contributors may be used to endorse or promote products derived from this 19 * software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #ifndef NRFX_SPI_H__ 35 #define NRFX_SPI_H__ 36 37 #include <nrfx.h> 38 #include <hal/nrf_spi.h> 39 #include <hal/nrf_gpio.h> 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 /** 46 * @defgroup nrfx_spi SPI driver 47 * @{ 48 * @ingroup nrf_spi 49 * @brief Serial Peripheral Interface master (SPI) driver. 50 */ 51 52 /** @brief Data structure of the Serial Peripheral Interface master (SPI) driver instance. */ 53 typedef struct 54 { 55 NRF_SPI_Type * p_reg; ///< Pointer to a structure with SPI registers. 56 uint8_t drv_inst_idx; ///< Index of the driver instance. For internal use only. 57 } nrfx_spi_t; 58 59 #ifndef __NRFX_DOXYGEN__ 60 enum { 61 /* List all enabled driver instances (in the format NRFX_\<instance_name\>_INST_IDX). */ 62 NRFX_INSTANCE_ENUM_LIST(SPI) 63 NRFX_SPI_ENABLED_COUNT 64 }; 65 #endif 66 67 /** @brief Macro for creating an instance of the SPI master driver. */ 68 #define NRFX_SPI_INSTANCE(id) \ 69 { \ 70 .p_reg = NRFX_CONCAT(NRF_, SPI, id), \ 71 .drv_inst_idx = NRFX_CONCAT(NRFX_SPI, id, _INST_IDX), \ 72 } 73 74 /** 75 * @brief This value can be provided instead of a pin number for signals MOSI, 76 * MISO, and Slave Select to specify that the given signal is not used and 77 * therefore does not need to be connected to a pin. 78 */ 79 #define NRFX_SPI_PIN_NOT_USED 0xFF 80 81 /** @brief Configuration structure of the SPI master driver instance. */ 82 typedef struct 83 { 84 uint8_t sck_pin; ///< SCK pin number. 85 uint8_t mosi_pin; ///< MOSI pin number (optional). 86 /**< Set to @ref NRFX_SPI_PIN_NOT_USED 87 * if this signal is not needed. */ 88 uint8_t miso_pin; ///< MISO pin number (optional). 89 /**< Set to @ref NRFX_SPI_PIN_NOT_USED 90 * if this signal is not needed. */ 91 uint8_t ss_pin; ///< Slave Select pin number (optional). 92 /**< Set to @ref NRFX_SPI_PIN_NOT_USED 93 * if this signal is not needed. The driver 94 * supports only active low for this signal. 95 * If the signal must be active high, 96 * it must be controlled externally. 97 * @note Unlike the other fields that specify 98 * pin numbers, this one cannot be omitted 99 * when both GPIO configuration and pin 100 * selection are to be skipped, as the driver 101 * must control the signal as a regular GPIO. */ 102 uint8_t irq_priority; ///< Interrupt priority. 103 uint8_t orc; ///< Overrun character. 104 /**< This character is used when all bytes from the TX buffer are sent, 105 * but the transfer continues due to RX. */ 106 nrf_spi_frequency_t frequency; ///< SPI frequency. 107 nrf_spi_mode_t mode; ///< SPI mode. 108 nrf_spi_bit_order_t bit_order; ///< SPI bit order. 109 nrf_gpio_pin_pull_t miso_pull; ///< MISO pull up configuration. 110 bool skip_gpio_cfg; ///< Skip GPIO configuration of pins. 111 /**< When set to true, the driver does not modify 112 * any GPIO parameters of the used pins. Those 113 * parameters are supposed to be configured 114 * externally before the driver is initialized. */ 115 bool skip_psel_cfg; ///< Skip pin selection configuration. 116 /**< When set to true, the driver does not modify 117 * pin select registers in the peripheral. 118 * Those registers are supposed to be set up 119 * externally before the driver is initialized. 120 * @note When both GPIO configuration and pin 121 * selection are to be skipped, the structure 122 * fields that specify pins can be omitted, 123 * as they are ignored anyway. This does not 124 * apply to the @p ss_pin field. */ 125 } nrfx_spi_config_t; 126 127 /** 128 * @brief SPI master instance default configuration. 129 * This configuration sets up SPI with the following options: 130 * - over-run character set to 0xFF 131 * - clock frequency 4 MHz 132 * - mode 0 enabled (SCK active high, sample on leading edge of clock) 133 * - MSB shifted out first 134 * - MISO pull-up disabled 135 * 136 * @param[in] _pin_sck SCK pin. 137 * @param[in] _pin_mosi MOSI pin. 138 * @param[in] _pin_miso MISO pin. 139 * @param[in] _pin_ss SS pin. 140 */ 141 #define NRFX_SPI_DEFAULT_CONFIG(_pin_sck, _pin_mosi, _pin_miso, _pin_ss) \ 142 { \ 143 .sck_pin = _pin_sck, \ 144 .mosi_pin = _pin_mosi, \ 145 .miso_pin = _pin_miso, \ 146 .ss_pin = _pin_ss, \ 147 .irq_priority = NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY, \ 148 .orc = 0xFF, \ 149 .frequency = NRF_SPI_FREQ_4M, \ 150 .mode = NRF_SPI_MODE_0, \ 151 .bit_order = NRF_SPI_BIT_ORDER_MSB_FIRST, \ 152 .miso_pull = NRF_GPIO_PIN_NOPULL, \ 153 } 154 155 /** @brief Single transfer descriptor structure. */ 156 typedef struct 157 { 158 uint8_t const * p_tx_buffer; ///< Pointer to TX buffer. 159 size_t tx_length; ///< TX buffer length. 160 uint8_t * p_rx_buffer; ///< Pointer to RX buffer. 161 size_t rx_length; ///< RX buffer length. 162 }nrfx_spi_xfer_desc_t; 163 164 /** 165 * @brief Macro for setting up single transfer descriptor. 166 * 167 * This macro is for internal use only. 168 */ 169 #define NRFX_SPI_SINGLE_XFER(p_tx, tx_len, p_rx, rx_len) \ 170 { \ 171 .p_tx_buffer = (uint8_t const *)(p_tx), \ 172 .tx_length = (tx_len), \ 173 .p_rx_buffer = (p_rx), \ 174 .rx_length = (rx_len), \ 175 } 176 177 /** @brief Macro for setting the duplex TX RX transfer. */ 178 #define NRFX_SPI_XFER_TRX(p_tx_buf, tx_length, p_rx_buf, rx_length) \ 179 NRFX_SPI_SINGLE_XFER(p_tx_buf, tx_length, p_rx_buf, rx_length) 180 181 /** @brief Macro for setting the TX transfer. */ 182 #define NRFX_SPI_XFER_TX(p_buf, length) \ 183 NRFX_SPI_SINGLE_XFER(p_buf, length, NULL, 0) 184 185 /** @brief Macro for setting the RX transfer. */ 186 #define NRFX_SPI_XFER_RX(p_buf, length) \ 187 NRFX_SPI_SINGLE_XFER(NULL, 0, p_buf, length) 188 189 /** 190 * @brief SPI master driver event types, passed to the handler routine provided 191 * during initialization. 192 */ 193 typedef enum 194 { 195 NRFX_SPI_EVENT_DONE, ///< Transfer done. 196 } nrfx_spi_evt_type_t; 197 198 /** @brief SPI master event description with transmission details. */ 199 typedef struct 200 { 201 nrfx_spi_evt_type_t type; ///< Event type. 202 nrfx_spi_xfer_desc_t xfer_desc; ///< Transfer details. 203 } nrfx_spi_evt_t; 204 205 /** @brief SPI master driver event handler type. */ 206 typedef void (* nrfx_spi_evt_handler_t)(nrfx_spi_evt_t const * p_event, 207 void * p_context); 208 209 /** 210 * @brief Function for initializing the SPI master driver instance. 211 * 212 * This function configures and enables the specified peripheral. 213 * 214 * @param[in] p_instance Pointer to the driver instance structure. 215 * @param[in] p_config Pointer to the structure with the initial configuration. 216 * @param[in] handler Event handler provided by the user. If NULL, transfers 217 * will be performed in blocking mode. 218 * @param[in] p_context Context passed to the event handler. 219 * 220 * @retval NRFX_SUCCESS Initialization was successful. 221 * @retval NRFX_ERROR_ALREADY The driver is already initialized. 222 * @retval NRFX_ERROR_INVALID_STATE The driver is already initialized. 223 * Deprecated - use @ref NRFX_ERROR_ALREADY instead. 224 * @retval NRFX_ERROR_BUSY Some other peripheral with the same 225 * instance ID is already in use. This is 226 * possible only if @ref nrfx_prs module 227 * is enabled. 228 */ 229 nrfx_err_t nrfx_spi_init(nrfx_spi_t const * p_instance, 230 nrfx_spi_config_t const * p_config, 231 nrfx_spi_evt_handler_t handler, 232 void * p_context); 233 234 /** 235 * @brief Function for reconfiguring the SPI master driver instance. 236 * 237 * @param[in] p_instance Pointer to the driver instance structure. 238 * @param[in] p_config Pointer to the structure with the configuration. 239 * 240 * @retval NRFX_SUCCESS Reconfiguration was successful. 241 * @retval NRFX_ERROR_BUSY The driver is during transfer. 242 * @retval NRFX_ERROR_INVALID_STATE The driver is uninitialized. 243 */ 244 nrfx_err_t nrfx_spi_reconfigure(nrfx_spi_t const * p_instance, 245 nrfx_spi_config_t const * p_config); 246 247 /** 248 * @brief Function for uninitializing the SPI master driver instance. 249 * 250 * @param[in] p_instance Pointer to the driver instance structure. 251 */ 252 void nrfx_spi_uninit(nrfx_spi_t const * p_instance); 253 254 /** 255 * @brief Function for checking if the SPI driver instance is initialized. 256 * 257 * @param[in] p_instance Pointer to the driver instance structure. 258 * 259 * @retval true Instance is already initialized. 260 * @retval false Instance is not initialized. 261 */ 262 bool nrfx_spi_init_check(nrfx_spi_t const * p_instance); 263 264 /** 265 * @brief Function for starting the SPI data transfer. 266 * 267 * If an event handler was provided in the @ref nrfx_spi_init call, this function 268 * returns immediately and the handler is called when the transfer is done. 269 * Otherwise, the transfer is performed in blocking mode, which means that this function 270 * returns when the transfer is finished. 271 * 272 * @param p_instance Pointer to the driver instance structure. 273 * @param p_xfer_desc Pointer to the transfer descriptor. 274 * @param flags Transfer options (0 for default settings). 275 * Currently, no additional flags are available. 276 * 277 * @retval NRFX_SUCCESS The procedure is successful. 278 * @retval NRFX_ERROR_BUSY The driver is not ready for a new transfer. 279 * @retval NRFX_ERROR_NOT_SUPPORTED The provided parameters are not supported. 280 */ 281 nrfx_err_t nrfx_spi_xfer(nrfx_spi_t const * p_instance, 282 nrfx_spi_xfer_desc_t const * p_xfer_desc, 283 uint32_t flags); 284 285 /** 286 * @brief Function for aborting the ongoing transfer. 287 * 288 * @param[in] p_instance Pointer to the driver instance structure. 289 */ 290 void nrfx_spi_abort(nrfx_spi_t const * p_instance); 291 292 /** 293 * @brief Macro returning SPI interrupt handler. 294 * 295 * param[in] idx SPI index. 296 * 297 * @return Interrupt handler. 298 */ 299 #define NRFX_SPI_INST_HANDLER_GET(idx) NRFX_CONCAT_3(nrfx_spi_, idx, _irq_handler) 300 301 /** @} */ 302 303 /* 304 * Declare interrupt handlers for all enabled driver instances in the following format: 305 * nrfx_\<periph_name\>_\<idx\>_irq_handler (for example, nrfx_spi_0_irq_handler). 306 * 307 * A specific interrupt handler for the driver instance can be retrieved by using 308 * the NRFX_SPI_INST_HANDLER_GET macro. 309 * 310 * Here is a sample of using the NRFX_SPI_INST_HANDLER_GET macro to map an interrupt handler 311 * in a Zephyr application: 312 * 313 * IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_SPI_INST_GET(\<instance_index\>)), \<priority\>, 314 * NRFX_SPI_INST_HANDLER_GET(\<instance_index\>), 0, 0); 315 */ 316 NRFX_INSTANCE_IRQ_HANDLERS_DECLARE(SPI, spi) 317 318 319 #ifdef __cplusplus 320 } 321 #endif 322 323 #endif // NRFX_SPI_H__ 324