xref: /nrf52832-nimble/nordic/nrfx/hal/nrf_spi.h (revision 150812a83cab50279bd772ef6db1bfaf255f2c5b)
1 /*
2  * Copyright (c) 2015 - 2018, 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 /**
57  * @brief SPI events.
58  */
59 typedef enum
60 {
61     /*lint -save -e30*/
62     NRF_SPI_EVENT_READY = offsetof(NRF_SPI_Type, EVENTS_READY) ///< TXD byte sent and RXD byte received.
63     /*lint -restore*/
64 } nrf_spi_event_t;
65 
66 /**
67  * @brief SPI interrupts.
68  */
69 typedef enum
70 {
71     NRF_SPI_INT_READY_MASK = SPI_INTENSET_READY_Msk, ///< Interrupt on READY event.
72     NRF_SPI_ALL_INTS_MASK  = SPI_INTENSET_READY_Msk  ///< All SPI interrupts.
73 } nrf_spi_int_mask_t;
74 
75 /**
76  * @brief SPI data rates.
77  */
78 typedef enum
79 {
80     NRF_SPI_FREQ_125K = SPI_FREQUENCY_FREQUENCY_K125,   ///< 125 kbps.
81     NRF_SPI_FREQ_250K = SPI_FREQUENCY_FREQUENCY_K250,   ///< 250 kbps.
82     NRF_SPI_FREQ_500K = SPI_FREQUENCY_FREQUENCY_K500,   ///< 500 kbps.
83     NRF_SPI_FREQ_1M   = SPI_FREQUENCY_FREQUENCY_M1,     ///< 1 Mbps.
84     NRF_SPI_FREQ_2M   = SPI_FREQUENCY_FREQUENCY_M2,     ///< 2 Mbps.
85     NRF_SPI_FREQ_4M   = SPI_FREQUENCY_FREQUENCY_M4,     ///< 4 Mbps.
86     // [conversion to 'int' needed to prevent compilers from complaining
87     //  that the provided value (0x80000000UL) is out of range of "int"]
88     NRF_SPI_FREQ_8M   = (int)SPI_FREQUENCY_FREQUENCY_M8 ///< 8 Mbps.
89 } nrf_spi_frequency_t;
90 
91 /**
92  * @brief SPI modes.
93  */
94 typedef enum
95 {
96     NRF_SPI_MODE_0, ///< SCK active high, sample on leading edge of clock.
97     NRF_SPI_MODE_1, ///< SCK active high, sample on trailing edge of clock.
98     NRF_SPI_MODE_2, ///< SCK active low, sample on leading edge of clock.
99     NRF_SPI_MODE_3  ///< SCK active low, sample on trailing edge of clock.
100 } nrf_spi_mode_t;
101 
102 /**
103  * @brief SPI bit orders.
104  */
105 typedef enum
106 {
107     NRF_SPI_BIT_ORDER_MSB_FIRST = SPI_CONFIG_ORDER_MsbFirst, ///< Most significant bit shifted out first.
108     NRF_SPI_BIT_ORDER_LSB_FIRST = SPI_CONFIG_ORDER_LsbFirst  ///< Least significant bit shifted out first.
109 } nrf_spi_bit_order_t;
110 
111 
112 /**
113  * @brief Function for clearing a specific SPI event.
114  *
115  * @param[in] p_reg     Pointer to the peripheral registers structure.
116  * @param[in] spi_event Event to clear.
117  */
118 __STATIC_INLINE void nrf_spi_event_clear(NRF_SPI_Type * p_reg,
119                                          nrf_spi_event_t spi_event);
120 
121 /**
122  * @brief Function for checking the state of a specific SPI event.
123  *
124  * @param[in] p_reg     Pointer to the peripheral registers structure.
125  * @param[in] spi_event Event to check.
126  *
127  * @retval true  If the event is set.
128  * @retval false If the event is not set.
129  */
130 __STATIC_INLINE bool nrf_spi_event_check(NRF_SPI_Type * p_reg,
131                                          nrf_spi_event_t spi_event);
132 
133 /**
134  * @brief Function for getting the address of a specific SPI event register.
135  *
136  * @param[in] p_reg     Pointer to the peripheral registers structure.
137  * @param[in] spi_event Requested event.
138  *
139  * @return Address of the specified event register.
140  */
141 __STATIC_INLINE uint32_t * nrf_spi_event_address_get(NRF_SPI_Type  * p_reg,
142                                                      nrf_spi_event_t spi_event);
143 
144 /**
145  * @brief Function for enabling specified interrupts.
146  *
147  * @param[in] p_reg         Pointer to the peripheral registers structure.
148  * @param[in] spi_int_mask  Interrupts to enable.
149  */
150 __STATIC_INLINE void nrf_spi_int_enable(NRF_SPI_Type * p_reg,
151                                         uint32_t spi_int_mask);
152 
153 /**
154  * @brief Function for disabling specified interrupts.
155  *
156  * @param[in] p_reg         Pointer to the peripheral registers structure.
157  * @param[in] spi_int_mask  Interrupts to disable.
158  */
159 __STATIC_INLINE void nrf_spi_int_disable(NRF_SPI_Type * p_reg,
160                                          uint32_t spi_int_mask);
161 
162 /**
163  * @brief Function for retrieving the state of a given interrupt.
164  *
165  * @param[in] p_reg   Pointer to the peripheral registers structure.
166  * @param[in] spi_int Interrupt to check.
167  *
168  * @retval true  If the interrupt is enabled.
169  * @retval false If the interrupt is not enabled.
170  */
171 __STATIC_INLINE bool nrf_spi_int_enable_check(NRF_SPI_Type * p_reg,
172                                               nrf_spi_int_mask_t spi_int);
173 
174 /**
175  * @brief Function for enabling the SPI peripheral.
176  *
177  * @param[in] p_reg Pointer to the peripheral registers structure.
178  */
179 __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 peripheral registers structure.
185  */
186 __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 peripheral registers structure.
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 __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 writing data to the SPI transmitter register.
206  *
207  * @param[in] p_reg Pointer to the peripheral registers structure.
208  * @param[in] data  TX data to send.
209  */
210 __STATIC_INLINE void nrf_spi_txd_set(NRF_SPI_Type * p_reg, uint8_t data);
211 
212 /**
213  * @brief Function for reading data from the SPI receiver register.
214  *
215  * @param[in] p_reg Pointer to the peripheral registers structure.
216  *
217  * @return RX data received.
218  */
219 __STATIC_INLINE uint8_t nrf_spi_rxd_get(NRF_SPI_Type * p_reg);
220 
221 /**
222  * @brief Function for setting the SPI master data rate.
223  *
224  * @param[in] p_reg     Pointer to the peripheral registers structure.
225  * @param[in] frequency SPI frequency.
226  */
227 __STATIC_INLINE void nrf_spi_frequency_set(NRF_SPI_Type * p_reg,
228                                            nrf_spi_frequency_t frequency);
229 
230 /**
231  * @brief Function for setting the SPI configuration.
232  *
233  * @param[in] p_reg         Pointer to the peripheral registers structure.
234  * @param[in] spi_mode      SPI mode.
235  * @param[in] spi_bit_order SPI bit order.
236  */
237 __STATIC_INLINE void nrf_spi_configure(NRF_SPI_Type * p_reg,
238                                        nrf_spi_mode_t spi_mode,
239                                        nrf_spi_bit_order_t spi_bit_order);
240 
241 
242 #ifndef SUPPRESS_INLINE_IMPLEMENTATION
243 
nrf_spi_event_clear(NRF_SPI_Type * p_reg,nrf_spi_event_t spi_event)244 __STATIC_INLINE void nrf_spi_event_clear(NRF_SPI_Type * p_reg,
245                                          nrf_spi_event_t spi_event)
246 {
247     *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spi_event)) = 0x0UL;
248 #if __CORTEX_M == 0x04
249     volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spi_event));
250     (void)dummy;
251 #endif
252 }
253 
nrf_spi_event_check(NRF_SPI_Type * p_reg,nrf_spi_event_t spi_event)254 __STATIC_INLINE bool nrf_spi_event_check(NRF_SPI_Type * p_reg,
255                                          nrf_spi_event_t spi_event)
256 {
257     return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)spi_event);
258 }
259 
nrf_spi_event_address_get(NRF_SPI_Type * p_reg,nrf_spi_event_t spi_event)260 __STATIC_INLINE uint32_t * nrf_spi_event_address_get(NRF_SPI_Type * p_reg,
261                                                      nrf_spi_event_t spi_event)
262 {
263     return (uint32_t *)((uint8_t *)p_reg + (uint32_t)spi_event);
264 }
265 
nrf_spi_int_enable(NRF_SPI_Type * p_reg,uint32_t spi_int_mask)266 __STATIC_INLINE void nrf_spi_int_enable(NRF_SPI_Type * p_reg,
267                                         uint32_t spi_int_mask)
268 {
269     p_reg->INTENSET = spi_int_mask;
270 }
271 
nrf_spi_int_disable(NRF_SPI_Type * p_reg,uint32_t spi_int_mask)272 __STATIC_INLINE void nrf_spi_int_disable(NRF_SPI_Type * p_reg,
273                                          uint32_t spi_int_mask)
274 {
275     p_reg->INTENCLR = spi_int_mask;
276 }
277 
nrf_spi_int_enable_check(NRF_SPI_Type * p_reg,nrf_spi_int_mask_t spi_int)278 __STATIC_INLINE bool nrf_spi_int_enable_check(NRF_SPI_Type * p_reg,
279                                               nrf_spi_int_mask_t spi_int)
280 {
281     return (bool)(p_reg->INTENSET & spi_int);
282 }
283 
nrf_spi_enable(NRF_SPI_Type * p_reg)284 __STATIC_INLINE void nrf_spi_enable(NRF_SPI_Type * p_reg)
285 {
286     p_reg->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
287 }
288 
nrf_spi_disable(NRF_SPI_Type * p_reg)289 __STATIC_INLINE void nrf_spi_disable(NRF_SPI_Type * p_reg)
290 {
291     p_reg->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos);
292 }
293 
nrf_spi_pins_set(NRF_SPI_Type * p_reg,uint32_t sck_pin,uint32_t mosi_pin,uint32_t miso_pin)294 __STATIC_INLINE void nrf_spi_pins_set(NRF_SPI_Type * p_reg,
295                                       uint32_t sck_pin,
296                                       uint32_t mosi_pin,
297                                       uint32_t miso_pin)
298 {
299     p_reg->PSELSCK  = sck_pin;
300     p_reg->PSELMOSI = mosi_pin;
301     p_reg->PSELMISO = miso_pin;
302 }
303 
nrf_spi_txd_set(NRF_SPI_Type * p_reg,uint8_t data)304 __STATIC_INLINE void nrf_spi_txd_set(NRF_SPI_Type * p_reg, uint8_t data)
305 {
306     p_reg->TXD = data;
307 }
308 
nrf_spi_rxd_get(NRF_SPI_Type * p_reg)309 __STATIC_INLINE uint8_t nrf_spi_rxd_get(NRF_SPI_Type * p_reg)
310 {
311     return p_reg->RXD;
312 }
313 
nrf_spi_frequency_set(NRF_SPI_Type * p_reg,nrf_spi_frequency_t frequency)314 __STATIC_INLINE void nrf_spi_frequency_set(NRF_SPI_Type * p_reg,
315                                            nrf_spi_frequency_t frequency)
316 {
317     p_reg->FREQUENCY = frequency;
318 }
319 
nrf_spi_configure(NRF_SPI_Type * p_reg,nrf_spi_mode_t spi_mode,nrf_spi_bit_order_t spi_bit_order)320 __STATIC_INLINE void nrf_spi_configure(NRF_SPI_Type * p_reg,
321                                        nrf_spi_mode_t spi_mode,
322                                        nrf_spi_bit_order_t spi_bit_order)
323 {
324     uint32_t config = (spi_bit_order == NRF_SPI_BIT_ORDER_MSB_FIRST ?
325         SPI_CONFIG_ORDER_MsbFirst : SPI_CONFIG_ORDER_LsbFirst);
326     switch (spi_mode)
327     {
328     default:
329     case NRF_SPI_MODE_0:
330         config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos) |
331                   (SPI_CONFIG_CPHA_Leading    << SPI_CONFIG_CPHA_Pos);
332         break;
333 
334     case NRF_SPI_MODE_1:
335         config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos) |
336                   (SPI_CONFIG_CPHA_Trailing   << SPI_CONFIG_CPHA_Pos);
337         break;
338 
339     case NRF_SPI_MODE_2:
340         config |= (SPI_CONFIG_CPOL_ActiveLow  << SPI_CONFIG_CPOL_Pos) |
341                   (SPI_CONFIG_CPHA_Leading    << SPI_CONFIG_CPHA_Pos);
342         break;
343 
344     case NRF_SPI_MODE_3:
345         config |= (SPI_CONFIG_CPOL_ActiveLow  << SPI_CONFIG_CPOL_Pos) |
346                   (SPI_CONFIG_CPHA_Trailing   << SPI_CONFIG_CPHA_Pos);
347         break;
348     }
349     p_reg->CONFIG = config;
350 }
351 
352 #endif // SUPPRESS_INLINE_IMPLEMENTATION
353 
354 /** @} */
355 
356 #ifdef __cplusplus
357 }
358 #endif
359 
360 #endif // NRF_SPI_H__
361