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_TWI_H__
33 #define NRF_TWI_H__
34
35 #include <nrfx.h>
36
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40
41 /**
42 * @defgroup nrf_twi_hal TWI HAL
43 * @{
44 * @ingroup nrf_twi
45 * @brief Hardware access layer for managing the TWI peripheral.
46 */
47
48 /**
49 * @brief TWI tasks.
50 */
51 typedef enum
52 {
53 /*lint -save -e30*/
54 NRF_TWI_TASK_STARTRX = offsetof(NRF_TWI_Type, TASKS_STARTRX), ///< Start TWI receive sequence.
55 NRF_TWI_TASK_STARTTX = offsetof(NRF_TWI_Type, TASKS_STARTTX), ///< Start TWI transmit sequence.
56 NRF_TWI_TASK_STOP = offsetof(NRF_TWI_Type, TASKS_STOP), ///< Stop TWI transaction.
57 NRF_TWI_TASK_SUSPEND = offsetof(NRF_TWI_Type, TASKS_SUSPEND), ///< Suspend TWI transaction.
58 NRF_TWI_TASK_RESUME = offsetof(NRF_TWI_Type, TASKS_RESUME) ///< Resume TWI transaction.
59 /*lint -restore*/
60 } nrf_twi_task_t;
61
62 /**
63 * @brief TWI events.
64 */
65 typedef enum
66 {
67 /*lint -save -e30*/
68 NRF_TWI_EVENT_STOPPED = offsetof(NRF_TWI_Type, EVENTS_STOPPED), ///< TWI stopped.
69 NRF_TWI_EVENT_RXDREADY = offsetof(NRF_TWI_Type, EVENTS_RXDREADY), ///< TWI RXD byte received.
70 NRF_TWI_EVENT_TXDSENT = offsetof(NRF_TWI_Type, EVENTS_TXDSENT), ///< TWI TXD byte sent.
71 NRF_TWI_EVENT_ERROR = offsetof(NRF_TWI_Type, EVENTS_ERROR), ///< TWI error.
72 NRF_TWI_EVENT_BB = offsetof(NRF_TWI_Type, EVENTS_BB), ///< TWI byte boundary, generated before each byte that is sent or received.
73 NRF_TWI_EVENT_SUSPENDED = offsetof(NRF_TWI_Type, EVENTS_SUSPENDED) ///< TWI entered the suspended state.
74 /*lint -restore*/
75 } nrf_twi_event_t;
76
77 /**
78 * @brief TWI shortcuts.
79 */
80 typedef enum
81 {
82 NRF_TWI_SHORT_BB_SUSPEND_MASK = TWI_SHORTS_BB_SUSPEND_Msk, ///< Shortcut between BB event and SUSPEND task.
83 NRF_TWI_SHORT_BB_STOP_MASK = TWI_SHORTS_BB_STOP_Msk, ///< Shortcut between BB event and STOP task.
84 NRF_TWI_ALL_SHORTS_MASK = TWI_SHORTS_BB_SUSPEND_Msk |
85 TWI_SHORTS_BB_STOP_Msk ///< All TWI shortcuts.
86 } nrf_twi_short_mask_t;
87
88 /**
89 * @brief TWI interrupts.
90 */
91 typedef enum
92 {
93 NRF_TWI_INT_STOPPED_MASK = TWI_INTENSET_STOPPED_Msk, ///< Interrupt on STOPPED event.
94 NRF_TWI_INT_RXDREADY_MASK = TWI_INTENSET_RXDREADY_Msk, ///< Interrupt on RXDREADY event.
95 NRF_TWI_INT_TXDSENT_MASK = TWI_INTENSET_TXDSENT_Msk, ///< Interrupt on TXDSENT event.
96 NRF_TWI_INT_ERROR_MASK = TWI_INTENSET_ERROR_Msk, ///< Interrupt on ERROR event.
97 NRF_TWI_INT_BB_MASK = TWI_INTENSET_BB_Msk, ///< Interrupt on BB event.
98 NRF_TWI_INT_SUSPENDED_MASK = TWI_INTENSET_SUSPENDED_Msk, ///< Interrupt on SUSPENDED event.
99 NRF_TWI_ALL_INTS_MASK = TWI_INTENSET_STOPPED_Msk |
100 TWI_INTENSET_RXDREADY_Msk |
101 TWI_INTENSET_TXDSENT_Msk |
102 TWI_INTENSET_ERROR_Msk |
103 TWI_INTENSET_BB_Msk |
104 TWI_INTENSET_SUSPENDED_Msk ///< All TWI interrupts.
105 } nrf_twi_int_mask_t;
106
107 /**
108 * @brief TWI error source.
109 */
110 typedef enum
111 {
112 NRF_TWI_ERROR_ADDRESS_NACK = TWI_ERRORSRC_ANACK_Msk, ///< NACK received after sending the address.
113 NRF_TWI_ERROR_DATA_NACK = TWI_ERRORSRC_DNACK_Msk, ///< NACK received after sending a data byte.
114 NRF_TWI_ERROR_OVERRUN = TWI_ERRORSRC_OVERRUN_Msk ///< Overrun error.
115 /**< A new byte was received before the previous byte was read
116 * from the RXD register (previous data is lost). */
117 } nrf_twi_error_t;
118
119 /**
120 * @brief TWI master clock frequency.
121 */
122 typedef enum
123 {
124 NRF_TWI_FREQ_100K = TWI_FREQUENCY_FREQUENCY_K100, ///< 100 kbps.
125 NRF_TWI_FREQ_250K = TWI_FREQUENCY_FREQUENCY_K250, ///< 250 kbps.
126 NRF_TWI_FREQ_400K = TWI_FREQUENCY_FREQUENCY_K400 ///< 400 kbps.
127 } nrf_twi_frequency_t;
128
129
130 /**
131 * @brief Function for activating a specific TWI task.
132 *
133 * @param[in] p_reg Pointer to the peripheral registers structure.
134 * @param[in] task Task to activate.
135 */
136 __STATIC_INLINE void nrf_twi_task_trigger(NRF_TWI_Type * p_reg,
137 nrf_twi_task_t task);
138
139 /**
140 * @brief Function for getting the address of a specific TWI task register.
141 *
142 * @param[in] p_reg Pointer to the peripheral registers structure.
143 * @param[in] task Requested task.
144 *
145 * @return Address of the specified task register.
146 */
147 __STATIC_INLINE uint32_t * nrf_twi_task_address_get(NRF_TWI_Type * p_reg,
148 nrf_twi_task_t task);
149
150 /**
151 * @brief Function for clearing a specific TWI event.
152 *
153 * @param[in] p_reg Pointer to the peripheral registers structure.
154 * @param[in] event Event to clear.
155 */
156 __STATIC_INLINE void nrf_twi_event_clear(NRF_TWI_Type * p_reg,
157 nrf_twi_event_t event);
158
159 /**
160 * @brief Function for checking the state of a specific event.
161 *
162 * @param[in] p_reg Pointer to the peripheral registers structure.
163 * @param[in] event Event to check.
164 *
165 * @retval true If the event is set.
166 * @retval false If the event is not set.
167 */
168 __STATIC_INLINE bool nrf_twi_event_check(NRF_TWI_Type * p_reg,
169 nrf_twi_event_t event);
170
171 /**
172 * @brief Function for getting the address of a specific TWI event register.
173 *
174 * @param[in] p_reg Pointer to the peripheral registers structure.
175 * @param[in] event Requested event.
176 *
177 * @return Address of the specified event register.
178 */
179 __STATIC_INLINE uint32_t * nrf_twi_event_address_get(NRF_TWI_Type * p_reg,
180 nrf_twi_event_t event);
181
182 /**
183 * @brief Function for enabling specified shortcuts.
184 *
185 * @param[in] p_reg Pointer to the peripheral registers structure.
186 * @param[in] shorts_mask Shortcuts to enable.
187 */
188 __STATIC_INLINE void nrf_twi_shorts_enable(NRF_TWI_Type * p_reg,
189 uint32_t shorts_mask);
190
191 /**
192 * @brief Function for disabling specified shortcuts.
193 *
194 * @param[in] p_reg Pointer to the peripheral registers structure.
195 * @param[in] shorts_mask Shortcuts to disable.
196 */
197 __STATIC_INLINE void nrf_twi_shorts_disable(NRF_TWI_Type * p_reg,
198 uint32_t shorts_mask);
199
200 /**
201 * @brief Function for enabling specified interrupts.
202 *
203 * @param[in] p_reg Pointer to the peripheral registers structure.
204 * @param[in] int_mask Interrupts to enable.
205 */
206 __STATIC_INLINE void nrf_twi_int_enable(NRF_TWI_Type * p_reg,
207 uint32_t int_mask);
208
209 /**
210 * @brief Function for disabling specified interrupts.
211 *
212 * @param[in] p_reg Pointer to the peripheral registers structure.
213 * @param[in] int_mask Interrupts to disable.
214 */
215 __STATIC_INLINE void nrf_twi_int_disable(NRF_TWI_Type * p_reg,
216 uint32_t int_mask);
217
218 /**
219 * @brief Function for retrieving the state of a given interrupt.
220 *
221 * @param[in] p_reg Pointer to the peripheral registers structure.
222 * @param[in] int_mask Interrupt to check.
223 *
224 * @retval true If the interrupt is enabled.
225 * @retval false If the interrupt is not enabled.
226 */
227 __STATIC_INLINE bool nrf_twi_int_enable_check(NRF_TWI_Type * p_reg,
228 nrf_twi_int_mask_t int_mask);
229
230 /**
231 * @brief Function for enabling the TWI peripheral.
232 *
233 * @param[in] p_reg Pointer to the peripheral registers structure.
234 */
235 __STATIC_INLINE void nrf_twi_enable(NRF_TWI_Type * p_reg);
236
237 /**
238 * @brief Function for disabling the TWI peripheral.
239 *
240 * @param[in] p_reg Pointer to the peripheral registers structure.
241 */
242 __STATIC_INLINE void nrf_twi_disable(NRF_TWI_Type * p_reg);
243
244 /**
245 * @brief Function for configuring TWI pins.
246 *
247 *
248 * @param[in] p_reg Pointer to the peripheral registers structure.
249 * @param[in] scl_pin SCL pin number.
250 * @param[in] sda_pin SDA pin number.
251 */
252 __STATIC_INLINE void nrf_twi_pins_set(NRF_TWI_Type * p_reg,
253 uint32_t scl_pin,
254 uint32_t sda_pin);
255
256 /**
257 * @brief Function for setting the TWI master clock frequency.
258 *
259 * @param[in] p_reg Pointer to the peripheral registers structure.
260 * @param[in] frequency TWI frequency.
261 */
262 __STATIC_INLINE void nrf_twi_frequency_set(NRF_TWI_Type * p_reg,
263 nrf_twi_frequency_t frequency);
264
265 /**
266 * @brief Function for checking the TWI error source.
267 *
268 * The error flags are cleared after reading.
269 *
270 * @param[in] p_reg Pointer to the peripheral registers structure.
271 *
272 * @return Mask with error source flags.
273 */
274 __STATIC_INLINE uint32_t nrf_twi_errorsrc_get_and_clear(NRF_TWI_Type * p_reg);
275
276 /**
277 * @brief Function for setting the address to be used in TWI transfers.
278 *
279 * @param[in] p_reg Pointer to the peripheral registers structure.
280 * @param[in] address Address to be used in transfers.
281 */
282 __STATIC_INLINE void nrf_twi_address_set(NRF_TWI_Type * p_reg, uint8_t address);
283
284 /**
285 * @brief Function for reading data received by TWI.
286 *
287 * @param[in] p_reg Pointer to the peripheral registers structure.
288 *
289 * @return Received data.
290 */
291 __STATIC_INLINE uint8_t nrf_twi_rxd_get(NRF_TWI_Type * p_reg);
292
293 /**
294 * @brief Function for writing data to be transmitted by TWI.
295 *
296 * @param[in] p_reg Pointer to the peripheral registers structure.
297 * @param[in] data Data to be transmitted.
298 */
299 __STATIC_INLINE void nrf_twi_txd_set(NRF_TWI_Type * p_reg, uint8_t data);
300
301 __STATIC_INLINE void nrf_twi_shorts_set(NRF_TWI_Type * p_reg,
302 uint32_t shorts_mask);
303
304 #ifndef SUPPRESS_INLINE_IMPLEMENTATION
305
nrf_twi_task_trigger(NRF_TWI_Type * p_reg,nrf_twi_task_t task)306 __STATIC_INLINE void nrf_twi_task_trigger(NRF_TWI_Type * p_reg,
307 nrf_twi_task_t task)
308 {
309 *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL;
310 }
311
nrf_twi_task_address_get(NRF_TWI_Type * p_reg,nrf_twi_task_t task)312 __STATIC_INLINE uint32_t * nrf_twi_task_address_get(NRF_TWI_Type * p_reg,
313 nrf_twi_task_t task)
314 {
315 return (uint32_t *)((uint8_t *)p_reg + (uint32_t)task);
316 }
317
nrf_twi_event_clear(NRF_TWI_Type * p_reg,nrf_twi_event_t event)318 __STATIC_INLINE void nrf_twi_event_clear(NRF_TWI_Type * p_reg,
319 nrf_twi_event_t event)
320 {
321 *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL;
322 #if __CORTEX_M == 0x04
323 volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event));
324 (void)dummy;
325 #endif
326 }
327
nrf_twi_event_check(NRF_TWI_Type * p_reg,nrf_twi_event_t event)328 __STATIC_INLINE bool nrf_twi_event_check(NRF_TWI_Type * p_reg,
329 nrf_twi_event_t event)
330 {
331 return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event);
332 }
333
nrf_twi_event_address_get(NRF_TWI_Type * p_reg,nrf_twi_event_t event)334 __STATIC_INLINE uint32_t * nrf_twi_event_address_get(NRF_TWI_Type * p_reg,
335 nrf_twi_event_t event)
336 {
337 return (uint32_t *)((uint8_t *)p_reg + (uint32_t)event);
338 }
339
nrf_twi_shorts_enable(NRF_TWI_Type * p_reg,uint32_t shorts_mask)340 __STATIC_INLINE void nrf_twi_shorts_enable(NRF_TWI_Type * p_reg,
341 uint32_t shorts_mask)
342 {
343 p_reg->SHORTS |= shorts_mask;
344 }
345
nrf_twi_shorts_disable(NRF_TWI_Type * p_reg,uint32_t shorts_mask)346 __STATIC_INLINE void nrf_twi_shorts_disable(NRF_TWI_Type * p_reg,
347 uint32_t shorts_mask)
348 {
349 p_reg->SHORTS &= ~(shorts_mask);
350 }
351
nrf_twi_int_enable(NRF_TWI_Type * p_reg,uint32_t int_mask)352 __STATIC_INLINE void nrf_twi_int_enable(NRF_TWI_Type * p_reg,
353 uint32_t int_mask)
354 {
355 p_reg->INTENSET = int_mask;
356 }
357
nrf_twi_int_disable(NRF_TWI_Type * p_reg,uint32_t int_mask)358 __STATIC_INLINE void nrf_twi_int_disable(NRF_TWI_Type * p_reg,
359 uint32_t int_mask)
360 {
361 p_reg->INTENCLR = int_mask;
362 }
363
nrf_twi_int_enable_check(NRF_TWI_Type * p_reg,nrf_twi_int_mask_t int_mask)364 __STATIC_INLINE bool nrf_twi_int_enable_check(NRF_TWI_Type * p_reg,
365 nrf_twi_int_mask_t int_mask)
366 {
367 return (bool)(p_reg->INTENSET & int_mask);
368 }
369
nrf_twi_enable(NRF_TWI_Type * p_reg)370 __STATIC_INLINE void nrf_twi_enable(NRF_TWI_Type * p_reg)
371 {
372 p_reg->ENABLE = (TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos);
373 }
374
nrf_twi_disable(NRF_TWI_Type * p_reg)375 __STATIC_INLINE void nrf_twi_disable(NRF_TWI_Type * p_reg)
376 {
377 p_reg->ENABLE = (TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos);
378 }
379
nrf_twi_pins_set(NRF_TWI_Type * p_reg,uint32_t scl_pin,uint32_t sda_pin)380 __STATIC_INLINE void nrf_twi_pins_set(NRF_TWI_Type * p_reg,
381 uint32_t scl_pin,
382 uint32_t sda_pin)
383 {
384 #if defined(TWI_PSEL_SCL_CONNECT_Pos)
385 p_reg->PSEL.SCL = scl_pin;
386 #else
387 p_reg->PSELSCL = scl_pin;
388 #endif
389
390 #if defined(TWI_PSEL_SDA_CONNECT_Pos)
391 p_reg->PSEL.SDA = sda_pin;
392 #else
393 p_reg->PSELSDA = sda_pin;
394 #endif
395 }
396
nrf_twi_frequency_set(NRF_TWI_Type * p_reg,nrf_twi_frequency_t frequency)397 __STATIC_INLINE void nrf_twi_frequency_set(NRF_TWI_Type * p_reg,
398 nrf_twi_frequency_t frequency)
399 {
400 p_reg->FREQUENCY = frequency;
401 }
402
nrf_twi_errorsrc_get_and_clear(NRF_TWI_Type * p_reg)403 __STATIC_INLINE uint32_t nrf_twi_errorsrc_get_and_clear(NRF_TWI_Type * p_reg)
404 {
405 uint32_t error_source = p_reg->ERRORSRC;
406
407 // [error flags are cleared by writing '1' on their position]
408 p_reg->ERRORSRC = error_source;
409
410 return error_source;
411 }
412
nrf_twi_address_set(NRF_TWI_Type * p_reg,uint8_t address)413 __STATIC_INLINE void nrf_twi_address_set(NRF_TWI_Type * p_reg, uint8_t address)
414 {
415 p_reg->ADDRESS = address;
416 }
417
nrf_twi_rxd_get(NRF_TWI_Type * p_reg)418 __STATIC_INLINE uint8_t nrf_twi_rxd_get(NRF_TWI_Type * p_reg)
419 {
420 return (uint8_t)p_reg->RXD;
421 }
422
nrf_twi_txd_set(NRF_TWI_Type * p_reg,uint8_t data)423 __STATIC_INLINE void nrf_twi_txd_set(NRF_TWI_Type * p_reg, uint8_t data)
424 {
425 p_reg->TXD = data;
426 }
427
nrf_twi_shorts_set(NRF_TWI_Type * p_reg,uint32_t shorts_mask)428 __STATIC_INLINE void nrf_twi_shorts_set(NRF_TWI_Type * p_reg,
429 uint32_t shorts_mask)
430 {
431 p_reg->SHORTS = shorts_mask;
432 }
433
434 #endif // SUPPRESS_INLINE_IMPLEMENTATION
435
436 /** @} */
437
438 #ifdef __cplusplus
439 }
440 #endif
441
442 #endif // NRF_TWI_H__
443