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