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