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