1 /* 2 * Copyright (c) 2015 - 2020, 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_SPIS_H__ 33 #define NRFX_SPIS_H__ 34 35 #include <nrfx.h> 36 #include <hal/nrf_spis.h> 37 #include <hal/nrf_gpio.h> 38 39 #ifdef __cplusplus 40 extern "C" { 41 #endif 42 43 /** 44 * @defgroup nrfx_spis SPIS driver 45 * @{ 46 * @ingroup nrf_spis 47 * @brief Serial Peripheral Interface Slave with EasyDMA (SPIS) driver. 48 */ 49 50 /** @brief Data structure for the Serial Peripheral Interface Slave with EasyDMA (SPIS) driver instance. */ 51 typedef struct 52 { 53 NRF_SPIS_Type * p_reg; //!< Pointer to a structure with SPIS registers. 54 uint8_t drv_inst_idx; //!< Index of the driver instance. For internal use only. 55 } nrfx_spis_t; 56 57 #ifndef __NRFX_DOXYGEN__ 58 enum { 59 #if NRFX_CHECK(NRFX_SPIS0_ENABLED) 60 NRFX_SPIS0_INST_IDX, 61 #endif 62 #if NRFX_CHECK(NRFX_SPIS1_ENABLED) 63 NRFX_SPIS1_INST_IDX, 64 #endif 65 #if NRFX_CHECK(NRFX_SPIS2_ENABLED) 66 NRFX_SPIS2_INST_IDX, 67 #endif 68 #if NRFX_CHECK(NRFX_SPIS3_ENABLED) 69 NRFX_SPIS3_INST_IDX, 70 #endif 71 NRFX_SPIS_ENABLED_COUNT 72 }; 73 #endif 74 75 /** @brief Macro for creating an instance of the SPI slave driver. */ 76 #define NRFX_SPIS_INSTANCE(id) \ 77 { \ 78 .p_reg = NRFX_CONCAT_2(NRF_SPIS, id), \ 79 .drv_inst_idx = NRFX_CONCAT_3(NRFX_SPIS, id, _INST_IDX), \ 80 } 81 82 /** 83 * @brief This value can be provided instead of a pin number for the signals MOSI 84 * and MISO to specify that the given signal is not used and therefore 85 * does not need to be connected to a pin. 86 */ 87 #define NRFX_SPIS_PIN_NOT_USED 0xFF 88 89 /** @brief SPI slave driver event types. */ 90 typedef enum 91 { 92 NRFX_SPIS_BUFFERS_SET_DONE, //!< Memory buffer set event. Memory buffers have been set successfully to the SPI slave device, and SPI transaction can be done. 93 NRFX_SPIS_XFER_DONE, //!< SPI transaction event. SPI transaction has been completed. 94 NRFX_SPIS_EVT_TYPE_MAX //!< Enumeration upper bound. 95 } nrfx_spis_evt_type_t; 96 97 /** @brief SPI slave driver event structure. */ 98 typedef struct 99 { 100 nrfx_spis_evt_type_t evt_type; //!< Type of the event. 101 size_t rx_amount; //!< Number of bytes received in the last transaction. This parameter is only valid for @ref NRFX_SPIS_XFER_DONE events. 102 size_t tx_amount; //!< Number of bytes transmitted in the last transaction. This parameter is only valid for @ref NRFX_SPIS_XFER_DONE events. 103 } nrfx_spis_evt_t; 104 105 /** 106 * @brief SPIS driver default configuration. 107 * 108 * This configuration sets up SPIS with the following options: 109 * - mode: 0 (SCK active high, sample on leading edge of the clock signal) 110 * - MSB shifted out first 111 * - CSN pull-up disabled 112 * - MISO pin drive set to standard '0' and standard '1' 113 * - default character set to 0xFF 114 * - over-read character set to 0xFE 115 * 116 * @param[in] _pin_sck SCK pin. 117 * @param[in] _pin_mosi MOSI pin. 118 * @param[in] _pin_miso MISO pin. 119 * @param[in] _pin_csn CSN pin. 120 */ 121 #define NRFX_SPIS_DEFAULT_CONFIG(_pin_sck, _pin_mosi, _pin_miso, _pin_csn) \ 122 { \ 123 .miso_pin = _pin_miso, \ 124 .mosi_pin = _pin_mosi, \ 125 .sck_pin = _pin_sck, \ 126 .csn_pin = _pin_csn, \ 127 .mode = NRF_SPIS_MODE_0, \ 128 .bit_order = NRF_SPIS_BIT_ORDER_MSB_FIRST, \ 129 .csn_pullup = NRF_GPIO_PIN_NOPULL, \ 130 .miso_drive = NRF_GPIO_PIN_S0S1, \ 131 .def = 0xFF, \ 132 .orc = 0xFE, \ 133 .irq_priority = NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY, \ 134 } 135 136 /** @brief SPI peripheral device configuration data. */ 137 typedef struct 138 { 139 uint32_t miso_pin; //!< SPI MISO pin (optional). 140 /**< Set @ref NRFX_SPIS_PIN_NOT_USED 141 * if this signal is not needed. */ 142 uint32_t mosi_pin; //!< SPI MOSI pin (optional). 143 /**< Set @ref NRFX_SPIS_PIN_NOT_USED 144 * if this signal is not needed. */ 145 uint32_t sck_pin; //!< SPI SCK pin. 146 uint32_t csn_pin; //!< SPI CSN pin. 147 nrf_spis_mode_t mode; //!< SPI mode. 148 nrf_spis_bit_order_t bit_order; //!< SPI transaction bit order. 149 nrf_gpio_pin_pull_t csn_pullup; //!< CSN pin pull-up configuration. 150 nrf_gpio_pin_drive_t miso_drive; //!< MISO pin drive configuration. 151 uint8_t def; //!< Character clocked out in case of an ignored transaction. 152 uint8_t orc; //!< Character clocked out after an over-read of the transmit buffer. 153 uint8_t irq_priority; //!< Interrupt priority. 154 } nrfx_spis_config_t; 155 156 157 /** 158 * @brief SPI slave driver event handler type. 159 * 160 * @param[in] p_event Pointer to the event structure. The structure is 161 * allocated on the stack so it is valid only until 162 * the event handler returns. 163 * @param[in] p_context Context set on initialization. 164 */ 165 typedef void (*nrfx_spis_event_handler_t)(nrfx_spis_evt_t const * p_event, 166 void * p_context); 167 168 /** 169 * @brief Function for initializing the SPI slave driver instance. 170 * 171 * @note When the nRF52 Anomaly 109 workaround for SPIS is enabled, this function 172 * initializes the GPIOTE driver as well, and uses one of GPIOTE channels 173 * to detect falling edges on CSN pin. 174 * 175 * @param[in] p_instance Pointer to the driver instance structure. 176 * @param[in] p_config Pointer to the structure with the initial configuration. 177 * @param[in] event_handler Function to be called by the SPI slave driver upon event. 178 * Must not be NULL. 179 * @param[in] p_context Context passed to the event handler. 180 * 181 * @retval NRFX_SUCCESS The initialization was successful. 182 * @retval NRFX_ERROR_INVALID_STATE The instance is already initialized. 183 * @retval NRFX_ERROR_INVALID_PARAM Invalid parameter is supplied. 184 * @retval NRFX_ERROR_BUSY Some other peripheral with the same 185 * instance ID is already in use. This is 186 * possible only if @ref nrfx_prs module 187 * is enabled. 188 * @retval NRFX_ERROR_INTERNAL GPIOTE channel for detecting falling edges 189 * on CSN pin cannot be initialized. Possible 190 * only when using nRF52 Anomaly 109 workaround. 191 */ 192 nrfx_err_t nrfx_spis_init(nrfx_spis_t const * p_instance, 193 nrfx_spis_config_t const * p_config, 194 nrfx_spis_event_handler_t event_handler, 195 void * p_context); 196 197 /** 198 * @brief Function for uninitializing the SPI slave driver instance. 199 * 200 * @param[in] p_instance Pointer to the driver instance structure. 201 */ 202 void nrfx_spis_uninit(nrfx_spis_t const * p_instance); 203 204 /** 205 * @brief Function for preparing the SPI slave instance for a single SPI transaction. 206 * 207 * This function prepares the SPI slave device to be ready for a single SPI transaction. It configures 208 * the SPI slave device to use the memory supplied with the function call in SPI transactions. 209 * 210 * When either the memory buffer configuration or the SPI transaction has been 211 * completed, the event callback function will be called with the appropriate event 212 * @ref nrfx_spis_evt_type_t. The callback function can be called before returning from 213 * this function, because it is called from the SPI slave interrupt context. 214 * 215 * @note This function can be called from the callback function context. 216 * 217 * @note Client applications must call this function after every @ref NRFX_SPIS_XFER_DONE event if 218 * the SPI slave driver must be prepared for a possible new SPI transaction. 219 * 220 * @note Peripherals using EasyDMA (including SPIS) require the transfer buffers 221 * to be placed in the Data RAM region. If this condition is not met, 222 * this function will fail with the error code NRFX_ERROR_INVALID_ADDR. 223 * 224 * @param[in] p_instance Pointer to the driver instance structure. 225 * @param[in] p_tx_buffer Pointer to the TX buffer. Can be NULL when the buffer length is zero. 226 * @param[in] p_rx_buffer Pointer to the RX buffer. Can be NULL when the buffer length is zero. 227 * @param[in] tx_buffer_length Length of the TX buffer in bytes. 228 * @param[in] rx_buffer_length Length of the RX buffer in bytes. 229 * 230 * @retval NRFX_SUCCESS The operation was successful. 231 * @retval NRFX_ERROR_INVALID_STATE The operation failed because the SPI slave device is in an incorrect state. 232 * @retval NRFX_ERROR_INVALID_ADDR The provided buffers are not placed in the Data 233 * RAM region. 234 * @retval NRFX_ERROR_INVALID_LENGTH Provided lengths exceed the EasyDMA limits for the peripheral. 235 * @retval NRFX_ERROR_INTERNAL The operation failed because of an internal error. 236 */ 237 nrfx_err_t nrfx_spis_buffers_set(nrfx_spis_t const * p_instance, 238 uint8_t const * p_tx_buffer, 239 size_t tx_buffer_length, 240 uint8_t * p_rx_buffer, 241 size_t rx_buffer_length); 242 243 /** @} */ 244 245 246 void nrfx_spis_0_irq_handler(void); 247 void nrfx_spis_1_irq_handler(void); 248 void nrfx_spis_2_irq_handler(void); 249 void nrfx_spis_3_irq_handler(void); 250 251 252 #ifdef __cplusplus 253 } 254 #endif 255 256 #endif // NRFX_SPIS_H__ 257 258