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_SPI_H__
33 #define NRFX_SPI_H__
34 
35 #include <nrfx.h>
36 #include <hal/nrf_spi.h>
37 #include <hal/nrf_gpio.h>
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /**
44  * @defgroup nrfx_spi SPI driver
45  * @{
46  * @ingroup nrf_spi
47  * @brief   Serial Peripheral Interface master (SPI) driver.
48  */
49 
50 /** @brief Data structure of the Serial Peripheral Interface master (SPI) driver instance. */
51 typedef struct
52 {
53     NRF_SPI_Type * p_reg;        ///< Pointer to a structure with SPI registers.
54     uint8_t        drv_inst_idx; ///< Index of the driver instance. For internal use only.
55 } nrfx_spi_t;
56 
57 #ifndef __NRFX_DOXYGEN__
58 enum {
59 #if NRFX_CHECK(NRFX_SPI0_ENABLED)
60     NRFX_SPI0_INST_IDX,
61 #endif
62 #if NRFX_CHECK(NRFX_SPI1_ENABLED)
63     NRFX_SPI1_INST_IDX,
64 #endif
65 #if NRFX_CHECK(NRFX_SPI2_ENABLED)
66     NRFX_SPI2_INST_IDX,
67 #endif
68     NRFX_SPI_ENABLED_COUNT
69 };
70 #endif
71 
72 /** @brief Macro for creating an instance of the SPI master driver. */
73 #define NRFX_SPI_INSTANCE(id)                               \
74 {                                                           \
75     .p_reg        = NRFX_CONCAT_2(NRF_SPI, id),             \
76     .drv_inst_idx = NRFX_CONCAT_3(NRFX_SPI, id, _INST_IDX), \
77 }
78 
79 /**
80  * @brief This value can be provided instead of a pin number for signals MOSI,
81  *        MISO, and Slave Select to specify that the given signal is not used and
82  *        therefore does not need to be connected to a pin.
83  */
84 #define NRFX_SPI_PIN_NOT_USED  0xFF
85 
86 /** @brief Configuration structure of the SPI master driver instance. */
87 typedef struct
88 {
89     uint8_t sck_pin;                ///< SCK pin number.
90     uint8_t mosi_pin;               ///< MOSI pin number (optional).
91                                     /**< Set to @ref NRFX_SPI_PIN_NOT_USED
92                                      *   if this signal is not needed. */
93     uint8_t miso_pin;               ///< MISO pin number (optional).
94                                     /**< Set to @ref NRFX_SPI_PIN_NOT_USED
95                                      *   if this signal is not needed. */
96     uint8_t ss_pin;                 ///< Slave Select pin number (optional).
97                                     /**< Set to @ref NRFX_SPI_PIN_NOT_USED
98                                      *   if this signal is not needed. The driver
99                                      *   supports only active low for this signal.
100                                      *   If the signal must be active high,
101                                      *   it must be controlled externally. */
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 } nrfx_spi_config_t;
111 
112 /**
113  * @brief SPI master instance default configuration.
114  * This configuration sets up SPI with the following options:
115  * - over-run character set to 0xFF
116  * - clock frequency 4 MHz
117  * - mode 0 enabled (SCK active high, sample on leading edge of clock)
118  * - MSB shifted out first
119  * - MISO pull-up disabled
120  *
121  * @param[in] _pin_sck  SCK pin.
122  * @param[in] _pin_mosi MOSI pin.
123  * @param[in] _pin_miso MISO pin.
124  * @param[in] _pin_ss   SS pin.
125  */
126 #define NRFX_SPI_DEFAULT_CONFIG(_pin_sck, _pin_mosi, _pin_miso, _pin_ss)    \
127 {                                                                           \
128     .sck_pin      = _pin_sck,                                               \
129     .mosi_pin     = _pin_mosi,                                              \
130     .miso_pin     = _pin_miso,                                              \
131     .ss_pin       = _pin_ss,                                                \
132     .irq_priority = NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY,                   \
133     .orc          = 0xFF,                                                   \
134     .frequency    = NRF_SPI_FREQ_4M,                                        \
135     .mode         = NRF_SPI_MODE_0,                                         \
136     .bit_order    = NRF_SPI_BIT_ORDER_MSB_FIRST,                            \
137     .miso_pull    = NRF_GPIO_PIN_NOPULL,                                    \
138 }
139 
140 /** @brief Single transfer descriptor structure. */
141 typedef struct
142 {
143     uint8_t const * p_tx_buffer; ///< Pointer to TX buffer.
144     size_t          tx_length;   ///< TX buffer length.
145     uint8_t       * p_rx_buffer; ///< Pointer to RX buffer.
146     size_t          rx_length;   ///< RX buffer length.
147 }nrfx_spi_xfer_desc_t;
148 
149 /**
150  * @brief Macro for setting up single transfer descriptor.
151  *
152  * This macro is for internal use only.
153  */
154 #define NRFX_SPI_SINGLE_XFER(p_tx, tx_len, p_rx, rx_len) \
155 {                                                        \
156     .p_tx_buffer = (uint8_t const *)(p_tx),              \
157     .tx_length = (tx_len),                               \
158     .p_rx_buffer = (p_rx),                               \
159     .rx_length = (rx_len),                               \
160 }
161 
162 /** @brief Macro for setting the duplex TX RX transfer. */
163 #define NRFX_SPI_XFER_TRX(p_tx_buf, tx_length, p_rx_buf, rx_length) \
164         NRFX_SPI_SINGLE_XFER(p_tx_buf, tx_length, p_rx_buf, rx_length)
165 
166 /** @brief Macro for setting the TX transfer. */
167 #define NRFX_SPI_XFER_TX(p_buf, length) \
168         NRFX_SPI_SINGLE_XFER(p_buf, length, NULL, 0)
169 
170 /** @brief Macro for setting the RX transfer. */
171 #define NRFX_SPI_XFER_RX(p_buf, length) \
172         NRFX_SPI_SINGLE_XFER(NULL, 0, p_buf, length)
173 
174 /**
175  * @brief SPI master driver event types, passed to the handler routine provided
176  *        during initialization.
177  */
178 typedef enum
179 {
180     NRFX_SPI_EVENT_DONE, ///< Transfer done.
181 } nrfx_spi_evt_type_t;
182 
183 /** @brief SPI master event description with transmission details. */
184 typedef struct
185 {
186     nrfx_spi_evt_type_t  type;      ///< Event type.
187     nrfx_spi_xfer_desc_t xfer_desc; ///< Transfer details.
188 } nrfx_spi_evt_t;
189 
190 /** @brief SPI master driver event handler type. */
191 typedef void (* nrfx_spi_evt_handler_t)(nrfx_spi_evt_t const * p_event,
192                                         void *                 p_context);
193 
194 /**
195  * @brief Function for initializing the SPI master driver instance.
196  *
197  * This function configures and enables the specified peripheral.
198  *
199  * @param[in] p_instance Pointer to the driver instance structure.
200  * @param[in] p_config   Pointer to the structure with the initial configuration.
201  * @param[in] handler    Event handler provided by the user. If NULL, transfers
202  *                       will be performed in blocking mode.
203  * @param[in] p_context  Context passed to the event handler.
204  *
205  * @retval NRFX_SUCCESS             Initialization was successful.
206  * @retval NRFX_ERROR_INVALID_STATE The driver was already initialized.
207  * @retval NRFX_ERROR_BUSY          Some other peripheral with the same
208  *                                  instance ID is already in use. This is
209  *                                  possible only if @ref nrfx_prs module
210  *                                  is enabled.
211  */
212 nrfx_err_t nrfx_spi_init(nrfx_spi_t const *        p_instance,
213                          nrfx_spi_config_t const * p_config,
214                          nrfx_spi_evt_handler_t    handler,
215                          void *                    p_context);
216 
217 /**
218  * @brief Function for uninitializing the SPI master driver instance.
219  *
220  * @param[in] p_instance Pointer to the driver instance structure.
221  */
222 void nrfx_spi_uninit(nrfx_spi_t const * p_instance);
223 
224 /**
225  * @brief Function for starting the SPI data transfer.
226  *
227  * If an event handler was provided in the @ref nrfx_spi_init call, this function
228  * returns immediately and the handler is called when the transfer is done.
229  * Otherwise, the transfer is performed in blocking mode, which means that this function
230  * returns when the transfer is finished.
231  *
232  * @param p_instance  Pointer to the driver instance structure.
233  * @param p_xfer_desc Pointer to the transfer descriptor.
234  * @param flags       Transfer options (0 for default settings).
235  *                    Currently, no additional flags are available.
236  *
237  * @retval NRFX_SUCCESS             The procedure is successful.
238  * @retval NRFX_ERROR_BUSY          The driver is not ready for a new transfer.
239  * @retval NRFX_ERROR_NOT_SUPPORTED The provided parameters are not supported.
240  */
241 nrfx_err_t nrfx_spi_xfer(nrfx_spi_t const *           p_instance,
242                          nrfx_spi_xfer_desc_t const * p_xfer_desc,
243                          uint32_t                     flags);
244 
245 /**
246  * @brief Function for aborting the ongoing transfer.
247  *
248  * @param[in] p_instance Pointer to the driver instance structure.
249  */
250 void nrfx_spi_abort(nrfx_spi_t const * p_instance);
251 
252 /** @} */
253 
254 
255 void nrfx_spi_0_irq_handler(void);
256 void nrfx_spi_1_irq_handler(void);
257 void nrfx_spi_2_irq_handler(void);
258 
259 
260 #ifdef __cplusplus
261 }
262 #endif
263 
264 #endif // NRFX_SPI_H__
265