1 /***************************************************************************//** 2 * \file cyhal_gpio.h 3 * 4 * \brief 5 * Provides a high level interface for interacting with the GPIO on Infineon devices. 6 * This interface abstracts out the chip specific details. If any chip specific 7 * functionality is necessary, or performance is critical the low level functions 8 * can be used directly. 9 * 10 ******************************************************************************** 11 * \copyright 12 * Copyright 2018-2021 Cypress Semiconductor Corporation (an Infineon company) or 13 * an affiliate of Cypress Semiconductor Corporation 14 * 15 * SPDX-License-Identifier: Apache-2.0 16 * 17 * Licensed under the Apache License, Version 2.0 (the "License"); 18 * you may not use this file except in compliance with the License. 19 * You may obtain a copy of the License at 20 * 21 * http://www.apache.org/licenses/LICENSE-2.0 22 * 23 * Unless required by applicable law or agreed to in writing, software 24 * distributed under the License is distributed on an "AS IS" BASIS, 25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 * See the License for the specific language governing permissions and 27 * limitations under the License. 28 *******************************************************************************/ 29 30 /** 31 * \addtogroup group_hal_gpio GPIO (General Purpose Input Output) 32 * \ingroup group_hal 33 * \{ 34 * High level interface for configuring and interacting with general purpose input/outputs (GPIO). 35 * 36 * The GPIO driver provides functions to configure and initialize GPIO, and to read and write data to the pin. 37 * The driver also supports interrupt generation on GPIO signals with rising, falling or both edges. 38 * 39 * \note The APIs in this driver need not be used if a GPIO is to be used as an input or output of peripherals like I2C or PWM. 40 * The respective peripheral's driver will utilize the GPIO interface to configure and initialize its GPIO pins. 41 * 42 * \section subsection_gpio_features Features 43 * * Configurable GPIO pin direction - \ref cyhal_gpio_direction_t 44 * * Configurable GPIO pin drive modes - \ref cyhal_gpio_drive_mode_t 45 * * Configurable analog and digital characteristics 46 * * Configurable edge-triggered interrupts and callback assignment on GPIO events - \ref cyhal_gpio_event_t 47 * 48 * \section subsection_gpio_quickstart Quick Start 49 * \ref cyhal_gpio_init can be used for a simple GPIO initialization by providing the pin number (<b>pin</b>), pin direction (<b>direction</b>), 50 * pin drive mode (<b>drive_mode</b>) and the initial value on the pin (<b>init_val</b>). 51 * 52 * \section subsection_gpio_sample_snippets Code Snippets 53 * 54 * \subsection subsection_gpio_snippet_1 Snippet 1: Reading value from GPIO 55 * The following snippet initializes GPIO pin as an input with high impedance digital drive mode and initial value = <b>false</b> (low). A value is read 56 * from the pin and stored to a uint8_t variable (<b>read_val</b>). 57 58 * \snippet hal_gpio.c snippet_cyhal_gpio_read 59 60 * \subsection subsection_gpio_snippet_2 Snippet 2: Writing value to a GPIO 61 * The following snippet initializes GPIO pin as an output pin with strong drive mode and initial value = <b>false</b> (low). 62 * A value = <b>true</b> (high) is written to the output driver. 63 64 * \snippet hal_gpio.c snippet_cyhal_gpio_write 65 66 * \subsection subsection_gpio_snippet_3 Snippet 3: Reconfiguring a GPIO 67 * The following snippet shows how to reconfigure a GPIO pin during run-time using the firmware. The GPIO pin 68 * is first initialized as an output pin with strong drive mode. The pin is then reconfigured as an input with high impedance digital drive mode. 69 * \note \ref cyhal_gpio_configure only changes the <b>direction</b> and the <b>drive_mode</b> 70 * of the pin. Previously set pin value is retained. 71 * 72 * \snippet hal_gpio.c snippet_cyhal_gpio_reconfigure 73 74 * \subsection subsection_gpio_snippet_4 Snippet 4: Interrupts on GPIO events 75 * GPIO events can be mapped to an interrupt and assigned to a callback function. The callback function needs to be first registered and 76 * then the event needs to be enabled. 77 ** The following snippet initializes GPIO pin as an input pin. It registers a callback function and enables detection 78 * of a falling edge event to trigger the callback. 79 * \note If no argument needs to be passed to the callback function then a NULL can be passed during registering. <br> 80 * 81 * \snippet hal_gpio.c snippet_cyhal_gpio_interrupt 82 */ 83 84 #pragma once 85 86 #include <stdint.h> 87 #include <stdbool.h> 88 #include "cy_result.h" 89 #include "cyhal_hw_types.h" 90 91 #if defined(__cplusplus) 92 extern "C" { 93 #endif /* __cplusplus */ 94 95 /** \addtogroup group_hal_results_gpio GPIO HAL Results 96 * GPIO specific return codes 97 * \ingroup group_hal_results 98 * \{ *//** 99 */ 100 101 /** The specified pin has no supported input signal */ 102 #define CYHAL_GPIO_RSLT_ERR_NO_INPUT_SIGNAL \ 103 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_GPIO, 0)) 104 /** The specified pin has no supported output signal */ 105 #define CYHAL_GPIO_RSLT_ERR_NO_OUTPUT_SIGNAL \ 106 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_GPIO, 1)) 107 /** The parameter is invalid */ 108 #define CYHAL_GPIO_RSLT_ERR_BAD_PARAM \ 109 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_GPIO, 2)) 110 111 /** 112 * \} 113 */ 114 115 /******************************************************************************* 116 * Defines 117 *******************************************************************************/ 118 119 /** Integer representation of no connect pin (required to exist in all BSPs) */ 120 #define CYHAL_NC_PIN_VALUE (NC) 121 122 /******************************************************************************* 123 * Enumerations 124 *******************************************************************************/ 125 126 /** Pin events */ 127 typedef enum 128 { 129 CYHAL_GPIO_IRQ_NONE = 0, /**< No interrupt */ 130 CYHAL_GPIO_IRQ_RISE = 1 << 0, /**< Interrupt on rising edge */ 131 CYHAL_GPIO_IRQ_FALL = 1 << 1, /**< Interrupt on falling edge */ 132 CYHAL_GPIO_IRQ_BOTH = (CYHAL_GPIO_IRQ_RISE | CYHAL_GPIO_IRQ_FALL), /**< Interrupt on both rising and falling edges */ 133 } cyhal_gpio_event_t; 134 135 /** Pin direction */ 136 typedef enum 137 { 138 CYHAL_GPIO_DIR_INPUT, /**< Input pin */ 139 CYHAL_GPIO_DIR_OUTPUT, /**< Output pin */ 140 CYHAL_GPIO_DIR_BIDIRECTIONAL, /**< Input and output pin */ 141 } cyhal_gpio_direction_t; 142 143 /** Pin drive mode */ 144 145 /** \note When the <b> drive_mode </b> of the <b> pin </b> is set to <b> CYHAL_GPIO_DRIVE_PULL_NONE </b>, 146 * it is set to <b> CYHAL_GPIO_DRIVE_STRONG </b> if the <b> direction </b> 147 * of the <b> pin </b> is <b> CYHAL_GPIO_DIR_OUTPUT </b> or <b> CYHAL_GPIO_DIR_BIDIRECTIONAL</b>. 148 * If not, the <b> drive_mode </b> of the <b> pin </b> is set to <b> CYHAL_GPIO_DRIVE_NONE</b>. 149 */ 150 typedef enum 151 { 152 CYHAL_GPIO_DRIVE_NONE, /**< Digital Hi-Z. Input only. Input init value(s): 0 or 1 */ 153 CYHAL_GPIO_DRIVE_ANALOG, /**< Analog Hi-Z. Use only for analog purpose */ 154 CYHAL_GPIO_DRIVE_PULLUP, /**< Pull-up resistor. Input and output. Input init value(s): 1, output value(s): 0 */ 155 CYHAL_GPIO_DRIVE_PULLDOWN, /**< Pull-down resistor. Input and output. Input init value(s): 0, output value(s): 1 */ 156 CYHAL_GPIO_DRIVE_OPENDRAINDRIVESLOW, /**< Open-drain, Drives Low. Input and output. Input init value(s): 1, output value(s): 0 */ 157 CYHAL_GPIO_DRIVE_OPENDRAINDRIVESHIGH, /**< Open-drain, Drives High. Input and output. Input init value(s): 0, output value(s): 1 */ 158 CYHAL_GPIO_DRIVE_STRONG, /**< Strong output. Output only. Output init value(s): 0 or 1 */ 159 CYHAL_GPIO_DRIVE_PULLUPDOWN, /**< Pull-up and pull-down resistors. Input and output. Input init value(s): 0 or 1, output value(s): 0 or 1 */ 160 CYHAL_GPIO_DRIVE_PULL_NONE, /**< No Pull-up or pull-down resistors. Input and output. Input init value(s): 0 or 1, output value(s): 0 or 1 */ 161 } cyhal_gpio_drive_mode_t; 162 163 /** GPIO callback function type */ 164 typedef void (*cyhal_gpio_event_callback_t)(void *callback_arg, cyhal_gpio_event_t event); 165 166 /** Structure containing callback data for pins. 167 * Instances of this object are expected to persist for the length of time the callback is 168 * registered. As such, care must be given if declaring it on the stack to ensure the frame does 169 * not go away while the callback is still registered.*/ 170 typedef struct cyhal_gpio_callback_data_s 171 { 172 cyhal_gpio_event_callback_t callback; /**< The callback function to run */ 173 void* callback_arg; /**< Optional argument for the callback */ 174 struct cyhal_gpio_callback_data_s* next; /**< NULL. Filled in by the HAL driver */ 175 cyhal_gpio_t pin; /**< NC. Filled in by the HAL driver */ 176 } cyhal_gpio_callback_data_t; 177 178 /******************************************************************************* 179 * Functions 180 *******************************************************************************/ 181 182 /** Initialize the GPIO pin <br> 183 * See \ref subsection_gpio_snippet_1. 184 * 185 * @param[in] pin The GPIO pin to initialize 186 * @param[in] direction The pin direction 187 * @param[in] drive_mode The pin drive mode 188 * @param[in] init_val Initial value on the pin 189 * 190 * @return The status of the init request 191 * 192 * Guidance for using gpio drive modes ( \ref cyhal_gpio_drive_mode_t for details). 193 * For default use drive modes: 194 * Input GPIO direction - \ref CYHAL_GPIO_DRIVE_NONE 195 * Output GPIO direction - \ref CYHAL_GPIO_DRIVE_STRONG 196 * Bidirectional GPIO - \ref CYHAL_GPIO_DRIVE_PULLUPDOWN 197 * \warning Don't use \ref CYHAL_GPIO_DRIVE_STRONG for input GPIO direction. It may cause an overcurrent issue. 198 */ 199 cy_rslt_t cyhal_gpio_init(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drive_mode, bool init_val); 200 201 /** Uninitialize the gpio peripheral and the cyhal_gpio_t object 202 * 203 * @param[in] pin Pin number 204 */ 205 void cyhal_gpio_free(cyhal_gpio_t pin); 206 207 /** Configure the GPIO pin <br> 208 * See \ref subsection_gpio_snippet_3. 209 * 210 * @param[in] pin The GPIO pin 211 * @param[in] direction The pin direction 212 * @param[in] drive_mode The pin drive mode 213 * 214 * @return The status of the configure request 215 */ 216 cy_rslt_t cyhal_gpio_configure(cyhal_gpio_t pin, cyhal_gpio_direction_t direction, cyhal_gpio_drive_mode_t drive_mode); 217 218 /** Set the output value for the pin. This only works for output & in_out pins. <br> 219 * See \ref subsection_gpio_snippet_2. 220 * 221 * @param[in] pin The GPIO object 222 * @param[in] value The value to be set (high = true, low = false) 223 */ 224 void cyhal_gpio_write(cyhal_gpio_t pin, bool value); 225 226 /** Read the input value. This only works for \ref CYHAL_GPIO_DIR_INPUT & \ref CYHAL_GPIO_DIR_BIDIRECTIONAL pins. <br> 227 * See \ref subsection_gpio_snippet_1. 228 * 229 * @param[in] pin The GPIO object 230 * @return The value of the IO (true = high, false = low) 231 */ 232 bool cyhal_gpio_read(cyhal_gpio_t pin); 233 234 /** Toggle the output value <br> 235 * See \ref subsection_gpio_snippet_4. 236 * @param[in] pin The GPIO object 237 */ 238 void cyhal_gpio_toggle(cyhal_gpio_t pin); 239 240 /** Register/clear a callback handler for pin events <br> 241 * 242 * The referenced function will be called when one of the events enabled by \ref 243 * cyhal_gpio_enable_event occurs. 244 * 245 * See \ref subsection_gpio_snippet_4. 246 * 247 * \note The signature for this function is slightly different from other HAL register_callback 248 * functions. This is because the cyhal_gpio_t is a enum value and not a pointer to a struct. This 249 * prevents storing the callback information on the instance object itself. So instead we need a 250 * different mechanism to keep track of this data. 251 * 252 * @param[in] pin The GPIO object 253 * @param[in] callback_data The callback data to register. Use NULL to unregister. This object must 254 * persist for the length of time the callback is registered. As such, it 255 * should not be declared on the stack. 256 */ 257 void cyhal_gpio_register_callback(cyhal_gpio_t pin, cyhal_gpio_callback_data_t* callback_data); 258 259 /** Enable or Disable the specified GPIO event <br> 260 * 261 * When an enabled event occurs, the function specified by \ref cyhal_gpio_register_callback will be called. 262 * 263 * See \ref subsection_gpio_snippet_4. 264 * 265 * @param[in] pin The GPIO object 266 * @param[in] event The GPIO event 267 * @param[in] intr_priority The priority for NVIC interrupt events. Interrupt priorities specific to a pin may not 268 * be supported on all platforms. Refer to platform implementation specific documentation 269 * for details. 270 * @param[in] enable True to turn on interrupts, False to turn off 271 */ 272 void cyhal_gpio_enable_event(cyhal_gpio_t pin, cyhal_gpio_event_t event, uint8_t intr_priority, bool enable); 273 274 /** Connects a source signal and enables an input to a pin that, when triggered, will set the pins output 275 * 276 * @param[in] pin GPIO object 277 * @param[in] source Source signal obtained from another driver's cyhal_<PERIPH>_enable_output 278 * @return The status of the connection 279 * */ 280 cy_rslt_t cyhal_gpio_connect_digital(cyhal_gpio_t pin, cyhal_source_t source); 281 282 /** Enables an output signal from a pin that is triggered by the pins input 283 * 284 * @param[in] pin GPIO object 285 * @param[in] type Whether the signal will act as a edge or level input 286 * @param[out] source Pointer to user-allocated source signal object which 287 * will be initialized by enable_output. \p source should be passed to 288 * (dis)connect_digital functions to (dis)connect the associated endpoints. 289 * @return The status of the output enable 290 * */ 291 cy_rslt_t cyhal_gpio_enable_output(cyhal_gpio_t pin, cyhal_signal_type_t type, cyhal_source_t *source); 292 293 /** Disconnects a source signal and disables an input to a pin 294 * 295 * @param[in] pin GPIO object 296 * @param[in] source Source signal from cyhal_<PERIPH>_enable_output to disable 297 * @return The status of the disconnection 298 * */ 299 cy_rslt_t cyhal_gpio_disconnect_digital(cyhal_gpio_t pin, cyhal_source_t source); 300 301 /** Disables an output signal from a pin 302 * 303 * @param[in] pin GPIO object 304 * @return The status of the output enable 305 * */ 306 cy_rslt_t cyhal_gpio_disable_output(cyhal_gpio_t pin); 307 308 #ifdef __cplusplus 309 } 310 #endif /* __cplusplus */ 311 312 #ifdef CYHAL_GPIO_IMPL_HEADER 313 #include CYHAL_GPIO_IMPL_HEADER 314 #endif /* CYHAL_GPIO_IMPL_HEADER */ 315 316 /** \} group_hal_gpio */ 317