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