1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #include <stdbool.h>
10 #include "sdkconfig.h"
11 #include "esp_err.h"
12 #include "esp_intr_alloc.h"
13 #include "soc/soc_caps.h"
14 #include "hal/gpio_types.h"
15 #include "esp_rom_gpio.h"
16 #include "driver/gpio_etm.h"
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 #define GPIO_PIN_COUNT                      (SOC_GPIO_PIN_COUNT)
23 /// Check whether it is a valid GPIO number
24 #define GPIO_IS_VALID_GPIO(gpio_num)        ((gpio_num >= 0) && \
25                                               (((1ULL << (gpio_num)) & SOC_GPIO_VALID_GPIO_MASK) != 0))
26 /// Check whether it can be a valid GPIO number of output mode
27 #define GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) ((gpio_num >= 0) && \
28                                               (((1ULL << (gpio_num)) & SOC_GPIO_VALID_OUTPUT_GPIO_MASK) != 0))
29 /// Check whether it can be a valid digital I/O pad
30 #define GPIO_IS_VALID_DIGITAL_IO_PAD(gpio_num) ((gpio_num >= 0) && \
31                                                  (((1ULL << (gpio_num)) & SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK) != 0))
32 
33 typedef intr_handle_t gpio_isr_handle_t;
34 
35 /**
36  * @brief GPIO interrupt handler
37  *
38  * @param arg User registered data
39  */
40 typedef void (*gpio_isr_t)(void *arg);
41 
42 /**
43  * @brief Configuration parameters of GPIO pad for gpio_config function
44  */
45 typedef struct {
46     uint64_t pin_bit_mask;          /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
47     gpio_mode_t mode;               /*!< GPIO mode: set input/output mode                     */
48     gpio_pullup_t pull_up_en;       /*!< GPIO pull-up                                         */
49     gpio_pulldown_t pull_down_en;   /*!< GPIO pull-down                                       */
50     gpio_int_type_t intr_type;      /*!< GPIO interrupt type                                  */
51 #if SOC_GPIO_SUPPORT_PIN_HYS_FILTER
52     gpio_hys_ctrl_mode_t hys_ctrl_mode;       /*!< GPIO hysteresis: hysteresis filter on slope input    */
53 #endif
54 } gpio_config_t;
55 
56 /**
57  * @brief GPIO common configuration
58  *
59  *        Configure GPIO's Mode,pull-up,PullDown,IntrType
60  *
61  * @param  pGPIOConfig Pointer to GPIO configure struct
62  *
63  * @return
64  *     - ESP_OK success
65  *     - ESP_ERR_INVALID_ARG Parameter error
66  *
67  */
68 esp_err_t gpio_config(const gpio_config_t *pGPIOConfig);
69 
70 /**
71  * @brief Reset an gpio to default state (select gpio function, enable pullup and disable input and output).
72  *
73  * @param gpio_num GPIO number.
74  *
75  * @note This function also configures the IOMUX for this pin to the GPIO
76  *       function, and disconnects any other peripheral output configured via GPIO
77  *       Matrix.
78  *
79  * @return Always return ESP_OK.
80  */
81 esp_err_t gpio_reset_pin(gpio_num_t gpio_num);
82 
83 /**
84  * @brief  GPIO set interrupt trigger type
85  *
86  * @param  gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_16 (16);
87  * @param  intr_type Interrupt type, select from gpio_int_type_t
88  *
89  * @return
90  *     - ESP_OK  Success
91  *     - ESP_ERR_INVALID_ARG Parameter error
92  *
93  */
94 esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type);
95 
96 /**
97  * @brief  Enable GPIO module interrupt signal
98  *
99  * @note ESP32: Please do not use the interrupt of GPIO36 and GPIO39 when using ADC or Wi-Fi and Bluetooth with sleep mode enabled.
100  *       Please refer to the comments of `adc1_get_raw`.
101  *       Please refer to Section 3.11 of <a href="https://espressif.com/sites/default/files/documentation/eco_and_workarounds_for_bugs_in_esp32_en.pdf">ESP32 ECO and Workarounds for Bugs</a> for the description of this issue.
102 
103  *
104  * @param  gpio_num GPIO number. If you want to enable an interrupt on e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
105  *
106  * @return
107  *     - ESP_OK Success
108  *     - ESP_ERR_INVALID_ARG Parameter error
109  *
110  */
111 esp_err_t gpio_intr_enable(gpio_num_t gpio_num);
112 
113 /**
114  * @brief  Disable GPIO module interrupt signal
115  *
116  * @note This function is allowed to be executed when Cache is disabled within ISR context, by enabling `CONFIG_GPIO_CTRL_FUNC_IN_IRAM`
117  *
118  * @param  gpio_num GPIO number. If you want to disable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
119  *
120  * @return
121  *     - ESP_OK success
122  *     - ESP_ERR_INVALID_ARG Parameter error
123  *
124  */
125 esp_err_t gpio_intr_disable(gpio_num_t gpio_num);
126 
127 /**
128  * @brief  GPIO set output level
129  *
130  * @note This function is allowed to be executed when Cache is disabled within ISR context, by enabling `CONFIG_GPIO_CTRL_FUNC_IN_IRAM`
131  *
132  * @param  gpio_num GPIO number. If you want to set the output level of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
133  * @param  level Output level. 0: low ; 1: high
134  *
135  * @return
136  *     - ESP_OK Success
137  *     - ESP_ERR_INVALID_ARG GPIO number error
138  *
139  */
140 esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level);
141 
142 /**
143  * @brief  GPIO get input level
144  *
145  * @warning If the pad is not configured for input (or input and output) the returned value is always 0.
146  *
147  * @param  gpio_num GPIO number. If you want to get the logic level of e.g. pin GPIO16, gpio_num should be GPIO_NUM_16 (16);
148  *
149  * @return
150  *     - 0 the GPIO input level is 0
151  *     - 1 the GPIO input level is 1
152  *
153  */
154 int gpio_get_level(gpio_num_t gpio_num);
155 
156 /**
157  * @brief    GPIO set direction
158  *
159  * Configure GPIO direction,such as output_only,input_only,output_and_input
160  *
161  * @param  gpio_num  Configure GPIO pins number, it should be GPIO number. If you want to set direction of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
162  * @param  mode GPIO direction
163  *
164  * @return
165  *     - ESP_OK Success
166  *     - ESP_ERR_INVALID_ARG GPIO error
167  *
168  */
169 esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
170 
171 /**
172  * @brief  Configure GPIO pull-up/pull-down resistors
173  *
174  * @note ESP32: Only pins that support both input & output have integrated pull-up and pull-down resistors. Input-only GPIOs 34-39 do not.
175  *
176  * @param  gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
177  * @param  pull GPIO pull up/down mode.
178  *
179  * @return
180  *     - ESP_OK Success
181  *     - ESP_ERR_INVALID_ARG : Parameter error
182  *
183  */
184 esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
185 
186 /**
187  * @brief Enable GPIO wake-up function.
188  *
189  * @param gpio_num GPIO number.
190  *
191  * @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
192  *
193  * @return
194  *     - ESP_OK Success
195  *     - ESP_ERR_INVALID_ARG Parameter error
196  */
197 esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type);
198 esp_err_t esp_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type);
199 
200 /**
201  * @brief Disable GPIO wake-up function.
202  *
203  * @param gpio_num GPIO number
204  *
205  * @return
206  *     - ESP_OK Success
207  *     - ESP_ERR_INVALID_ARG Parameter error
208  */
209 esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num);
210 
211 /**
212  * @brief   Register GPIO interrupt handler, the handler is an ISR.
213  *          The handler will be attached to the same CPU core that this function is running on.
214  *
215  * This ISR function is called whenever any GPIO interrupt occurs. See
216  * the alternative gpio_install_isr_service() and
217  * gpio_isr_handler_add() API in order to have the driver support
218  * per-GPIO ISRs.
219  *
220  * @param  fn  Interrupt handler function.
221  * @param  arg  Parameter for handler function
222  * @param  intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
223  *            ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
224  * @param  handle Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.
225  *
226  * \verbatim embed:rst:leading-asterisk
227  * To disable or remove the ISR, pass the returned handle to the :doc:`interrupt allocation functions </api-reference/system/intr_alloc>`.
228  * \endverbatim
229  *
230  * @return
231  *     - ESP_OK Success ;
232  *     - ESP_ERR_INVALID_ARG GPIO error
233  *     - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
234  */
235 esp_err_t gpio_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, gpio_isr_handle_t *handle);
236 
237 /**
238   * @brief Enable pull-up on GPIO.
239   *
240   * @param gpio_num GPIO number
241   *
242   * @return
243   *     - ESP_OK Success
244   *     - ESP_ERR_INVALID_ARG Parameter error
245   */
246 esp_err_t gpio_pullup_en(gpio_num_t gpio_num);
247 
248 /**
249   * @brief Disable pull-up on GPIO.
250   *
251   * @param gpio_num GPIO number
252   *
253   * @return
254   *     - ESP_OK Success
255   *     - ESP_ERR_INVALID_ARG Parameter error
256   */
257 esp_err_t gpio_pullup_dis(gpio_num_t gpio_num);
258 
259 /**
260   * @brief Enable pull-down on GPIO.
261   *
262   * @param gpio_num GPIO number
263   *
264   * @return
265   *     - ESP_OK Success
266   *     - ESP_ERR_INVALID_ARG Parameter error
267   */
268 esp_err_t gpio_pulldown_en(gpio_num_t gpio_num);
269 
270 /**
271   * @brief Disable pull-down on GPIO.
272   *
273   * @param gpio_num GPIO number
274   *
275   * @return
276   *     - ESP_OK Success
277   *     - ESP_ERR_INVALID_ARG Parameter error
278   */
279 esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
280 
281 /**
282   * @brief Install the GPIO driver's ETS_GPIO_INTR_SOURCE ISR handler service, which allows per-pin GPIO interrupt handlers.
283   *
284   * This function is incompatible with gpio_isr_register() - if that function is used, a single global ISR is registered for all GPIO interrupts. If this function is used, the ISR service provides a global GPIO ISR and individual pin handlers are registered via the gpio_isr_handler_add() function.
285   *
286   * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
287   *            ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
288   *
289   * @return
290   *     - ESP_OK Success
291   *     - ESP_ERR_NO_MEM No memory to install this service
292   *     - ESP_ERR_INVALID_STATE ISR service already installed.
293   *     - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
294   *     - ESP_ERR_INVALID_ARG GPIO error
295   */
296 esp_err_t gpio_install_isr_service(int intr_alloc_flags);
297 
298 /**
299   * @brief Uninstall the driver's GPIO ISR service, freeing related resources.
300   */
301 void gpio_uninstall_isr_service(void);
302 
303 /**
304   * @brief Add ISR handler for the corresponding GPIO pin.
305   *
306   * Call this function after using gpio_install_isr_service() to
307   * install the driver's GPIO ISR handler service.
308   *
309   * The pin ISR handlers no longer need to be declared with IRAM_ATTR,
310   * unless you pass the ESP_INTR_FLAG_IRAM flag when allocating the
311   * ISR in gpio_install_isr_service().
312   *
313   * This ISR handler will be called from an ISR. So there is a stack
314   * size limit (configurable as "ISR stack size" in menuconfig). This
315   * limit is smaller compared to a global GPIO interrupt handler due
316   * to the additional level of indirection.
317   *
318   * @param gpio_num GPIO number
319   * @param isr_handler ISR handler function for the corresponding GPIO number.
320   * @param args parameter for ISR handler.
321   *
322   * @return
323   *     - ESP_OK Success
324   *     - ESP_ERR_INVALID_STATE Wrong state, the ISR service has not been initialized.
325   *     - ESP_ERR_INVALID_ARG Parameter error
326   */
327 esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void *args);
328 
329 /**
330   * @brief Remove ISR handler for the corresponding GPIO pin.
331   *
332   * @param gpio_num GPIO number
333   *
334   * @return
335   *     - ESP_OK Success
336   *     - ESP_ERR_INVALID_STATE Wrong state, the ISR service has not been initialized.
337   *     - ESP_ERR_INVALID_ARG Parameter error
338   */
339 esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num);
340 
341 /**
342   * @brief Set GPIO pad drive capability
343   *
344   * @param gpio_num GPIO number, only support output GPIOs
345   * @param strength Drive capability of the pad
346   *
347   * @return
348   *     - ESP_OK Success
349   *     - ESP_ERR_INVALID_ARG Parameter error
350   */
351 esp_err_t gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t strength);
352 
353 /**
354   * @brief Get GPIO pad drive capability
355   *
356   * @param gpio_num GPIO number, only support output GPIOs
357   * @param strength Pointer to accept drive capability of the pad
358   *
359   * @return
360   *     - ESP_OK Success
361   *     - ESP_ERR_INVALID_ARG Parameter error
362   */
363 esp_err_t gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *strength);
364 
365 /**
366   * @brief Enable gpio pad hold function.
367   *
368   * When a GPIO is set to hold, its state is latched at that moment and will not change when the internal
369   * signal or the IO MUX/GPIO configuration is modified (including input enable, output enable, output value,
370   * function, and drive strength values). This function can be used to retain the state of GPIOs when the chip
371   * or system is reset, for example, when watchdog time-out or Deep-sleep events are triggered.
372   *
373   * This function works in both input and output modes, and only applicable to output-capable GPIOs.
374   * If this function is enabled:
375   *   in output mode: the output level of the GPIO will be locked and can not be changed.
376   *   in input mode: the input read value can still reflect the changes of the input signal.
377   *
378   * However, on ESP32/S2/C3/S3/C2, this function cannot be used to hold the state of a digital GPIO during Deep-sleep.
379   * Even if this function is enabled, the digital GPIO will be reset to its default state when the chip wakes up from
380   * Deep-sleep. If you want to hold the state of a digital GPIO during Deep-sleep, please call `gpio_deep_sleep_hold_en`.
381   *
382   * Power down or call `gpio_hold_dis` will disable this function.
383   *
384   * @param gpio_num GPIO number, only support output-capable GPIOs
385   *
386   * @return
387   *     - ESP_OK Success
388   *     - ESP_ERR_NOT_SUPPORTED Not support pad hold function
389   */
390 esp_err_t gpio_hold_en(gpio_num_t gpio_num);
391 
392 /**
393   * @brief Disable gpio pad hold function.
394   *
395   * When the chip is woken up from Deep-sleep, the gpio will be set to the default mode, so, the gpio will output
396   * the default level if this function is called. If you don't want the level changes, the gpio should be configured to
397   * a known state before this function is called.
398   *  e.g.
399   *     If you hold gpio18 high during Deep-sleep, after the chip is woken up and `gpio_hold_dis` is called,
400   *     gpio18 will output low level(because gpio18 is input mode by default). If you don't want this behavior,
401   *     you should configure gpio18 as output mode and set it to hight level before calling `gpio_hold_dis`.
402   *
403   * @param gpio_num GPIO number, only support output-capable GPIOs
404   *
405   * @return
406   *     - ESP_OK Success
407   *     - ESP_ERR_NOT_SUPPORTED Not support pad hold function
408   */
409 esp_err_t gpio_hold_dis(gpio_num_t gpio_num);
410 
411 #if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
412 /**
413   * @brief Enable all digital gpio pads hold function during Deep-sleep.
414   *
415   * Enabling this feature makes all digital gpio pads be at the holding state during Deep-sleep. The state of each pad
416   * holds is its active configuration (not pad's sleep configuration!).
417   *
418   * Note that this pad hold feature only works when the chip is in Deep-sleep mode. When the chip is in active mode,
419   * the digital gpio state can be changed freely even you have called this function.
420   *
421   * After this API is being called, the digital gpio Deep-sleep hold feature will work during every sleep process. You
422   * should call `gpio_deep_sleep_hold_dis` to disable this feature.
423   */
424 void gpio_deep_sleep_hold_en(void);
425 
426 /**
427   * @brief Disable all digital gpio pads hold function during Deep-sleep.
428   */
429 void gpio_deep_sleep_hold_dis(void);
430 #endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
431 
432 /**
433   * @brief Set pad input to a peripheral signal through the IOMUX.
434   * @param gpio_num GPIO number of the pad.
435   * @param signal_idx Peripheral signal id to input. One of the ``*_IN_IDX`` signals in ``soc/gpio_sig_map.h``.
436   */
437 void gpio_iomux_in(uint32_t gpio_num, uint32_t signal_idx);
438 
439 /**
440   * @brief Set peripheral output to an GPIO pad through the IOMUX.
441   * @param gpio_num gpio_num GPIO number of the pad.
442   * @param func The function number of the peripheral pin to output pin.
443   *        One of the ``FUNC_X_*`` of specified pin (X) in ``soc/io_mux_reg.h``.
444   * @param oen_inv True if the output enable needs to be inverted, otherwise False.
445   */
446 void gpio_iomux_out(uint8_t gpio_num, int func, bool oen_inv);
447 
448 #if SOC_GPIO_SUPPORT_FORCE_HOLD
449 /**
450   * @brief Force hold all digital and rtc gpio pads.
451   *
452   * GPIO force hold, no matter the chip in active mode or sleep modes.
453   *
454   * This function will immediately cause all pads to latch the current values of input enable, output enable,
455   * output value, function, and drive strength values.
456   *
457   * @warning This function will hold flash and UART pins as well. Therefore, this function, and all code run afterwards
458   * (till calling `gpio_force_unhold_all` to disable this feature), MUST be placed in internal RAM as holding the flash
459   * pins will halt SPI flash operation, and holding the UART pins will halt any UART logging.
460   * */
461 esp_err_t gpio_force_hold_all(void);
462 
463 /**
464   * @brief Force unhold all digital and rtc gpio pads.
465   * */
466 esp_err_t gpio_force_unhold_all(void);
467 #endif
468 
469 /**
470   * @brief Enable SLP_SEL to change GPIO status automantically in lightsleep.
471   * @param gpio_num GPIO number of the pad.
472   *
473   * @return
474   *     - ESP_OK Success
475   *
476   */
477 esp_err_t gpio_sleep_sel_en(gpio_num_t gpio_num);
478 
479 /**
480   * @brief Disable SLP_SEL to change GPIO status automantically in lightsleep.
481   * @param gpio_num GPIO number of the pad.
482   *
483   * @return
484   *     - ESP_OK Success
485   */
486 esp_err_t gpio_sleep_sel_dis(gpio_num_t gpio_num);
487 
488 /**
489  * @brief    GPIO set direction at sleep
490  *
491  * Configure GPIO direction,such as output_only,input_only,output_and_input
492  *
493  * @param  gpio_num  Configure GPIO pins number, it should be GPIO number. If you want to set direction of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
494  * @param  mode GPIO direction
495  *
496  * @return
497  *     - ESP_OK Success
498  *     - ESP_ERR_INVALID_ARG GPIO error
499  */
500 esp_err_t gpio_sleep_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
501 
502 /**
503  * @brief  Configure GPIO pull-up/pull-down resistors at sleep
504  *
505  * @note ESP32: Only pins that support both input & output have integrated pull-up and pull-down resistors. Input-only GPIOs 34-39 do not.
506  *
507  * @param  gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
508  * @param  pull GPIO pull up/down mode.
509  *
510  * @return
511  *     - ESP_OK Success
512  *     - ESP_ERR_INVALID_ARG : Parameter error
513  */
514 esp_err_t gpio_sleep_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
515 
516 #if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
517 
518 #define GPIO_IS_DEEP_SLEEP_WAKEUP_VALID_GPIO(gpio_num)    ((gpio_num >= 0) && \
519                                                           (((1ULL << (gpio_num)) & SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK) != 0))
520 
521 /**
522  * @brief Enable GPIO deep-sleep wake-up function.
523  *
524  * @param gpio_num GPIO number.
525  *
526  * @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
527  *
528  * @note Called by the SDK. User shouldn't call this directly in the APP.
529  *
530  * @return
531  *     - ESP_OK Success
532  *     - ESP_ERR_INVALID_ARG Parameter error
533  */
534 esp_err_t gpio_deep_sleep_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type);
535 
536 /**
537  * @brief Disable GPIO deep-sleep wake-up function.
538  *
539  * @param gpio_num GPIO number
540  *
541  * @return
542  *     - ESP_OK Success
543  *     - ESP_ERR_INVALID_ARG Parameter error
544  */
545 esp_err_t gpio_deep_sleep_wakeup_disable(gpio_num_t gpio_num);
546 
547 #endif
548 
549 #ifdef __cplusplus
550 }
551 #endif
552