1 /*
2 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <esp_types.h>
8 #include "esp_err.h"
9 #include "freertos/FreeRTOS.h"
10 #include "driver/gpio.h"
11 #include "driver/rtc_io.h"
12 #include "soc/soc.h"
13 #include "soc/periph_defs.h"
14 #if !CONFIG_FREERTOS_UNICORE
15 #include "esp_ipc.h"
16 #endif
17
18 #include "soc/soc_caps.h"
19 #include "soc/gpio_periph.h"
20 #include "esp_log.h"
21 #include "esp_check.h"
22 #include "hal/gpio_hal.h"
23 #include "esp_rom_gpio.h"
24
25 static const char *GPIO_TAG = "gpio";
26 #define GPIO_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, GPIO_TAG, "%s", str)
27
28 #define GPIO_ISR_CORE_ID_UNINIT (3)
29
30 //default value for SOC_GPIO_SUPPORT_RTC_INDEPENDENT is 0
31 #ifndef SOC_GPIO_SUPPORT_RTC_INDEPENDENT
32 #define SOC_GPIO_SUPPORT_RTC_INDEPENDENT 0
33 #endif
34
35 typedef struct {
36 gpio_isr_t fn; /*!< isr function */
37 void *args; /*!< isr function args */
38 } gpio_isr_func_t;
39
40 // Used by the IPC call to register the interrupt service routine.
41 typedef struct {
42 int source; /*!< ISR source */
43 int intr_alloc_flags; /*!< ISR alloc flag */
44 void (*fn)(void*); /*!< ISR function */
45 void *arg; /*!< ISR function args*/
46 void *handle; /*!< ISR handle */
47 esp_err_t ret;
48 } gpio_isr_alloc_t;
49
50 typedef struct {
51 gpio_hal_context_t *gpio_hal;
52 portMUX_TYPE gpio_spinlock;
53 uint32_t isr_core_id;
54 gpio_isr_func_t *gpio_isr_func;
55 gpio_isr_handle_t gpio_isr_handle;
56 } gpio_context_t;
57
58 static gpio_hal_context_t _gpio_hal = {
59 .dev = GPIO_HAL_GET_HW(GPIO_PORT_0)
60 };
61
62 static gpio_context_t gpio_context = {
63 .gpio_hal = &_gpio_hal,
64 .gpio_spinlock = portMUX_INITIALIZER_UNLOCKED,
65 .isr_core_id = GPIO_ISR_CORE_ID_UNINIT,
66 .gpio_isr_func = NULL,
67 };
68
gpio_pullup_en(gpio_num_t gpio_num)69 esp_err_t gpio_pullup_en(gpio_num_t gpio_num)
70 {
71 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
72
73 if (!rtc_gpio_is_valid_gpio(gpio_num) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
74 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
75 gpio_hal_pullup_en(gpio_context.gpio_hal, gpio_num);
76 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
77 } else {
78 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
79 rtc_gpio_pullup_en(gpio_num);
80 #else
81 abort(); // This should be eliminated as unreachable, unless a programming error has occured
82 #endif
83 }
84
85 return ESP_OK;
86 }
87
gpio_pullup_dis(gpio_num_t gpio_num)88 esp_err_t gpio_pullup_dis(gpio_num_t gpio_num)
89 {
90 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
91
92 if (!rtc_gpio_is_valid_gpio(gpio_num) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
93 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
94 gpio_hal_pullup_dis(gpio_context.gpio_hal, gpio_num);
95 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
96 } else {
97 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
98 rtc_gpio_pullup_dis(gpio_num);
99 #else
100 abort(); // This should be eliminated as unreachable, unless a programming error has occured
101 #endif
102 }
103
104 return ESP_OK;
105 }
106
gpio_pulldown_en(gpio_num_t gpio_num)107 esp_err_t gpio_pulldown_en(gpio_num_t gpio_num)
108 {
109 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
110
111 if (!rtc_gpio_is_valid_gpio(gpio_num) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
112 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
113 gpio_hal_pulldown_en(gpio_context.gpio_hal, gpio_num);
114 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
115 } else {
116 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
117 rtc_gpio_pulldown_en(gpio_num);
118 #else
119 abort(); // This should be eliminated as unreachable, unless a programming error has occured
120 #endif
121 }
122
123 return ESP_OK;
124 }
125
gpio_pulldown_dis(gpio_num_t gpio_num)126 esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num)
127 {
128 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
129
130 if (!rtc_gpio_is_valid_gpio(gpio_num) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
131 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
132 gpio_hal_pulldown_dis(gpio_context.gpio_hal, gpio_num);
133 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
134 } else {
135 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
136 rtc_gpio_pulldown_dis(gpio_num);
137 #else
138 abort(); // This should be eliminated as unreachable, unless a programming error has occured
139 #endif
140 }
141
142 return ESP_OK;
143 }
144
gpio_set_intr_type(gpio_num_t gpio_num,gpio_int_type_t intr_type)145 esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type)
146 {
147 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
148 GPIO_CHECK(intr_type < GPIO_INTR_MAX, "GPIO interrupt type error", ESP_ERR_INVALID_ARG);
149
150 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
151 gpio_hal_set_intr_type(gpio_context.gpio_hal, gpio_num, intr_type);
152 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
153 return ESP_OK;
154 }
155
gpio_intr_enable_on_core(gpio_num_t gpio_num,uint32_t core_id)156 static esp_err_t gpio_intr_enable_on_core(gpio_num_t gpio_num, uint32_t core_id)
157 {
158 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
159 gpio_hal_intr_enable_on_core(gpio_context.gpio_hal, gpio_num, core_id);
160 return ESP_OK;
161 }
162
gpio_intr_enable(gpio_num_t gpio_num)163 esp_err_t gpio_intr_enable(gpio_num_t gpio_num)
164 {
165 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
166 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
167 if(gpio_context.isr_core_id == GPIO_ISR_CORE_ID_UNINIT) {
168 gpio_context.isr_core_id = xPortGetCoreID();
169 }
170 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
171 return gpio_intr_enable_on_core (gpio_num, gpio_context.isr_core_id);
172 }
173
gpio_intr_disable(gpio_num_t gpio_num)174 esp_err_t gpio_intr_disable(gpio_num_t gpio_num)
175 {
176 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
177 gpio_hal_intr_disable(gpio_context.gpio_hal, gpio_num);
178 return ESP_OK;
179 }
180
gpio_input_disable(gpio_num_t gpio_num)181 static esp_err_t gpio_input_disable(gpio_num_t gpio_num)
182 {
183 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
184 gpio_hal_input_disable(gpio_context.gpio_hal, gpio_num);
185 return ESP_OK;
186 }
187
gpio_input_enable(gpio_num_t gpio_num)188 static esp_err_t gpio_input_enable(gpio_num_t gpio_num)
189 {
190 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
191 gpio_hal_input_enable(gpio_context.gpio_hal, gpio_num);
192 return ESP_OK;
193 }
194
gpio_output_disable(gpio_num_t gpio_num)195 static esp_err_t gpio_output_disable(gpio_num_t gpio_num)
196 {
197 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
198 gpio_hal_output_disable(gpio_context.gpio_hal, gpio_num);
199 return ESP_OK;
200 }
201
gpio_output_enable(gpio_num_t gpio_num)202 static esp_err_t gpio_output_enable(gpio_num_t gpio_num)
203 {
204 GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error", ESP_ERR_INVALID_ARG);
205 gpio_hal_output_enable(gpio_context.gpio_hal, gpio_num);
206 esp_rom_gpio_connect_out_signal(gpio_num, SIG_GPIO_OUT_IDX, false, false);
207 return ESP_OK;
208 }
209
gpio_od_disable(gpio_num_t gpio_num)210 static esp_err_t gpio_od_disable(gpio_num_t gpio_num)
211 {
212 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
213 gpio_hal_od_disable(gpio_context.gpio_hal, gpio_num);
214 return ESP_OK;
215 }
216
gpio_od_enable(gpio_num_t gpio_num)217 static esp_err_t gpio_od_enable(gpio_num_t gpio_num)
218 {
219 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
220 gpio_hal_od_enable(gpio_context.gpio_hal, gpio_num);
221 return ESP_OK;
222 }
223
gpio_set_level(gpio_num_t gpio_num,uint32_t level)224 esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level)
225 {
226 GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error", ESP_ERR_INVALID_ARG);
227 gpio_hal_set_level(gpio_context.gpio_hal, gpio_num, level);
228 return ESP_OK;
229 }
230
gpio_get_level(gpio_num_t gpio_num)231 int gpio_get_level(gpio_num_t gpio_num)
232 {
233 return gpio_hal_get_level(gpio_context.gpio_hal, gpio_num);
234 }
235
gpio_set_pull_mode(gpio_num_t gpio_num,gpio_pull_mode_t pull)236 esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull)
237 {
238 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
239 GPIO_CHECK(pull <= GPIO_FLOATING, "GPIO pull mode error", ESP_ERR_INVALID_ARG);
240 esp_err_t ret = ESP_OK;
241
242 switch (pull) {
243 case GPIO_PULLUP_ONLY:
244 gpio_pulldown_dis(gpio_num);
245 gpio_pullup_en(gpio_num);
246 break;
247
248 case GPIO_PULLDOWN_ONLY:
249 gpio_pulldown_en(gpio_num);
250 gpio_pullup_dis(gpio_num);
251 break;
252
253 case GPIO_PULLUP_PULLDOWN:
254 gpio_pulldown_en(gpio_num);
255 gpio_pullup_en(gpio_num);
256 break;
257
258 case GPIO_FLOATING:
259 gpio_pulldown_dis(gpio_num);
260 gpio_pullup_dis(gpio_num);
261 break;
262
263 default:
264 ESP_LOGE(GPIO_TAG, "Unknown pull up/down mode,gpio_num=%u,pull=%u", gpio_num, pull);
265 ret = ESP_ERR_INVALID_ARG;
266 break;
267 }
268
269 return ret;
270 }
271
gpio_set_direction(gpio_num_t gpio_num,gpio_mode_t mode)272 esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode)
273 {
274 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
275
276 if ((GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) != true) && (mode & GPIO_MODE_DEF_OUTPUT)) {
277 ESP_LOGE(GPIO_TAG, "io_num=%d can only be input", gpio_num);
278 return ESP_ERR_INVALID_ARG;
279 }
280
281 esp_err_t ret = ESP_OK;
282
283 if (mode & GPIO_MODE_DEF_INPUT) {
284 gpio_input_enable(gpio_num);
285 } else {
286 gpio_input_disable(gpio_num);
287 }
288
289 if (mode & GPIO_MODE_DEF_OUTPUT) {
290 gpio_output_enable(gpio_num);
291 } else {
292 gpio_output_disable(gpio_num);
293 }
294
295 if (mode & GPIO_MODE_DEF_OD) {
296 gpio_od_enable(gpio_num);
297 } else {
298 gpio_od_disable(gpio_num);
299 }
300
301 return ret;
302 }
303
gpio_config(const gpio_config_t * pGPIOConfig)304 esp_err_t gpio_config(const gpio_config_t *pGPIOConfig)
305 {
306 uint64_t gpio_pin_mask = (pGPIOConfig->pin_bit_mask);
307 uint32_t io_reg = 0;
308 uint32_t io_num = 0;
309 uint8_t input_en = 0;
310 uint8_t output_en = 0;
311 uint8_t od_en = 0;
312 uint8_t pu_en = 0;
313 uint8_t pd_en = 0;
314
315 if (pGPIOConfig->pin_bit_mask == 0 ||
316 pGPIOConfig->pin_bit_mask & ~SOC_GPIO_VALID_GPIO_MASK) {
317 ESP_LOGE(GPIO_TAG, "GPIO_PIN mask error ");
318 return ESP_ERR_INVALID_ARG;
319 }
320
321 if (pGPIOConfig->mode & GPIO_MODE_DEF_OUTPUT &&
322 pGPIOConfig->pin_bit_mask & ~SOC_GPIO_VALID_OUTPUT_GPIO_MASK) {
323 ESP_LOGE(GPIO_TAG, "GPIO can only be used as input mode");
324 return ESP_ERR_INVALID_ARG;
325 }
326
327 do {
328 io_reg = GPIO_PIN_MUX_REG[io_num];
329
330 if (((gpio_pin_mask >> io_num) & BIT(0))) {
331 assert(io_reg != (intptr_t)NULL);
332
333 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
334 if (rtc_gpio_is_valid_gpio(io_num)) {
335 rtc_gpio_deinit(io_num);
336 }
337 #endif
338
339 if ((pGPIOConfig->mode) & GPIO_MODE_DEF_INPUT) {
340 input_en = 1;
341 gpio_input_enable(io_num);
342 } else {
343 gpio_input_disable(io_num);
344 }
345
346 if ((pGPIOConfig->mode) & GPIO_MODE_DEF_OD) {
347 od_en = 1;
348 gpio_od_enable(io_num);
349 } else {
350 gpio_od_disable(io_num);
351 }
352
353 if ((pGPIOConfig->mode) & GPIO_MODE_DEF_OUTPUT) {
354 output_en = 1;
355 gpio_output_enable(io_num);
356 } else {
357 gpio_output_disable(io_num);
358 }
359
360 if (pGPIOConfig->pull_up_en) {
361 pu_en = 1;
362 gpio_pullup_en(io_num);
363 } else {
364 gpio_pullup_dis(io_num);
365 }
366
367 if (pGPIOConfig->pull_down_en) {
368 pd_en = 1;
369 gpio_pulldown_en(io_num);
370 } else {
371 gpio_pulldown_dis(io_num);
372 }
373
374 ESP_LOGI(GPIO_TAG, "GPIO[%d]| InputEn: %d| OutputEn: %d| OpenDrain: %d| Pullup: %d| Pulldown: %d| Intr:%d ", io_num, input_en, output_en, od_en, pu_en, pd_en, pGPIOConfig->intr_type);
375 gpio_set_intr_type(io_num, pGPIOConfig->intr_type);
376
377 if (pGPIOConfig->intr_type) {
378 gpio_intr_enable(io_num);
379 } else {
380 gpio_intr_disable(io_num);
381 }
382
383 /* By default, all the pins have to be configured as GPIO pins. */
384 gpio_hal_iomux_func_sel(io_reg, PIN_FUNC_GPIO);
385 }
386
387 io_num++;
388 } while (io_num < GPIO_PIN_COUNT);
389
390 return ESP_OK;
391 }
392
gpio_reset_pin(gpio_num_t gpio_num)393 esp_err_t gpio_reset_pin(gpio_num_t gpio_num)
394 {
395 assert(gpio_num >= 0 && GPIO_IS_VALID_GPIO(gpio_num));
396 gpio_config_t cfg = {
397 .pin_bit_mask = BIT64(gpio_num),
398 .mode = GPIO_MODE_DISABLE,
399 //for powersave reasons, the GPIO should not be floating, select pullup
400 .pull_up_en = true,
401 .pull_down_en = false,
402 .intr_type = GPIO_INTR_DISABLE,
403 };
404 gpio_config(&cfg);
405 return ESP_OK;
406 }
407
gpio_isr_loop(uint32_t status,const uint32_t gpio_num_start)408 static inline void IRAM_ATTR gpio_isr_loop(uint32_t status, const uint32_t gpio_num_start)
409 {
410 while (status) {
411 int nbit = __builtin_ffs(status) - 1;
412 status &= ~(1 << nbit);
413 int gpio_num = gpio_num_start + nbit;
414
415 if (gpio_context.gpio_isr_func[gpio_num].fn != NULL) {
416 gpio_context.gpio_isr_func[gpio_num].fn(gpio_context.gpio_isr_func[gpio_num].args);
417 }
418 }
419 }
420
gpio_intr_service(void * arg)421 static void IRAM_ATTR gpio_intr_service(void *arg)
422 {
423 //GPIO intr process
424 if (gpio_context.gpio_isr_func == NULL) {
425 return;
426 }
427
428 //read status to get interrupt status for GPIO0-31
429 uint32_t gpio_intr_status;
430 gpio_hal_get_intr_status(gpio_context.gpio_hal, gpio_context.isr_core_id, &gpio_intr_status);
431
432 if (gpio_intr_status) {
433 gpio_isr_loop(gpio_intr_status, 0);
434 gpio_hal_clear_intr_status(gpio_context.gpio_hal, gpio_intr_status);
435 }
436
437 //read status1 to get interrupt status for GPIO32-39
438 uint32_t gpio_intr_status_h;
439 gpio_hal_get_intr_status_high(gpio_context.gpio_hal, gpio_context.isr_core_id, &gpio_intr_status_h);
440
441 if (gpio_intr_status_h) {
442 gpio_isr_loop(gpio_intr_status_h, 32);
443 gpio_hal_clear_intr_status_high(gpio_context.gpio_hal, gpio_intr_status_h);
444 }
445 }
446
gpio_install_isr_service(int intr_alloc_flags)447 esp_err_t gpio_install_isr_service(int intr_alloc_flags)
448 {
449 GPIO_CHECK(gpio_context.gpio_isr_func == NULL, "GPIO isr service already installed", ESP_ERR_INVALID_STATE);
450 esp_err_t ret;
451 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
452 gpio_context.gpio_isr_func = (gpio_isr_func_t *) calloc(GPIO_NUM_MAX, sizeof(gpio_isr_func_t));
453 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
454 if (gpio_context.gpio_isr_func == NULL) {
455 ret = ESP_ERR_NO_MEM;
456 } else {
457 ret = gpio_isr_register(gpio_intr_service, NULL, intr_alloc_flags, &gpio_context.gpio_isr_handle);
458 }
459
460 return ret;
461 }
462
gpio_isr_handler_add(gpio_num_t gpio_num,gpio_isr_t isr_handler,void * args)463 esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void *args)
464 {
465 GPIO_CHECK(gpio_context.gpio_isr_func != NULL, "GPIO isr service is not installed, call gpio_install_isr_service() first", ESP_ERR_INVALID_STATE);
466 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
467 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
468 gpio_intr_disable(gpio_num);
469 if (gpio_context.gpio_isr_func) {
470 gpio_context.gpio_isr_func[gpio_num].fn = isr_handler;
471 gpio_context.gpio_isr_func[gpio_num].args = args;
472 }
473 gpio_intr_enable_on_core (gpio_num, esp_intr_get_cpu(gpio_context.gpio_isr_handle));
474 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
475 return ESP_OK;
476 }
477
gpio_isr_handler_remove(gpio_num_t gpio_num)478 esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num)
479 {
480 GPIO_CHECK(gpio_context.gpio_isr_func != NULL, "GPIO isr service is not installed, call gpio_install_isr_service() first", ESP_ERR_INVALID_STATE);
481 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
482 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
483 gpio_intr_disable(gpio_num);
484 if (gpio_context.gpio_isr_func) {
485 gpio_context.gpio_isr_func[gpio_num].fn = NULL;
486 gpio_context.gpio_isr_func[gpio_num].args = NULL;
487 }
488 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
489 return ESP_OK;
490 }
491
gpio_uninstall_isr_service(void)492 void gpio_uninstall_isr_service(void)
493 {
494 gpio_isr_func_t *gpio_isr_func_free = NULL;
495 gpio_isr_handle_t gpio_isr_handle_free = NULL;
496 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
497 if (gpio_context.gpio_isr_func == NULL) {
498 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
499 return;
500 }
501 gpio_isr_func_free = gpio_context.gpio_isr_func;
502 gpio_context.gpio_isr_func = NULL;
503 gpio_isr_handle_free = gpio_context.gpio_isr_handle;
504 gpio_context.gpio_isr_handle = NULL;
505 gpio_context.isr_core_id = GPIO_ISR_CORE_ID_UNINIT;
506 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
507 esp_intr_free(gpio_isr_handle_free);
508 free(gpio_isr_func_free);
509 return;
510 }
511
512
gpio_isr_register_on_core_static(void * param)513 static void gpio_isr_register_on_core_static(void *param)
514 {
515 gpio_isr_alloc_t *p = (gpio_isr_alloc_t *)param;
516 //We need to check the return value.
517 p->ret = esp_intr_alloc(p->source, p->intr_alloc_flags, p->fn, p->arg, p->handle);
518 }
519
gpio_isr_register(void (* fn)(void *),void * arg,int intr_alloc_flags,gpio_isr_handle_t * handle)520 esp_err_t gpio_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, gpio_isr_handle_t *handle)
521 {
522 GPIO_CHECK(fn, "GPIO ISR null", ESP_ERR_INVALID_ARG);
523 gpio_isr_alloc_t p;
524 p.source = ETS_GPIO_INTR_SOURCE;
525 p.intr_alloc_flags = intr_alloc_flags;
526 p.fn = fn;
527 p.arg = arg;
528 p.handle = handle;
529 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
530 if(gpio_context.isr_core_id == GPIO_ISR_CORE_ID_UNINIT) {
531 gpio_context.isr_core_id = xPortGetCoreID();
532 }
533 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
534 esp_err_t ret;
535 #if CONFIG_FREERTOS_UNICORE
536 gpio_isr_register_on_core_static(&p);
537 ret = ESP_OK;
538 #else /* CONFIG_FREERTOS_UNICORE */
539 ret = esp_ipc_call_blocking(gpio_context.isr_core_id, gpio_isr_register_on_core_static, (void *)&p);
540 #endif /* !CONFIG_FREERTOS_UNICORE */
541 if (ret != ESP_OK) {
542 ESP_LOGE(GPIO_TAG, "esp_ipc_call_blocking failed (0x%x)", ret);
543 return ESP_ERR_NOT_FOUND;
544 }
545 if (p.ret != ESP_OK) {
546 ESP_LOGE(GPIO_TAG, "esp_intr_alloc failed (0x%x)", p.ret);
547 return ESP_ERR_NOT_FOUND;
548 }
549 return ESP_OK;
550 }
551
gpio_wakeup_enable(gpio_num_t gpio_num,gpio_int_type_t intr_type)552 esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
553 {
554 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
555 esp_err_t ret = ESP_OK;
556
557 if ((intr_type == GPIO_INTR_LOW_LEVEL) || (intr_type == GPIO_INTR_HIGH_LEVEL)) {
558 #if SOC_RTCIO_WAKE_SUPPORTED
559 if (rtc_gpio_is_valid_gpio(gpio_num)) {
560 ret = rtc_gpio_wakeup_enable(gpio_num, intr_type);
561 }
562 #endif
563 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
564 gpio_hal_wakeup_enable(gpio_context.gpio_hal, gpio_num, intr_type);
565 #if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
566 gpio_hal_sleep_sel_dis(gpio_context.gpio_hal, gpio_num);
567 #endif
568 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
569 } else {
570 ESP_LOGE(GPIO_TAG, "GPIO wakeup only supports level mode, but edge mode set. gpio_num:%u", gpio_num);
571 ret = ESP_ERR_INVALID_ARG;
572 }
573
574 return ret;
575 }
576
gpio_wakeup_disable(gpio_num_t gpio_num)577 esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num)
578 {
579 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
580 esp_err_t ret = ESP_OK;
581 #if SOC_RTCIO_WAKE_SUPPORTED
582 if (rtc_gpio_is_valid_gpio(gpio_num)) {
583 ret = rtc_gpio_wakeup_disable(gpio_num);
584 }
585 #endif
586 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
587 gpio_hal_wakeup_disable(gpio_context.gpio_hal, gpio_num);
588 #if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
589 gpio_hal_sleep_sel_en(gpio_context.gpio_hal, gpio_num);
590 #endif
591 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
592 return ret;
593 }
594
gpio_set_drive_capability(gpio_num_t gpio_num,gpio_drive_cap_t strength)595 esp_err_t gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t strength)
596 {
597 GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
598 GPIO_CHECK(strength < GPIO_DRIVE_CAP_MAX, "GPIO drive capability error", ESP_ERR_INVALID_ARG);
599 esp_err_t ret = ESP_OK;
600
601 if (!rtc_gpio_is_valid_gpio(gpio_num) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
602 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
603 gpio_hal_set_drive_capability(gpio_context.gpio_hal, gpio_num, strength);
604 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
605 } else {
606 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
607 ret = rtc_gpio_set_drive_capability(gpio_num, strength);
608 #else
609 abort(); // This should be eliminated as unreachable, unless a programming error has occured
610 #endif
611 }
612
613 return ret;
614 }
615
gpio_get_drive_capability(gpio_num_t gpio_num,gpio_drive_cap_t * strength)616 esp_err_t gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *strength)
617 {
618 GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
619 GPIO_CHECK(strength != NULL, "GPIO drive capability pointer error", ESP_ERR_INVALID_ARG);
620 esp_err_t ret = ESP_OK;
621
622 if (!rtc_gpio_is_valid_gpio(gpio_num) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
623 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
624 gpio_hal_get_drive_capability(gpio_context.gpio_hal, gpio_num, strength);
625 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
626 } else {
627 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
628 ret = rtc_gpio_get_drive_capability(gpio_num, strength);
629 #else
630 abort(); // This should be eliminated as unreachable, unless a programming error has occured
631 #endif
632 }
633
634 return ret;
635 }
636
gpio_hold_en(gpio_num_t gpio_num)637 esp_err_t gpio_hold_en(gpio_num_t gpio_num)
638 {
639 GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "Only output-capable GPIO support this function", ESP_ERR_NOT_SUPPORTED);
640 int ret = ESP_OK;
641
642 if (rtc_gpio_is_valid_gpio(gpio_num)) {
643 #if SOC_RTCIO_HOLD_SUPPORTED
644 ret = rtc_gpio_hold_en(gpio_num);
645 #endif
646 } else if (GPIO_HOLD_MASK[gpio_num]) {
647 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
648 gpio_hal_hold_en(gpio_context.gpio_hal, gpio_num);
649 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
650 } else {
651 ret = ESP_ERR_NOT_SUPPORTED;
652 }
653
654 return ret;
655 }
656
gpio_hold_dis(gpio_num_t gpio_num)657 esp_err_t gpio_hold_dis(gpio_num_t gpio_num)
658 {
659 GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "Only output-capable GPIO support this function", ESP_ERR_NOT_SUPPORTED);
660 int ret = ESP_OK;
661
662 if (rtc_gpio_is_valid_gpio(gpio_num)) {
663 #if SOC_RTCIO_HOLD_SUPPORTED
664 ret = rtc_gpio_hold_dis(gpio_num);
665 #endif
666 }else if (GPIO_HOLD_MASK[gpio_num]) {
667 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
668 gpio_hal_hold_dis(gpio_context.gpio_hal, gpio_num);
669 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
670 } else {
671 ret = ESP_ERR_NOT_SUPPORTED;
672 }
673
674 return ret;
675 }
676
gpio_deep_sleep_hold_en(void)677 void gpio_deep_sleep_hold_en(void)
678 {
679 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
680 gpio_hal_deep_sleep_hold_en(gpio_context.gpio_hal);
681 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
682 }
683
gpio_deep_sleep_hold_dis(void)684 void gpio_deep_sleep_hold_dis(void)
685 {
686 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
687 gpio_hal_deep_sleep_hold_dis(gpio_context.gpio_hal);
688 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
689 }
690
691 #if SOC_GPIO_SUPPORT_FORCE_HOLD
692
gpio_force_hold_all()693 esp_err_t gpio_force_hold_all()
694 {
695 #if SOC_RTCIO_HOLD_SUPPORTED
696 rtc_gpio_force_hold_all();
697 #endif
698 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
699 gpio_hal_force_hold_all(gpio_context.gpio_hal);
700 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
701 return ESP_OK;
702 }
703
gpio_force_unhold_all()704 esp_err_t gpio_force_unhold_all()
705 {
706 #if SOC_RTCIO_HOLD_SUPPORTED
707 rtc_gpio_force_hold_dis_all();
708 #endif
709 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
710 gpio_hal_force_unhold_all();
711 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
712 return ESP_OK;
713 }
714 #endif
715
gpio_iomux_in(uint32_t gpio,uint32_t signal_idx)716 void gpio_iomux_in(uint32_t gpio, uint32_t signal_idx)
717 {
718 gpio_hal_iomux_in(gpio_context.gpio_hal, gpio, signal_idx);
719 }
720
gpio_iomux_out(uint8_t gpio_num,int func,bool oen_inv)721 void gpio_iomux_out(uint8_t gpio_num, int func, bool oen_inv)
722 {
723 gpio_hal_iomux_out(gpio_context.gpio_hal, gpio_num, func, (uint32_t)oen_inv);
724 }
725
726 #if SOC_GPIO_SUPPORT_SLP_SWITCH
gpio_sleep_pullup_en(gpio_num_t gpio_num)727 static esp_err_t gpio_sleep_pullup_en(gpio_num_t gpio_num)
728 {
729 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
730
731 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
732 gpio_hal_sleep_pullup_en(gpio_context.gpio_hal, gpio_num);
733 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
734
735 return ESP_OK;
736 }
737
gpio_sleep_pullup_dis(gpio_num_t gpio_num)738 static esp_err_t gpio_sleep_pullup_dis(gpio_num_t gpio_num)
739 {
740 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
741
742 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
743 gpio_hal_sleep_pullup_dis(gpio_context.gpio_hal, gpio_num);
744 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
745
746 return ESP_OK;
747 }
748
gpio_sleep_pulldown_en(gpio_num_t gpio_num)749 static esp_err_t gpio_sleep_pulldown_en(gpio_num_t gpio_num)
750 {
751 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
752
753 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
754 gpio_hal_sleep_pulldown_en(gpio_context.gpio_hal, gpio_num);
755 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
756
757 return ESP_OK;
758 }
759
gpio_sleep_pulldown_dis(gpio_num_t gpio_num)760 static esp_err_t gpio_sleep_pulldown_dis(gpio_num_t gpio_num)
761 {
762 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
763
764 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
765 gpio_hal_sleep_pulldown_dis(gpio_context.gpio_hal, gpio_num);
766 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
767
768 return ESP_OK;
769 }
770
gpio_sleep_input_disable(gpio_num_t gpio_num)771 static esp_err_t gpio_sleep_input_disable(gpio_num_t gpio_num)
772 {
773 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
774 gpio_hal_sleep_input_disable(gpio_context.gpio_hal, gpio_num);
775 return ESP_OK;
776 }
777
gpio_sleep_input_enable(gpio_num_t gpio_num)778 static esp_err_t gpio_sleep_input_enable(gpio_num_t gpio_num)
779 {
780 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
781 gpio_hal_sleep_input_enable(gpio_context.gpio_hal, gpio_num);
782 return ESP_OK;
783 }
784
gpio_sleep_output_disable(gpio_num_t gpio_num)785 static esp_err_t gpio_sleep_output_disable(gpio_num_t gpio_num)
786 {
787 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
788 gpio_hal_sleep_output_disable(gpio_context.gpio_hal, gpio_num);
789 return ESP_OK;
790 }
791
gpio_sleep_output_enable(gpio_num_t gpio_num)792 static esp_err_t gpio_sleep_output_enable(gpio_num_t gpio_num)
793 {
794 GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error", ESP_ERR_INVALID_ARG);
795 gpio_hal_sleep_output_enable(gpio_context.gpio_hal, gpio_num);
796 return ESP_OK;
797 }
798
gpio_sleep_set_direction(gpio_num_t gpio_num,gpio_mode_t mode)799 esp_err_t gpio_sleep_set_direction(gpio_num_t gpio_num, gpio_mode_t mode)
800 {
801 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
802
803 if ((GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) != true) && (mode & GPIO_MODE_DEF_OUTPUT)) {
804 ESP_LOGE(GPIO_TAG, "io_num=%d can only be input", gpio_num);
805 return ESP_ERR_INVALID_ARG;
806 }
807
808 esp_err_t ret = ESP_OK;
809
810 if (mode & GPIO_MODE_DEF_INPUT) {
811 gpio_sleep_input_enable(gpio_num);
812 } else {
813 gpio_sleep_input_disable(gpio_num);
814 }
815
816 if (mode & GPIO_MODE_DEF_OUTPUT) {
817 gpio_sleep_output_enable(gpio_num);
818 } else {
819 gpio_sleep_output_disable(gpio_num);
820 }
821
822 return ret;
823 }
824
gpio_sleep_set_pull_mode(gpio_num_t gpio_num,gpio_pull_mode_t pull)825 esp_err_t gpio_sleep_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull)
826 {
827 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
828 GPIO_CHECK(pull <= GPIO_FLOATING, "GPIO pull mode error", ESP_ERR_INVALID_ARG);
829 esp_err_t ret = ESP_OK;
830
831 switch (pull) {
832 case GPIO_PULLUP_ONLY:
833 gpio_sleep_pulldown_dis(gpio_num);
834 gpio_sleep_pullup_en(gpio_num);
835 break;
836
837 case GPIO_PULLDOWN_ONLY:
838 gpio_sleep_pulldown_en(gpio_num);
839 gpio_sleep_pullup_dis(gpio_num);
840 break;
841
842 case GPIO_PULLUP_PULLDOWN:
843 gpio_sleep_pulldown_en(gpio_num);
844 gpio_sleep_pullup_en(gpio_num);
845 break;
846
847 case GPIO_FLOATING:
848 gpio_sleep_pulldown_dis(gpio_num);
849 gpio_sleep_pullup_dis(gpio_num);
850 break;
851
852 default:
853 ESP_LOGE(GPIO_TAG, "Unknown pull up/down mode,gpio_num=%u,pull=%u", gpio_num, pull);
854 ret = ESP_ERR_INVALID_ARG;
855 break;
856 }
857
858 return ret;
859 }
860
gpio_sleep_sel_en(gpio_num_t gpio_num)861 esp_err_t gpio_sleep_sel_en(gpio_num_t gpio_num)
862 {
863 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
864
865 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
866 gpio_hal_sleep_sel_en(gpio_context.gpio_hal, gpio_num);
867 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
868
869 return ESP_OK;
870 }
871
gpio_sleep_sel_dis(gpio_num_t gpio_num)872 esp_err_t gpio_sleep_sel_dis(gpio_num_t gpio_num)
873 {
874 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
875
876 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
877 gpio_hal_sleep_sel_dis(gpio_context.gpio_hal, gpio_num);
878 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
879
880 return ESP_OK;
881 }
882
883 #if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
gpio_sleep_pupd_config_apply(gpio_num_t gpio_num)884 esp_err_t gpio_sleep_pupd_config_apply(gpio_num_t gpio_num)
885 {
886 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
887 gpio_hal_sleep_pupd_config_apply(gpio_context.gpio_hal, gpio_num);
888 return ESP_OK;
889 }
890
gpio_sleep_pupd_config_unapply(gpio_num_t gpio_num)891 esp_err_t gpio_sleep_pupd_config_unapply(gpio_num_t gpio_num)
892 {
893 GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
894 gpio_hal_sleep_pupd_config_unapply(gpio_context.gpio_hal, gpio_num);
895 return ESP_OK;
896 }
897 #endif // CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
898 #endif // SOC_GPIO_SUPPORT_SLP_SWITCH
899
900 #if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
gpio_deep_sleep_wakeup_enable(gpio_num_t gpio_num,gpio_int_type_t intr_type)901 esp_err_t gpio_deep_sleep_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
902 {
903 if (!gpio_hal_is_valid_deepsleep_wakeup_gpio(gpio_num)) {
904 ESP_LOGE(GPIO_TAG, "GPIO %d does not support deep sleep wakeup", gpio_num);
905 return ESP_ERR_INVALID_ARG;
906 }
907 if ((intr_type != GPIO_INTR_LOW_LEVEL) && (intr_type != GPIO_INTR_HIGH_LEVEL)) {
908 ESP_LOGE(GPIO_TAG, "GPIO wakeup only supports level mode, but edge mode set. gpio_num:%u", gpio_num);
909 return ESP_ERR_INVALID_ARG;
910 }
911 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
912 gpio_hal_deepsleep_wakeup_enable(gpio_context.gpio_hal, gpio_num, intr_type);
913 #if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
914 gpio_hal_sleep_sel_dis(gpio_context.gpio_hal, gpio_num);
915 #endif
916 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
917 return ESP_OK;
918 }
919
gpio_deep_sleep_wakeup_disable(gpio_num_t gpio_num)920 esp_err_t gpio_deep_sleep_wakeup_disable(gpio_num_t gpio_num)
921 {
922 if (!gpio_hal_is_valid_deepsleep_wakeup_gpio(gpio_num)) {
923 ESP_LOGE(GPIO_TAG, "GPIO %d does not support deep sleep wakeup", gpio_num);
924 return ESP_ERR_INVALID_ARG;
925 }
926 portENTER_CRITICAL(&gpio_context.gpio_spinlock);
927 gpio_hal_deepsleep_wakeup_disable(gpio_context.gpio_hal, gpio_num);
928 #if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
929 gpio_hal_sleep_sel_en(gpio_context.gpio_hal, gpio_num);
930 #endif
931 portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
932 return ESP_OK;
933 }
934 #endif // SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
935