1 /*
2  * Copyright (c) 2015 - 2024, 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 NRF_SPI_H__
35 #define NRF_SPI_H__
36 
37 #include <nrfx.h>
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /**
44  * @defgroup nrf_spi_hal SPI HAL
45  * @{
46  * @ingroup nrf_spi
47  * @brief   Hardware access layer for managing the SPI peripheral.
48  */
49 
50 /**
51  * @brief Macro getting pointer to the structure of registers of the SPI peripheral.
52  *
53  * @param[in] idx SPI instance index.
54  *
55  * @return Pointer to the structure of registers of the SPI peripheral.
56  */
57 #define NRF_SPI_INST_GET(idx) NRFX_CONCAT(NRF_, SPI, idx)
58 
59 /**
60  * @brief This value can be used as a parameter for the @ref nrf_spi_pins_set
61  *        function to specify that a given SPI signal (SCK, MOSI, or MISO)
62  *        shall not be connected to a physical pin.
63  */
64 #define NRF_SPI_PIN_NOT_CONNECTED  0xFFFFFFFF
65 
66 
67 /** @brief SPI events. */
68 typedef enum
69 {
70     NRF_SPI_EVENT_READY = offsetof(NRF_SPI_Type, EVENTS_READY) ///< TXD byte sent and RXD byte received.
71 } nrf_spi_event_t;
72 
73 /** @brief SPI interrupts. */
74 typedef enum
75 {
76     NRF_SPI_INT_READY_MASK = SPI_INTENSET_READY_Msk, ///< Interrupt on READY event.
77     NRF_SPI_ALL_INTS_MASK  = SPI_INTENSET_READY_Msk  ///< All SPI interrupts.
78 } nrf_spi_int_mask_t;
79 
80 /** @brief SPI data rates. */
81 typedef enum
82 {
83     NRF_SPI_FREQ_125K = SPI_FREQUENCY_FREQUENCY_K125,   ///< 125 kbps.
84     NRF_SPI_FREQ_250K = SPI_FREQUENCY_FREQUENCY_K250,   ///< 250 kbps.
85     NRF_SPI_FREQ_500K = SPI_FREQUENCY_FREQUENCY_K500,   ///< 500 kbps.
86     NRF_SPI_FREQ_1M   = SPI_FREQUENCY_FREQUENCY_M1,     ///< 1 Mbps.
87     NRF_SPI_FREQ_2M   = SPI_FREQUENCY_FREQUENCY_M2,     ///< 2 Mbps.
88     NRF_SPI_FREQ_4M   = SPI_FREQUENCY_FREQUENCY_M4,     ///< 4 Mbps.
89     // [conversion to 'int' needed to prevent compilers from complaining
90     //  that the provided value (0x80000000UL) is out of range of "int"]
91     NRF_SPI_FREQ_8M   = (int)SPI_FREQUENCY_FREQUENCY_M8 ///< 8 Mbps.
92 } nrf_spi_frequency_t;
93 
94 /** @brief SPI modes. */
95 typedef enum
96 {
97     NRF_SPI_MODE_0, ///< SCK active high, sample on leading edge of clock.
98     NRF_SPI_MODE_1, ///< SCK active high, sample on trailing edge of clock.
99     NRF_SPI_MODE_2, ///< SCK active low, sample on leading edge of clock.
100     NRF_SPI_MODE_3  ///< SCK active low, sample on trailing edge of clock.
101 } nrf_spi_mode_t;
102 
103 /** @brief SPI bit orders. */
104 typedef enum
105 {
106     NRF_SPI_BIT_ORDER_MSB_FIRST = SPI_CONFIG_ORDER_MsbFirst, ///< Most significant bit shifted out first.
107     NRF_SPI_BIT_ORDER_LSB_FIRST = SPI_CONFIG_ORDER_LsbFirst  ///< Least significant bit shifted out first.
108 } nrf_spi_bit_order_t;
109 
110 
111 /**
112  * @brief Function for clearing the specified SPI event.
113  *
114  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
115  * @param[in] event Event to be cleared.
116  */
117 NRF_STATIC_INLINE void nrf_spi_event_clear(NRF_SPI_Type *  p_reg,
118                                            nrf_spi_event_t event);
119 
120 /**
121  * @brief Function for retrieving the state of the SPI event.
122  *
123  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
124  * @param[in] event Event to be checked.
125  *
126  * @retval true  The event has been generated.
127  * @retval false The event has not been generated.
128  */
129 NRF_STATIC_INLINE bool nrf_spi_event_check(NRF_SPI_Type const * p_reg,
130                                            nrf_spi_event_t      event);
131 
132 /**
133  * @brief Function for getting the address of the specified SPI event register.
134  *
135  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
136  * @param[in] event The specified event.
137  *
138  * @return Address of the specified event register.
139  */
140 NRF_STATIC_INLINE uint32_t nrf_spi_event_address_get(NRF_SPI_Type const * p_reg,
141                                                      nrf_spi_event_t      event);
142 
143 /**
144  * @brief Function for enabling the specified interrupts.
145  *
146  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
147  * @param[in] mask  Mask of interrupts to be enabled.
148  *                  Use @ref nrf_spi_int_mask_t values for bit masking.
149  */
150 NRF_STATIC_INLINE void nrf_spi_int_enable(NRF_SPI_Type * p_reg,
151                                           uint32_t       mask);
152 
153 /**
154  * @brief Function for disabling the specified interrupts.
155  *
156  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
157  * @param[in] mask  Mask of interrupts to be disabled.
158  *                  Use @ref nrf_spi_int_mask_t values for bit masking.
159  */
160 NRF_STATIC_INLINE void nrf_spi_int_disable(NRF_SPI_Type * p_reg,
161                                            uint32_t       mask);
162 
163 /**
164  * @brief Function for checking if the specified interrupts are enabled.
165  *
166  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
167  * @param[in] mask  Mask of interrupts to be checked.
168  *                  Use @ref nrf_spi_int_mask_t values for bit masking.
169  *
170  * @return Mask of enabled interrupts.
171  */
172 NRF_STATIC_INLINE uint32_t nrf_spi_int_enable_check(NRF_SPI_Type const * p_reg, uint32_t mask);
173 
174 /**
175  * @brief Function for enabling the SPI peripheral.
176  *
177  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
178  */
179 NRF_STATIC_INLINE void nrf_spi_enable(NRF_SPI_Type * p_reg);
180 
181 /**
182  * @brief Function for disabling the SPI peripheral.
183  *
184  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
185  */
186 NRF_STATIC_INLINE void nrf_spi_disable(NRF_SPI_Type * p_reg);
187 
188 /**
189  * @brief Function for configuring SPI pins.
190  *
191  * If a given signal is not needed, pass the @ref NRF_SPI_PIN_NOT_CONNECTED
192  * value instead of its pin number.
193  *
194  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
195  * @param[in] sck_pin  SCK pin number.
196  * @param[in] mosi_pin MOSI pin number.
197  * @param[in] miso_pin MISO pin number.
198  */
199 NRF_STATIC_INLINE void nrf_spi_pins_set(NRF_SPI_Type * p_reg,
200                                         uint32_t       sck_pin,
201                                         uint32_t       mosi_pin,
202                                         uint32_t       miso_pin);
203 
204 /**
205  * @brief Function for getting the SCK pin selection.
206  *
207  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
208  *
209  * @return SCK pin selection;
210  */
211 NRF_STATIC_INLINE uint32_t nrf_spi_sck_pin_get(NRF_SPI_Type const * p_reg);
212 
213 /**
214  * @brief Function for getting the MOSI pin selection.
215  *
216  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
217  *
218  * @return MOSI pin selection;
219  */
220 NRF_STATIC_INLINE uint32_t nrf_spi_mosi_pin_get(NRF_SPI_Type const * p_reg);
221 
222 /**
223  * @brief Function for getting the MISO pin selection.
224  *
225  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
226  *
227  * @return MISO pin selection;
228  */
229 NRF_STATIC_INLINE uint32_t nrf_spi_miso_pin_get(NRF_SPI_Type const * p_reg);
230 
231 /**
232  * @brief Function for writing data to the SPI transmitter register.
233  *
234  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
235  * @param[in] data  TX data to send.
236  */
237 NRF_STATIC_INLINE void nrf_spi_txd_set(NRF_SPI_Type * p_reg, uint8_t data);
238 
239 /**
240  * @brief Function for reading data from the SPI receiver register.
241  *
242  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
243  *
244  * @return RX data received.
245  */
246 NRF_STATIC_INLINE uint8_t nrf_spi_rxd_get(NRF_SPI_Type const * p_reg);
247 
248 /**
249  * @brief Function for setting the SPI master data rate.
250  *
251  * @param[in] p_reg     Pointer to the structure of registers of the peripheral.
252  * @param[in] frequency SPI frequency.
253  */
254 NRF_STATIC_INLINE void nrf_spi_frequency_set(NRF_SPI_Type *      p_reg,
255                                              nrf_spi_frequency_t frequency);
256 
257 /**
258  * @brief Function for setting the SPI configuration.
259  *
260  * @param[in] p_reg         Pointer to the structure of registers of the peripheral.
261  * @param[in] spi_mode      SPI mode.
262  * @param[in] spi_bit_order SPI bit order.
263  */
264 NRF_STATIC_INLINE void nrf_spi_configure(NRF_SPI_Type *      p_reg,
265                                          nrf_spi_mode_t      spi_mode,
266                                          nrf_spi_bit_order_t spi_bit_order);
267 
268 
269 #ifndef NRF_DECLARE_ONLY
270 
nrf_spi_event_clear(NRF_SPI_Type * p_reg,nrf_spi_event_t event)271 NRF_STATIC_INLINE void nrf_spi_event_clear(NRF_SPI_Type *  p_reg,
272                                            nrf_spi_event_t event)
273 {
274     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL;
275     nrf_event_readback((uint8_t *)p_reg + (uint32_t)event);
276 }
277 
nrf_spi_event_check(NRF_SPI_Type const * p_reg,nrf_spi_event_t event)278 NRF_STATIC_INLINE bool nrf_spi_event_check(NRF_SPI_Type const * p_reg,
279                                            nrf_spi_event_t      event)
280 {
281     return nrf_event_check(p_reg, event);
282 }
283 
nrf_spi_event_address_get(NRF_SPI_Type const * p_reg,nrf_spi_event_t event)284 NRF_STATIC_INLINE uint32_t nrf_spi_event_address_get(NRF_SPI_Type const * p_reg,
285                                                      nrf_spi_event_t      event)
286 {
287     return nrf_task_event_address_get(p_reg, event);
288 }
289 
nrf_spi_int_enable(NRF_SPI_Type * p_reg,uint32_t mask)290 NRF_STATIC_INLINE void nrf_spi_int_enable(NRF_SPI_Type * p_reg,
291                                           uint32_t       mask)
292 {
293     p_reg->INTENSET = mask;
294 }
295 
nrf_spi_int_disable(NRF_SPI_Type * p_reg,uint32_t mask)296 NRF_STATIC_INLINE void nrf_spi_int_disable(NRF_SPI_Type * p_reg,
297                                            uint32_t       mask)
298 {
299     p_reg->INTENCLR = mask;
300 }
301 
nrf_spi_int_enable_check(NRF_SPI_Type const * p_reg,uint32_t mask)302 NRF_STATIC_INLINE uint32_t nrf_spi_int_enable_check(NRF_SPI_Type const * p_reg, uint32_t mask)
303 {
304     return p_reg->INTENSET & mask;
305 }
306 
nrf_spi_enable(NRF_SPI_Type * p_reg)307 NRF_STATIC_INLINE void nrf_spi_enable(NRF_SPI_Type * p_reg)
308 {
309     p_reg->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
310 }
311 
nrf_spi_disable(NRF_SPI_Type * p_reg)312 NRF_STATIC_INLINE void nrf_spi_disable(NRF_SPI_Type * p_reg)
313 {
314     p_reg->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos);
315 }
316 
nrf_spi_pins_set(NRF_SPI_Type * p_reg,uint32_t sck_pin,uint32_t mosi_pin,uint32_t miso_pin)317 NRF_STATIC_INLINE void nrf_spi_pins_set(NRF_SPI_Type * p_reg,
318                                         uint32_t       sck_pin,
319                                         uint32_t       mosi_pin,
320                                         uint32_t       miso_pin)
321 {
322 #if defined(SPI_PSEL_SCK_CONNECT_Pos)
323     p_reg->PSEL.SCK = sck_pin;
324 #else
325     p_reg->PSELSCK  = sck_pin;
326 #endif
327 
328 #if defined(SPI_PSEL_MOSI_CONNECT_Pos)
329     p_reg->PSEL.MOSI = mosi_pin;
330 #else
331     p_reg->PSELMOSI = mosi_pin;
332 #endif
333 
334 #if defined(SPI_PSEL_MISO_CONNECT_Pos)
335     p_reg->PSEL.MISO = miso_pin;
336 #else
337     p_reg->PSELMISO = miso_pin;
338 #endif
339 }
340 
nrf_spi_sck_pin_get(NRF_SPI_Type const * p_reg)341 NRF_STATIC_INLINE uint32_t nrf_spi_sck_pin_get(NRF_SPI_Type const * p_reg)
342 {
343 #if defined(SPI_PSEL_SCK_CONNECT_Pos)
344     return p_reg->PSEL.SCK;
345 #else
346     return p_reg->PSELSCK;
347 #endif
348 }
349 
nrf_spi_mosi_pin_get(NRF_SPI_Type const * p_reg)350 NRF_STATIC_INLINE uint32_t nrf_spi_mosi_pin_get(NRF_SPI_Type const * p_reg)
351 {
352 #if defined(SPI_PSEL_MOSI_CONNECT_Pos)
353     return p_reg->PSEL.MOSI;
354 #else
355     return p_reg->PSELMOSI;
356 #endif
357 }
358 
nrf_spi_miso_pin_get(NRF_SPI_Type const * p_reg)359 NRF_STATIC_INLINE uint32_t nrf_spi_miso_pin_get(NRF_SPI_Type const * p_reg)
360 {
361 #if defined(SPI_PSEL_MISO_CONNECT_Pos)
362     return p_reg->PSEL.MISO;
363 #else
364     return p_reg->PSELMISO;
365 #endif
366 }
367 
nrf_spi_txd_set(NRF_SPI_Type * p_reg,uint8_t data)368 NRF_STATIC_INLINE void nrf_spi_txd_set(NRF_SPI_Type * p_reg, uint8_t data)
369 {
370     p_reg->TXD = data;
371 }
372 
nrf_spi_rxd_get(NRF_SPI_Type const * p_reg)373 NRF_STATIC_INLINE uint8_t nrf_spi_rxd_get(NRF_SPI_Type const * p_reg)
374 {
375     return (uint8_t)p_reg->RXD;
376 }
377 
nrf_spi_frequency_set(NRF_SPI_Type * p_reg,nrf_spi_frequency_t frequency)378 NRF_STATIC_INLINE void nrf_spi_frequency_set(NRF_SPI_Type *      p_reg,
379                                              nrf_spi_frequency_t frequency)
380 {
381     p_reg->FREQUENCY = (uint32_t)frequency;
382 }
383 
nrf_spi_configure(NRF_SPI_Type * p_reg,nrf_spi_mode_t spi_mode,nrf_spi_bit_order_t spi_bit_order)384 NRF_STATIC_INLINE void nrf_spi_configure(NRF_SPI_Type *      p_reg,
385                                          nrf_spi_mode_t      spi_mode,
386                                          nrf_spi_bit_order_t spi_bit_order)
387 {
388     uint32_t config = (spi_bit_order == NRF_SPI_BIT_ORDER_MSB_FIRST ?
389         SPI_CONFIG_ORDER_MsbFirst : SPI_CONFIG_ORDER_LsbFirst);
390     switch (spi_mode)
391     {
392     default:
393     case NRF_SPI_MODE_0:
394         config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos) |
395                   (SPI_CONFIG_CPHA_Leading    << SPI_CONFIG_CPHA_Pos);
396         break;
397 
398     case NRF_SPI_MODE_1:
399         config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos) |
400                   (SPI_CONFIG_CPHA_Trailing   << SPI_CONFIG_CPHA_Pos);
401         break;
402 
403     case NRF_SPI_MODE_2:
404         config |= (SPI_CONFIG_CPOL_ActiveLow  << SPI_CONFIG_CPOL_Pos) |
405                   (SPI_CONFIG_CPHA_Leading    << SPI_CONFIG_CPHA_Pos);
406         break;
407 
408     case NRF_SPI_MODE_3:
409         config |= (SPI_CONFIG_CPOL_ActiveLow  << SPI_CONFIG_CPOL_Pos) |
410                   (SPI_CONFIG_CPHA_Trailing   << SPI_CONFIG_CPHA_Pos);
411         break;
412     }
413     p_reg->CONFIG = config;
414 }
415 
416 #endif // NRF_DECLARE_ONLY
417 
418 /** @} */
419 
420 #ifdef __cplusplus
421 }
422 #endif
423 
424 #endif // NRF_SPI_H__
425