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