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 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 setting the SCK pin.
206 *
207 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
208 * @param[in] pin SCK pin number.
209 */
210 NRF_STATIC_INLINE void nrf_spi_sck_pin_set(NRF_SPI_Type * p_reg, uint32_t pin);
211
212 /**
213 * @brief Function for setting the MOSI pin
214 *
215 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
216 * @param[in] pin MOSI pin number.
217 */
218 NRF_STATIC_INLINE void nrf_spi_mosi_pin_set(NRF_SPI_Type * p_reg, uint32_t pin);
219
220 /**
221 * @brief Function for setting the MISO pin.
222 *
223 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
224 * @param[in] pin MISO pin number.
225 */
226 NRF_STATIC_INLINE void nrf_spi_miso_pin_set(NRF_SPI_Type * p_reg, uint32_t pin);
227
228 /**
229 * @brief Function for getting the SCK pin selection.
230 *
231 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
232 *
233 * @return SCK pin selection;
234 */
235 NRF_STATIC_INLINE uint32_t nrf_spi_sck_pin_get(NRF_SPI_Type const * p_reg);
236
237 /**
238 * @brief Function for getting the MOSI pin selection.
239 *
240 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
241 *
242 * @return MOSI pin selection;
243 */
244 NRF_STATIC_INLINE uint32_t nrf_spi_mosi_pin_get(NRF_SPI_Type const * p_reg);
245
246 /**
247 * @brief Function for getting the MISO pin selection.
248 *
249 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
250 *
251 * @return MISO pin selection;
252 */
253 NRF_STATIC_INLINE uint32_t nrf_spi_miso_pin_get(NRF_SPI_Type const * p_reg);
254
255 /**
256 * @brief Function for writing data to the SPI transmitter register.
257 *
258 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
259 * @param[in] data TX data to send.
260 */
261 NRF_STATIC_INLINE void nrf_spi_txd_set(NRF_SPI_Type * p_reg, uint8_t data);
262
263 /**
264 * @brief Function for reading data from the SPI receiver register.
265 *
266 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
267 *
268 * @return RX data received.
269 */
270 NRF_STATIC_INLINE uint8_t nrf_spi_rxd_get(NRF_SPI_Type const * p_reg);
271
272 /**
273 * @brief Function for setting the SPI master data rate.
274 *
275 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
276 * @param[in] frequency SPI frequency.
277 */
278 NRF_STATIC_INLINE void nrf_spi_frequency_set(NRF_SPI_Type * p_reg,
279 nrf_spi_frequency_t frequency);
280
281 /**
282 * @brief Function for setting the SPI configuration.
283 *
284 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
285 * @param[in] spi_mode SPI mode.
286 * @param[in] spi_bit_order SPI bit order.
287 */
288 NRF_STATIC_INLINE void nrf_spi_configure(NRF_SPI_Type * p_reg,
289 nrf_spi_mode_t spi_mode,
290 nrf_spi_bit_order_t spi_bit_order);
291
292
293 #ifndef NRF_DECLARE_ONLY
294
nrf_spi_event_clear(NRF_SPI_Type * p_reg,nrf_spi_event_t event)295 NRF_STATIC_INLINE void nrf_spi_event_clear(NRF_SPI_Type * p_reg,
296 nrf_spi_event_t event)
297 {
298 *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL;
299 nrf_event_readback((uint8_t *)p_reg + (uint32_t)event);
300 }
301
nrf_spi_event_check(NRF_SPI_Type const * p_reg,nrf_spi_event_t event)302 NRF_STATIC_INLINE bool nrf_spi_event_check(NRF_SPI_Type const * p_reg,
303 nrf_spi_event_t event)
304 {
305 return nrf_event_check(p_reg, event);
306 }
307
nrf_spi_event_address_get(NRF_SPI_Type const * p_reg,nrf_spi_event_t event)308 NRF_STATIC_INLINE uint32_t nrf_spi_event_address_get(NRF_SPI_Type const * p_reg,
309 nrf_spi_event_t event)
310 {
311 return nrf_task_event_address_get(p_reg, event);
312 }
313
nrf_spi_int_enable(NRF_SPI_Type * p_reg,uint32_t mask)314 NRF_STATIC_INLINE void nrf_spi_int_enable(NRF_SPI_Type * p_reg,
315 uint32_t mask)
316 {
317 p_reg->INTENSET = mask;
318 }
319
nrf_spi_int_disable(NRF_SPI_Type * p_reg,uint32_t mask)320 NRF_STATIC_INLINE void nrf_spi_int_disable(NRF_SPI_Type * p_reg,
321 uint32_t mask)
322 {
323 p_reg->INTENCLR = mask;
324 }
325
nrf_spi_int_enable_check(NRF_SPI_Type const * p_reg,uint32_t mask)326 NRF_STATIC_INLINE uint32_t nrf_spi_int_enable_check(NRF_SPI_Type const * p_reg, uint32_t mask)
327 {
328 return p_reg->INTENSET & mask;
329 }
330
nrf_spi_enable(NRF_SPI_Type * p_reg)331 NRF_STATIC_INLINE void nrf_spi_enable(NRF_SPI_Type * p_reg)
332 {
333 p_reg->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
334 }
335
nrf_spi_disable(NRF_SPI_Type * p_reg)336 NRF_STATIC_INLINE void nrf_spi_disable(NRF_SPI_Type * p_reg)
337 {
338 p_reg->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos);
339 }
340
nrf_spi_pins_set(NRF_SPI_Type * p_reg,uint32_t sck_pin,uint32_t mosi_pin,uint32_t miso_pin)341 NRF_STATIC_INLINE void nrf_spi_pins_set(NRF_SPI_Type * p_reg,
342 uint32_t sck_pin,
343 uint32_t mosi_pin,
344 uint32_t miso_pin)
345 {
346 #if defined(SPI_PSEL_SCK_CONNECT_Pos)
347 p_reg->PSEL.SCK = sck_pin;
348 #else
349 p_reg->PSELSCK = sck_pin;
350 #endif
351
352 #if defined(SPI_PSEL_MOSI_CONNECT_Pos)
353 p_reg->PSEL.MOSI = mosi_pin;
354 #else
355 p_reg->PSELMOSI = mosi_pin;
356 #endif
357
358 #if defined(SPI_PSEL_MISO_CONNECT_Pos)
359 p_reg->PSEL.MISO = miso_pin;
360 #else
361 p_reg->PSELMISO = miso_pin;
362 #endif
363 }
364
nrf_spi_sck_pin_set(NRF_SPI_Type * p_reg,uint32_t pin)365 NRF_STATIC_INLINE void nrf_spi_sck_pin_set(NRF_SPI_Type * p_reg, uint32_t pin)
366 {
367 #if defined(SPI_PSEL_SCK_CONNECT_Pos)
368 p_reg->PSEL.SCK = pin;
369 #else
370 p_reg->PSELSCK = pin;
371 #endif
372 }
373
nrf_spi_mosi_pin_set(NRF_SPI_Type * p_reg,uint32_t pin)374 NRF_STATIC_INLINE void nrf_spi_mosi_pin_set(NRF_SPI_Type * p_reg, uint32_t pin)
375 {
376 #if defined(SPI_PSEL_MOSI_CONNECT_Pos)
377 p_reg->PSEL.MOSI = pin;
378 #else
379 p_reg->PSELMOSI = pin;
380 #endif
381 }
382
nrf_spi_miso_pin_set(NRF_SPI_Type * p_reg,uint32_t pin)383 NRF_STATIC_INLINE void nrf_spi_miso_pin_set(NRF_SPI_Type * p_reg, uint32_t pin)
384 {
385 #if defined(SPI_PSEL_MISO_CONNECT_Pos)
386 p_reg->PSEL.MISO = pin;
387 #else
388 p_reg->PSELMISO = pin;
389 #endif
390 }
391
nrf_spi_sck_pin_get(NRF_SPI_Type const * p_reg)392 NRF_STATIC_INLINE uint32_t nrf_spi_sck_pin_get(NRF_SPI_Type const * p_reg)
393 {
394 #if defined(SPI_PSEL_SCK_CONNECT_Pos)
395 return p_reg->PSEL.SCK;
396 #else
397 return p_reg->PSELSCK;
398 #endif
399 }
400
nrf_spi_mosi_pin_get(NRF_SPI_Type const * p_reg)401 NRF_STATIC_INLINE uint32_t nrf_spi_mosi_pin_get(NRF_SPI_Type const * p_reg)
402 {
403 #if defined(SPI_PSEL_MOSI_CONNECT_Pos)
404 return p_reg->PSEL.MOSI;
405 #else
406 return p_reg->PSELMOSI;
407 #endif
408 }
409
nrf_spi_miso_pin_get(NRF_SPI_Type const * p_reg)410 NRF_STATIC_INLINE uint32_t nrf_spi_miso_pin_get(NRF_SPI_Type const * p_reg)
411 {
412 #if defined(SPI_PSEL_MISO_CONNECT_Pos)
413 return p_reg->PSEL.MISO;
414 #else
415 return p_reg->PSELMISO;
416 #endif
417 }
418
nrf_spi_txd_set(NRF_SPI_Type * p_reg,uint8_t data)419 NRF_STATIC_INLINE void nrf_spi_txd_set(NRF_SPI_Type * p_reg, uint8_t data)
420 {
421 p_reg->TXD = data;
422 }
423
nrf_spi_rxd_get(NRF_SPI_Type const * p_reg)424 NRF_STATIC_INLINE uint8_t nrf_spi_rxd_get(NRF_SPI_Type const * p_reg)
425 {
426 return (uint8_t)p_reg->RXD;
427 }
428
nrf_spi_frequency_set(NRF_SPI_Type * p_reg,nrf_spi_frequency_t frequency)429 NRF_STATIC_INLINE void nrf_spi_frequency_set(NRF_SPI_Type * p_reg,
430 nrf_spi_frequency_t frequency)
431 {
432 p_reg->FREQUENCY = (uint32_t)frequency;
433 }
434
nrf_spi_configure(NRF_SPI_Type * p_reg,nrf_spi_mode_t spi_mode,nrf_spi_bit_order_t spi_bit_order)435 NRF_STATIC_INLINE void nrf_spi_configure(NRF_SPI_Type * p_reg,
436 nrf_spi_mode_t spi_mode,
437 nrf_spi_bit_order_t spi_bit_order)
438 {
439 uint32_t config = (spi_bit_order == NRF_SPI_BIT_ORDER_MSB_FIRST ?
440 SPI_CONFIG_ORDER_MsbFirst : SPI_CONFIG_ORDER_LsbFirst);
441 switch (spi_mode)
442 {
443 default:
444 case NRF_SPI_MODE_0:
445 config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos) |
446 (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos);
447 break;
448
449 case NRF_SPI_MODE_1:
450 config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos) |
451 (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos);
452 break;
453
454 case NRF_SPI_MODE_2:
455 config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos) |
456 (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos);
457 break;
458
459 case NRF_SPI_MODE_3:
460 config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos) |
461 (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos);
462 break;
463 }
464 p_reg->CONFIG = config;
465 }
466
467 #endif // NRF_DECLARE_ONLY
468
469 /** @} */
470
471 #ifdef __cplusplus
472 }
473 #endif
474
475 #endif // NRF_SPI_H__
476