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 NRFX_GPIOTE_H__ 33 #define NRFX_GPIOTE_H__ 34 35 #include <nrfx.h> 36 #include <hal/nrf_gpiote.h> 37 #include <hal/nrf_gpio.h> 38 39 #ifdef __cplusplus 40 extern "C" { 41 #endif 42 43 /** 44 * @defgroup nrfx_gpiote GPIOTE driver 45 * @{ 46 * @ingroup nrf_gpiote 47 * @brief GPIO Task Event (GPIOTE) peripheral driver. 48 */ 49 50 /** @brief Input pin configuration. */ 51 typedef struct 52 { 53 nrf_gpiote_polarity_t sense; /**< Transition that triggers the interrupt. */ 54 nrf_gpio_pin_pull_t pull; /**< Pulling mode. */ 55 bool is_watcher : 1; /**< True when the input pin is tracking an output pin. */ 56 bool hi_accuracy : 1; /**< True when high accuracy (IN_EVENT) is used. */ 57 bool skip_gpio_setup : 1; /**< Do not change GPIO configuration */ 58 } nrfx_gpiote_in_config_t; 59 60 /** 61 * @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect low-to-high transition. 62 * @details Set hi_accu to true to use IN_EVENT. 63 */ 64 #define NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(hi_accu) \ 65 { \ 66 .sense = NRF_GPIOTE_POLARITY_LOTOHI, \ 67 .pull = NRF_GPIO_PIN_NOPULL, \ 68 .is_watcher = false, \ 69 .hi_accuracy = hi_accu, \ 70 .skip_gpio_setup = false, \ 71 } 72 73 /** 74 * @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect high-to-low transition. 75 * @details Set hi_accu to true to use IN_EVENT. 76 */ 77 #define NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(hi_accu) \ 78 { \ 79 .sense = NRF_GPIOTE_POLARITY_HITOLO, \ 80 .pull = NRF_GPIO_PIN_NOPULL, \ 81 .is_watcher = false, \ 82 .hi_accuracy = hi_accu, \ 83 .skip_gpio_setup = false, \ 84 } 85 86 /** 87 * @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect any change on the pin. 88 * @details Set hi_accu to true to use IN_EVENT. 89 */ 90 #define NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(hi_accu) \ 91 { \ 92 .sense = NRF_GPIOTE_POLARITY_TOGGLE, \ 93 .pull = NRF_GPIO_PIN_NOPULL, \ 94 .is_watcher = false, \ 95 .hi_accuracy = hi_accu, \ 96 .skip_gpio_setup = false, \ 97 } 98 99 /** 100 * @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect low-to-high transition. 101 * @details Set hi_accu to true to use IN_EVENT. 102 * @note This macro prepares configuration that skips the GPIO setup. 103 */ 104 #define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_LOTOHI(hi_accu) \ 105 { \ 106 .sense = NRF_GPIOTE_POLARITY_LOTOHI, \ 107 .pull = NRF_GPIO_PIN_NOPULL, \ 108 .is_watcher = false, \ 109 .hi_accuracy = hi_accu, \ 110 .skip_gpio_setup = true, \ 111 } 112 113 /** 114 * @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect high-to-low transition. 115 * @details Set hi_accu to true to use IN_EVENT. 116 * @note This macro prepares configuration that skips the GPIO setup. 117 */ 118 #define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO(hi_accu) \ 119 { \ 120 .sense = NRF_GPIOTE_POLARITY_HITOLO, \ 121 .pull = NRF_GPIO_PIN_NOPULL, \ 122 .is_watcher = false, \ 123 .hi_accuracy = hi_accu, \ 124 .skip_gpio_setup = true, \ 125 } 126 127 /** 128 * @brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect any change on the pin. 129 * @details Set hi_accu to true to use IN_EVENT. 130 * @note This macro prepares configuration that skips the GPIO setup. 131 */ 132 #define NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_TOGGLE(hi_accu) \ 133 { \ 134 .sense = NRF_GPIOTE_POLARITY_TOGGLE, \ 135 .pull = NRF_GPIO_PIN_NOPULL, \ 136 .is_watcher = false, \ 137 .hi_accuracy = hi_accu, \ 138 .skip_gpio_setup = true, \ 139 } 140 141 142 /** @brief Output pin configuration. */ 143 typedef struct 144 { 145 nrf_gpiote_polarity_t action; /**< Configuration of the pin task. */ 146 nrf_gpiote_outinit_t init_state; /**< Initial state of the output pin. */ 147 bool task_pin; /**< True if the pin is controlled by a GPIOTE task. */ 148 } nrfx_gpiote_out_config_t; 149 150 /** @brief Macro for configuring a pin to use as output. GPIOTE is not used for the pin. */ 151 #define NRFX_GPIOTE_CONFIG_OUT_SIMPLE(init_high) \ 152 { \ 153 .action = NRF_GPIOTE_POLARITY_LOTOHI, \ 154 .init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \ 155 .task_pin = false, \ 156 } 157 158 /** 159 * @brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from high to low. 160 * @details The task will clear the pin. Therefore, the pin is set initially. 161 */ 162 #define NRFX_GPIOTE_CONFIG_OUT_TASK_LOW \ 163 { \ 164 .init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH, \ 165 .task_pin = true, \ 166 .action = NRF_GPIOTE_POLARITY_HITOLO, \ 167 } 168 169 /** 170 * @brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from low to high. 171 * @details The task will set the pin. Therefore, the pin is cleared initially. 172 */ 173 #define NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH \ 174 { \ 175 .action = NRF_GPIOTE_POLARITY_LOTOHI, \ 176 .init_state = NRF_GPIOTE_INITIAL_VALUE_LOW, \ 177 .task_pin = true, \ 178 } 179 180 /** 181 * @brief Macro for configuring a pin to use the GPIO OUT TASK to toggle the pin state. 182 * @details The initial pin state must be provided. 183 */ 184 #define NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(init_high) \ 185 { \ 186 .action = NRF_GPIOTE_POLARITY_TOGGLE, \ 187 .init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \ 188 .task_pin = true, \ 189 } 190 191 /** @brief Pin. */ 192 typedef uint32_t nrfx_gpiote_pin_t; 193 194 /** 195 * @brief Pin event handler prototype. 196 * 197 * @param[in] pin Pin that triggered this event. 198 * @param[in] action Action that led to triggering this event. 199 */ 200 typedef void (*nrfx_gpiote_evt_handler_t)(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action); 201 202 /** 203 * @brief Function for initializing the GPIOTE module. 204 * 205 * @details Only static configuration is supported to prevent the shared 206 * resource being customized by the initiator. 207 * 208 * @param[in] interrupt_priority Interrupt priority. 209 * 210 * @retval NRFX_SUCCESS Initialization was successful. 211 * @retval NRFX_ERROR_INVALID_STATE The driver was already initialized. 212 */ 213 nrfx_err_t nrfx_gpiote_init(uint8_t interrupt_priority); 214 215 /** 216 * @brief Function for checking if the GPIOTE module is initialized. 217 * 218 * @details The GPIOTE module is a shared module. Therefore, check if 219 * the module is already initialized and skip initialization if it is. 220 * 221 * @retval true The module is already initialized. 222 * @retval false The module is not initialized. 223 */ 224 bool nrfx_gpiote_is_init(void); 225 226 /** @brief Function for uninitializing the GPIOTE module. */ 227 void nrfx_gpiote_uninit(void); 228 229 /** 230 * @brief Function for initializing a GPIOTE output pin. 231 * @details The output pin can be controlled by the CPU or by PPI. The initial 232 * configuration specifies which mode is used. If PPI mode is used, the driver 233 * attempts to allocate one of the available GPIOTE channels. If no channel is 234 * available, an error is returned. 235 * 236 * @param[in] pin Pin. 237 * @param[in] p_config Initial configuration. 238 * 239 * @retval NRFX_SUCCESS Initialization was successful. 240 * @retval NRFX_ERROR_BUSY The pin is already used. 241 * @retval NRFX_ERROR_NO_MEM No GPIOTE channel is available. 242 */ 243 nrfx_err_t nrfx_gpiote_out_init(nrfx_gpiote_pin_t pin, 244 nrfx_gpiote_out_config_t const * p_config); 245 246 /** 247 * @brief Function for uninitializing a GPIOTE output pin. 248 * @details The driver frees the GPIOTE channel if the output pin was using one. 249 * 250 * @param[in] pin Pin. 251 */ 252 void nrfx_gpiote_out_uninit(nrfx_gpiote_pin_t pin); 253 254 /** 255 * @brief Function for setting a GPIOTE output pin. 256 * 257 * @param[in] pin Pin. 258 */ 259 void nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin); 260 261 /** 262 * @brief Function for clearing a GPIOTE output pin. 263 * 264 * @param[in] pin Pin. 265 */ 266 void nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin); 267 268 /** 269 * @brief Function for toggling a GPIOTE output pin. 270 * 271 * @param[in] pin Pin. 272 */ 273 void nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin); 274 275 /** 276 * @brief Function for enabling a GPIOTE output pin task. 277 * 278 * @param[in] pin Pin. 279 */ 280 void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin); 281 282 /** 283 * @brief Function for disabling a GPIOTE output pin task. 284 * 285 * @param[in] pin Pin. 286 */ 287 void nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin); 288 289 /** 290 * @brief Function for getting the OUT task for the specified output pin. 291 * 292 * @details The returned task identifier can be used within @ref nrf_gpiote_hal, 293 * for example, to configure a DPPI channel. 294 * 295 * @param[in] pin Pin. 296 * 297 * @return OUT task associated with the specified output pin. 298 */ 299 nrf_gpiote_task_t nrfx_gpiote_out_task_get(nrfx_gpiote_pin_t pin); 300 301 /** 302 * @brief Function for getting the address of the OUT task for the specified output pin. 303 * 304 * @param[in] pin Pin. 305 * 306 * @return Address of OUT task. 307 */ 308 uint32_t nrfx_gpiote_out_task_addr_get(nrfx_gpiote_pin_t pin); 309 310 #if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__) 311 /** 312 * @brief Function for getting the SET task for the specified output pin. 313 * 314 * @details The returned task identifier can be used within @ref nrf_gpiote_hal, 315 * for example, to configure a DPPI channel. 316 * 317 * @param[in] pin Pin. 318 * 319 * @return SET task associated with the specified output pin. 320 */ 321 nrf_gpiote_task_t nrfx_gpiote_set_task_get(nrfx_gpiote_pin_t pin); 322 323 /** 324 * @brief Function for getting the address of the SET task for the specified output pin. 325 * 326 * @param[in] pin Pin. 327 * 328 * @return Address of SET task. 329 */ 330 uint32_t nrfx_gpiote_set_task_addr_get(nrfx_gpiote_pin_t pin); 331 #endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__) 332 333 #if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__) 334 /** 335 * @brief Function for getting the CLR task for the specified output pin. 336 * 337 * @details The returned task identifier can be used within @ref nrf_gpiote_hal, 338 * for example, to configure a DPPI channel. 339 * 340 * @param[in] pin Pin. 341 * 342 * @return CLR task associated with the specified output pin. 343 */ 344 nrf_gpiote_task_t nrfx_gpiote_clr_task_get(nrfx_gpiote_pin_t pin); 345 346 /** 347 * @brief Function for getting the address of the SET task for the specified output pin. 348 * 349 * @param[in] pin Pin. 350 * 351 * @return Address of CLR task. 352 */ 353 uint32_t nrfx_gpiote_clr_task_addr_get(nrfx_gpiote_pin_t pin); 354 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__) 355 356 /** 357 * @brief Function for initializing a GPIOTE input pin. 358 * @details The input pin can act in two ways: 359 * - lower accuracy but low power (high frequency clock not needed) 360 * - higher accuracy (high frequency clock required) 361 * 362 * The initial configuration specifies which mode is used. 363 * If high-accuracy mode is used, the driver attempts to allocate one 364 * of the available GPIOTE channels. If no channel is 365 * available, an error is returned. 366 * In low accuracy mode SENSE feature is used. In this case, only one active pin 367 * can be detected at a time. It can be worked around by setting all of the used 368 * low accuracy pins to toggle mode. 369 * For more information about SENSE functionality, refer to Product Specification. 370 * 371 * @param[in] pin Pin. 372 * @param[in] p_config Initial configuration. 373 * @param[in] evt_handler User function to be called when the configured transition occurs. 374 * 375 * @retval NRFX_SUCCESS Initialization was successful. 376 * @retval NRFX_ERROR_BUSY The pin is already used. 377 * @retval NRFX_ERROR_NO_MEM No GPIOTE channel is available. 378 */ 379 nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin, 380 nrfx_gpiote_in_config_t const * p_config, 381 nrfx_gpiote_evt_handler_t evt_handler); 382 383 /** 384 * @brief Function for uninitializing a GPIOTE input pin. 385 * @details The driver frees the GPIOTE channel if the input pin was using one. 386 * 387 * @param[in] pin Pin. 388 */ 389 void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin); 390 391 /** 392 * @brief Function for enabling sensing of a GPIOTE input pin. 393 * 394 * @details If the input pin is configured as high-accuracy pin, the function 395 * enables an IN_EVENT. Otherwise, the function enables the GPIO sense mechanism. 396 * The PORT event is shared between multiple pins, therefore the interrupt is always enabled. 397 * 398 * @param[in] pin Pin. 399 * @param[in] int_enable True to enable the interrupt. Always valid for a high-accuracy pin. 400 */ 401 void nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin, bool int_enable); 402 403 /** 404 * @brief Function for disabling a GPIOTE input pin. 405 * 406 * @param[in] pin Pin. 407 */ 408 void nrfx_gpiote_in_event_disable(nrfx_gpiote_pin_t pin); 409 410 /** 411 * @brief Function for checking if a GPIOTE input pin is set. 412 * 413 * @param[in] pin Pin. 414 * 415 * @retval true The input pin is set. 416 * @retval false The input pin is not set. 417 */ 418 bool nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin); 419 420 /** 421 * @brief Function for getting the GPIOTE event for the specified input pin. 422 * 423 * @details The returned event identifier can be used within @ref nrf_gpiote_hal, 424 * for example, to configure a DPPI channel. 425 * If the pin is configured to use low-accuracy mode, the PORT event 426 * is returned. 427 * 428 * @param[in] pin Pin. 429 * 430 * @return Event associated with the specified input pin. 431 */ 432 nrf_gpiote_event_t nrfx_gpiote_in_event_get(nrfx_gpiote_pin_t pin); 433 434 /** 435 * @brief Function for getting the address of a GPIOTE input pin event. 436 * @details If the pin is configured to use low-accuracy mode, the address of the PORT event is returned. 437 * 438 * @param[in] pin Pin. 439 * 440 * @return Address of the specified input pin event. 441 */ 442 uint32_t nrfx_gpiote_in_event_addr_get(nrfx_gpiote_pin_t pin); 443 444 /** 445 * @brief Function for forcing a specific state on the pin configured as task. 446 * 447 * @param[in] pin Pin. 448 * @param[in] state Pin state. 449 */ 450 void nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin, uint8_t state); 451 452 /** 453 * @brief Function for triggering the task OUT manually. 454 * 455 * @param[in] pin Pin. 456 */ 457 void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin); 458 459 #if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__) 460 /** 461 * @brief Function for triggering the task SET manually. 462 * 463 * @param[in] pin Pin. 464 */ 465 void nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin); 466 #endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__) 467 468 #if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__) 469 /** 470 * @brief Function for triggering the task CLR manually. 471 * 472 * @param[in] pin Pin. 473 */ 474 void nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin); 475 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__) 476 477 /** @} */ 478 479 480 void nrfx_gpiote_irq_handler(void); 481 482 483 #ifdef __cplusplus 484 } 485 #endif 486 487 #endif // NRFX_GPIOTE_H__ 488