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