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