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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 413 __STATIC_INLINE void nrf_twi_address_set(NRF_TWI_Type * p_reg, uint8_t address) 414 { 415 p_reg->ADDRESS = address; 416 } 417 418 __STATIC_INLINE uint8_t nrf_twi_rxd_get(NRF_TWI_Type * p_reg) 419 { 420 return (uint8_t)p_reg->RXD; 421 } 422 423 __STATIC_INLINE void nrf_twi_txd_set(NRF_TWI_Type * p_reg, uint8_t data) 424 { 425 p_reg->TXD = data; 426 } 427 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