1 /*
2 * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*******************************************************************************
8 * NOTICE
9 * The hal is not public api, don't use in application code.
10 * See readme.md in hal/include/hal/readme.md
11 ******************************************************************************/
12
13 // The LL layer for ESP32 GPIO register operations
14
15 #pragma once
16
17 #include <stdbool.h>
18 #include "soc/soc.h"
19 #include "soc/gpio_periph.h"
20 #include "soc/gpio_struct.h"
21 #include "soc/rtc_cntl_reg.h"
22 #include "soc/rtc_io_reg.h"
23 #include "hal/gpio_types.h"
24 #include "hal/misc.h"
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29
30 // the address of esp32's IO_MUX_GPIOx_REGs are not incremented as the gpio number increments(address are out of order)
31 extern const uint8_t GPIO_PIN_MUX_REG_OFFSET[SOC_GPIO_PIN_COUNT];
32
33 // Get GPIO hardware instance with giving gpio num
34 #define GPIO_LL_GET_HW(num) (((num) == 0) ? (&GPIO) : NULL)
35
36 #define GPIO_LL_APP_CPU_INTR_ENA (BIT(0))
37 #define GPIO_LL_APP_CPU_NMI_INTR_ENA (BIT(1))
38 #define GPIO_LL_PRO_CPU_INTR_ENA (BIT(2))
39 #define GPIO_LL_PRO_CPU_NMI_INTR_ENA (BIT(3))
40 #define GPIO_LL_SDIO_EXT_INTR_ENA (BIT(4))
41
42 /**
43 * @brief Get the configuration for an IO
44 *
45 * @param hw Peripheral GPIO hardware instance address.
46 * @param gpio_num GPIO number
47 * @param pu Pull-up enabled or not
48 * @param pd Pull-down enabled or not
49 * @param ie Input enabled or not
50 * @param oe Output enabled or not
51 * @param od Open-drain enabled or not
52 * @param drv Drive strength value
53 * @param fun_sel IOMUX function selection value
54 * @param sig_out Outputting peripheral signal index
55 * @param slp_sel Pin sleep mode enabled or not
56 */
gpio_ll_get_io_config(gpio_dev_t * hw,uint32_t gpio_num,bool * pu,bool * pd,bool * ie,bool * oe,bool * od,uint32_t * drv,uint32_t * fun_sel,uint32_t * sig_out,bool * slp_sel)57 static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num,
58 bool *pu, bool *pd, bool *ie, bool *oe, bool *od, uint32_t *drv,
59 uint32_t *fun_sel, uint32_t *sig_out, bool *slp_sel)
60 {
61 uint32_t bit_shift = (gpio_num < 32) ? gpio_num : (gpio_num - 32);
62 uint32_t bit_mask = 1 << bit_shift;
63 uint32_t iomux_reg_val = REG_READ(GPIO_PIN_MUX_REG[gpio_num]);
64 *pu = (iomux_reg_val & FUN_PU_M) >> FUN_PU_S;
65 *pd = (iomux_reg_val & FUN_PD_M) >> FUN_PD_S;
66 *ie = (iomux_reg_val & FUN_IE_M) >> FUN_IE_S;
67 *oe = (((gpio_num < 32) ? hw->enable : hw->enable1.val) & bit_mask) >> bit_shift;
68 *od = hw->pin[gpio_num].pad_driver;
69 *drv = (iomux_reg_val & FUN_DRV_M) >> FUN_DRV_S;
70 *fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
71 *sig_out = hw->func_out_sel_cfg[gpio_num].func_sel;
72 *slp_sel = (iomux_reg_val & SLP_SEL_M) >> SLP_SEL_S;
73 }
74
75 /**
76 * @brief Enable pull-up on GPIO.
77 *
78 * @param hw Peripheral GPIO hardware instance address.
79 * @param gpio_num GPIO number
80 */
gpio_ll_pullup_en(gpio_dev_t * hw,uint32_t gpio_num)81 static inline void gpio_ll_pullup_en(gpio_dev_t *hw, uint32_t gpio_num)
82 {
83 REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
84 }
85
86 /**
87 * @brief Disable pull-up on GPIO.
88 *
89 * @param hw Peripheral GPIO hardware instance address.
90 * @param gpio_num GPIO number
91 */
92 __attribute__((always_inline))
gpio_ll_pullup_dis(gpio_dev_t * hw,uint32_t gpio_num)93 static inline void gpio_ll_pullup_dis(gpio_dev_t *hw, uint32_t gpio_num)
94 {
95 REG_CLR_BIT(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num], FUN_PU);
96 }
97
98 /**
99 * @brief Return pull-up status on GPIO.
100 *
101 * @param hw Peripheral GPIO hardware instance address.
102 * @param gpio_num GPIO number
103 * @return if GPIO gpio_num`s FUN_PU is true
104 */
gpio_ll_pullup_is_enabled(gpio_dev_t * hw,uint32_t gpio_num)105 static inline bool gpio_ll_pullup_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
106 {
107 return REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU) ? true : false;
108 }
109
110 /**
111 * @brief Enable pull-down on GPIO.
112 *
113 * @param hw Peripheral GPIO hardware instance address.
114 * @param gpio_num GPIO number
115 */
gpio_ll_pulldown_en(gpio_dev_t * hw,uint32_t gpio_num)116 static inline void gpio_ll_pulldown_en(gpio_dev_t *hw, uint32_t gpio_num)
117 {
118 REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
119 }
120
121 /**
122 * @brief Disable pull-down on GPIO.
123 *
124 * @param hw Peripheral GPIO hardware instance address.
125 * @param gpio_num GPIO number
126 */
127 __attribute__((always_inline))
gpio_ll_pulldown_dis(gpio_dev_t * hw,uint32_t gpio_num)128 static inline void gpio_ll_pulldown_dis(gpio_dev_t *hw, uint32_t gpio_num)
129 {
130 REG_CLR_BIT(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num], FUN_PD);
131 }
132
133 /**
134 * @brief Return pull-down status on GPIO.
135 *
136 * @param hw Peripheral GPIO hardware instance address.
137 * @param gpio_num GPIO number
138 * @return if GPIO gpio_num`s FUN_PD is true
139 */
gpio_ll_pulldown_is_enabled(gpio_dev_t * hw,uint32_t gpio_num)140 static inline bool gpio_ll_pulldown_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
141 {
142 return REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD) ? true : false;
143 }
144
145 /**
146 * @brief Enable GPIO pin used for wakeup from sleep.
147 *
148 * @param hw Peripheral GPIO hardware instance address.
149 * @param gpio_num GPIO number
150 */
gpio_ll_sleep_sel_en(gpio_dev_t * hw,uint32_t gpio_num)151 static inline void gpio_ll_sleep_sel_en(gpio_dev_t *hw, uint32_t gpio_num)
152 {
153 PIN_SLP_SEL_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
154 }
155
156 /**
157 * @brief Disable GPIO pin used for wakeup from sleep.
158 *
159 * @param hw Peripheral GPIO hardware instance address.
160 * @param gpio_num GPIO number
161 */
gpio_ll_sleep_sel_dis(gpio_dev_t * hw,uint32_t gpio_num)162 static inline void gpio_ll_sleep_sel_dis(gpio_dev_t *hw, uint32_t gpio_num)
163 {
164 PIN_SLP_SEL_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
165 }
166
167 /**
168 * @brief Return slp-sel status on GPIO.
169 *
170 * @param hw Peripheral GPIO hardware instance address.
171 * @param gpio_num GPIO number
172 * @return if GPIO gpio_num`s SLP_SEL is true
173 */
gpio_ll_sleep_sel_is_enabled(gpio_dev_t * hw,uint32_t gpio_num)174 static inline bool gpio_ll_sleep_sel_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
175 {
176 return REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], SLP_SEL) ? true : false;
177 }
178
179 /**
180 * @brief Disable GPIO pull-up in sleep mode.
181 *
182 * @param hw Peripheral GPIO hardware instance address.
183 * @param gpio_num GPIO number
184 */
gpio_ll_sleep_pullup_dis(gpio_dev_t * hw,uint32_t gpio_num)185 static inline void gpio_ll_sleep_pullup_dis(gpio_dev_t *hw, uint32_t gpio_num)
186 {
187 PIN_SLP_PULLUP_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
188 }
189
190 /**
191 * @brief Enable GPIO pull-up in sleep mode.
192 *
193 * @param hw Peripheral GPIO hardware instance address.
194 * @param gpio_num GPIO number
195 */
gpio_ll_sleep_pullup_en(gpio_dev_t * hw,uint32_t gpio_num)196 static inline void gpio_ll_sleep_pullup_en(gpio_dev_t *hw, uint32_t gpio_num)
197 {
198 PIN_SLP_PULLUP_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
199 }
200
201 /**
202 * @brief Return slp-pull-up status on GPIO.
203 *
204 * @param hw Peripheral GPIO hardware instance address.
205 * @param gpio_num GPIO number
206 * @return if GPIO gpio_num`s SLP_PU is true
207 */
gpio_ll_sleep_pullup_is_enabled(gpio_dev_t * hw,uint32_t gpio_num)208 static inline bool gpio_ll_sleep_pullup_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
209 {
210 return REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], SLP_PU) ? true : false;
211 }
212
213 /**
214 * @brief Enable GPIO pull-down in sleep mode.
215 *
216 * @param hw Peripheral GPIO hardware instance address.
217 * @param gpio_num GPIO number
218 */
gpio_ll_sleep_pulldown_en(gpio_dev_t * hw,uint32_t gpio_num)219 static inline void gpio_ll_sleep_pulldown_en(gpio_dev_t *hw, uint32_t gpio_num)
220 {
221 PIN_SLP_PULLDOWN_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
222 }
223
224 /**
225 * @brief Disable GPIO pull-down in sleep mode.
226 *
227 * @param hw Peripheral GPIO hardware instance address.
228 * @param gpio_num GPIO number
229 */
gpio_ll_sleep_pulldown_dis(gpio_dev_t * hw,uint32_t gpio_num)230 static inline void gpio_ll_sleep_pulldown_dis(gpio_dev_t *hw, uint32_t gpio_num)
231 {
232 PIN_SLP_PULLDOWN_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
233 }
234
235 /**
236 * @brief Return slp-pull-down status on GPIO.
237 *
238 * @param hw Peripheral GPIO hardware instance address.
239 * @param gpio_num GPIO number
240 * @return if GPIO gpio_num`s SLP_PD is true
241 */
gpio_ll_sleep_pulldown_is_enabled(gpio_dev_t * hw,uint32_t gpio_num)242 static inline bool gpio_ll_sleep_pulldown_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
243 {
244 return REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], SLP_PD) ? true : false;
245 }
246
247 /**
248 * @brief GPIO set interrupt trigger type
249 *
250 * @param hw Peripheral GPIO hardware instance address.
251 * @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);
252 * @param intr_type Interrupt type, select from gpio_int_type_t
253 */
gpio_ll_set_intr_type(gpio_dev_t * hw,uint32_t gpio_num,gpio_int_type_t intr_type)254 static inline void gpio_ll_set_intr_type(gpio_dev_t *hw, uint32_t gpio_num, gpio_int_type_t intr_type)
255 {
256 hw->pin[gpio_num].int_type = intr_type;
257 }
258
259 /**
260 * @brief Get GPIO interrupt status
261 *
262 * @param hw Peripheral GPIO hardware instance address.
263 * @param core_id interrupt core id
264 * @param status interrupt status
265 */
266 __attribute__((always_inline))
gpio_ll_get_intr_status(gpio_dev_t * hw,uint32_t core_id,uint32_t * status)267 static inline void gpio_ll_get_intr_status(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
268 {
269 *status = (core_id == 0) ? hw->pcpu_int : hw->acpu_int;
270 }
271
272 /**
273 * @brief Get GPIO interrupt status high
274 *
275 * @param hw Peripheral GPIO hardware instance address.
276 * @param core_id interrupt core id
277 * @param status interrupt status high
278 */
279 __attribute__((always_inline))
gpio_ll_get_intr_status_high(gpio_dev_t * hw,uint32_t core_id,uint32_t * status)280 static inline void gpio_ll_get_intr_status_high(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
281 {
282 *status = (core_id == 0) ? HAL_FORCE_READ_U32_REG_FIELD(hw->pcpu_int1, intr) : HAL_FORCE_READ_U32_REG_FIELD(hw->acpu_int1, intr);
283 }
284
285 /**
286 * @brief Clear GPIO interrupt status
287 *
288 * @param hw Peripheral GPIO hardware instance address.
289 * @param mask interrupt status clear mask
290 */
291 __attribute__((always_inline))
gpio_ll_clear_intr_status(gpio_dev_t * hw,uint32_t mask)292 static inline void gpio_ll_clear_intr_status(gpio_dev_t *hw, uint32_t mask)
293 {
294 hw->status_w1tc = mask;
295 }
296
297 /**
298 * @brief Clear GPIO interrupt status high
299 *
300 * @param hw Peripheral GPIO hardware instance address.
301 * @param mask interrupt status high clear mask
302 */
303 __attribute__((always_inline))
gpio_ll_clear_intr_status_high(gpio_dev_t * hw,uint32_t mask)304 static inline void gpio_ll_clear_intr_status_high(gpio_dev_t *hw, uint32_t mask)
305 {
306 HAL_FORCE_MODIFY_U32_REG_FIELD(hw->status1_w1tc, intr_st, mask);
307 }
308
309 /**
310 * @brief Enable GPIO module interrupt signal
311 *
312 * @param hw Peripheral GPIO hardware instance address.
313 * @param core_id Interrupt enabled CPU to corresponding ID
314 * @param gpio_num GPIO number. If you want to enable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
315 */
316 __attribute__((always_inline))
gpio_ll_intr_enable_on_core(gpio_dev_t * hw,uint32_t core_id,uint32_t gpio_num)317 static inline void gpio_ll_intr_enable_on_core(gpio_dev_t *hw, uint32_t core_id, uint32_t gpio_num)
318 {
319 if (core_id == 0) {
320 hw->pin[gpio_num].int_ena = GPIO_LL_PRO_CPU_INTR_ENA; //enable pro cpu intr
321 } else {
322 hw->pin[gpio_num].int_ena = GPIO_LL_APP_CPU_INTR_ENA; //enable app cpu intr
323 }
324 }
325
326 /**
327 * @brief Disable GPIO module interrupt signal
328 *
329 * @param hw Peripheral GPIO hardware instance address.
330 * @param gpio_num GPIO number. If you want to disable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
331 */
332 __attribute__((always_inline))
gpio_ll_intr_disable(gpio_dev_t * hw,uint32_t gpio_num)333 static inline void gpio_ll_intr_disable(gpio_dev_t *hw, uint32_t gpio_num)
334 {
335 hw->pin[gpio_num].int_ena = 0; //disable GPIO intr
336 }
337
338 /**
339 * @brief Disable input mode on GPIO.
340 *
341 * @param hw Peripheral GPIO hardware instance address.
342 * @param gpio_num GPIO number
343 */
344 __attribute__((always_inline))
gpio_ll_input_disable(gpio_dev_t * hw,uint32_t gpio_num)345 static inline void gpio_ll_input_disable(gpio_dev_t *hw, uint32_t gpio_num)
346 {
347 PIN_INPUT_DISABLE(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num]);
348 }
349
350 /**
351 * @brief Enable input mode on GPIO.
352 *
353 * @param hw Peripheral GPIO hardware instance address.
354 * @param gpio_num GPIO number
355 */
gpio_ll_input_enable(gpio_dev_t * hw,uint32_t gpio_num)356 static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num)
357 {
358 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
359 }
360
361 /**
362 * @brief Disable output mode on GPIO.
363 *
364 * @param hw Peripheral GPIO hardware instance address.
365 * @param gpio_num GPIO number
366 */
367 __attribute__((always_inline))
gpio_ll_output_disable(gpio_dev_t * hw,uint32_t gpio_num)368 static inline void gpio_ll_output_disable(gpio_dev_t *hw, uint32_t gpio_num)
369 {
370 if (gpio_num < 32) {
371 hw->enable_w1tc = (0x1 << gpio_num);
372 } else {
373 HAL_FORCE_MODIFY_U32_REG_FIELD(hw->enable1_w1tc, data, (0x1 << (gpio_num - 32)));
374 }
375
376 // Ensure no other output signal is routed via GPIO matrix to this pin
377 REG_WRITE(GPIO_FUNC0_OUT_SEL_CFG_REG + (gpio_num * 4),
378 SIG_GPIO_OUT_IDX);
379 }
380
381 /**
382 * @brief Enable output mode on GPIO.
383 *
384 * @param hw Peripheral GPIO hardware instance address.
385 * @param gpio_num GPIO number
386 */
gpio_ll_output_enable(gpio_dev_t * hw,uint32_t gpio_num)387 static inline __attribute__((always_inline)) void gpio_ll_output_enable(gpio_dev_t *hw, uint32_t gpio_num)
388 {
389 if (gpio_num < 32) {
390 hw->enable_w1ts = (0x1 << gpio_num);
391 } else {
392 HAL_FORCE_MODIFY_U32_REG_FIELD(hw->enable1_w1ts, data, (0x1 << (gpio_num - 32)));
393 }
394 }
395
396 /**
397 * @brief Disable GPIO input in sleep mode.
398 *
399 * @param hw Peripheral GPIO hardware instance address.
400 * @param gpio_num GPIO number
401 */
gpio_ll_sleep_input_disable(gpio_dev_t * hw,uint32_t gpio_num)402 static inline void gpio_ll_sleep_input_disable(gpio_dev_t *hw, uint32_t gpio_num)
403 {
404 PIN_SLP_INPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
405 }
406
407 /**
408 * @brief Enable GPIO input in sleep mode.
409 *
410 * @param hw Peripheral GPIO hardware instance address.
411 * @param gpio_num GPIO number
412 */
gpio_ll_sleep_input_enable(gpio_dev_t * hw,uint32_t gpio_num)413 static inline void gpio_ll_sleep_input_enable(gpio_dev_t *hw, uint32_t gpio_num)
414 {
415 PIN_SLP_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
416 }
417
418 /**
419 * @brief Disable GPIO output in sleep mode.
420 *
421 * @param hw Peripheral GPIO hardware instance address.
422 * @param gpio_num GPIO number
423 */
gpio_ll_sleep_output_disable(gpio_dev_t * hw,uint32_t gpio_num)424 static inline void gpio_ll_sleep_output_disable(gpio_dev_t *hw, uint32_t gpio_num)
425 {
426 PIN_SLP_OUTPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
427 }
428
429 /**
430 * @brief Enable GPIO output in sleep mode.
431 *
432 * @param hw Peripheral GPIO hardware instance address.
433 * @param gpio_num GPIO number
434 */
gpio_ll_sleep_output_enable(gpio_dev_t * hw,uint32_t gpio_num)435 static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num)
436 {
437 PIN_SLP_OUTPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
438 }
439
440 /**
441 * @brief Disable open-drain mode on GPIO.
442 *
443 * @param hw Peripheral GPIO hardware instance address.
444 * @param gpio_num GPIO number
445 */
gpio_ll_od_disable(gpio_dev_t * hw,uint32_t gpio_num)446 static inline __attribute__((always_inline)) void gpio_ll_od_disable(gpio_dev_t *hw, uint32_t gpio_num)
447 {
448 hw->pin[gpio_num].pad_driver = 0;
449 }
450
451 /**
452 * @brief Enable open-drain mode on GPIO.
453 *
454 * @param hw Peripheral GPIO hardware instance address.
455 * @param gpio_num GPIO number
456 */
gpio_ll_od_enable(gpio_dev_t * hw,uint32_t gpio_num)457 static inline void gpio_ll_od_enable(gpio_dev_t *hw, uint32_t gpio_num)
458 {
459 hw->pin[gpio_num].pad_driver = 1;
460 }
461
462 /**
463 * @brief Select a function for the pin in the IOMUX
464 *
465 * @param hw Peripheral GPIO hardware instance address.
466 * @param gpio_num GPIO number
467 * @param func Function to assign to the pin
468 */
gpio_ll_func_sel(gpio_dev_t * hw,uint8_t gpio_num,uint32_t func)469 static inline __attribute__((always_inline)) void gpio_ll_func_sel(gpio_dev_t *hw, uint8_t gpio_num, uint32_t func)
470 {
471 PIN_FUNC_SELECT(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num], func);
472 }
473
474 /**
475 * @brief GPIO set output level
476 *
477 * @param hw Peripheral GPIO hardware instance address.
478 * @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);
479 * @param level Output level. 0: low ; 1: high
480 */
481 __attribute__((always_inline))
gpio_ll_set_level(gpio_dev_t * hw,uint32_t gpio_num,uint32_t level)482 static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t level)
483 {
484 if (level) {
485 if (gpio_num < 32) {
486 hw->out_w1ts = (1 << gpio_num);
487 } else {
488 HAL_FORCE_MODIFY_U32_REG_FIELD(hw->out1_w1ts, data, (1 << (gpio_num - 32)));
489 }
490 } else {
491 if (gpio_num < 32) {
492 hw->out_w1tc = (1 << gpio_num);
493 } else {
494 HAL_FORCE_MODIFY_U32_REG_FIELD(hw->out1_w1tc, data, (1 << (gpio_num - 32)));
495 }
496 }
497 }
498
499 /**
500 * @brief GPIO get input level
501 *
502 * @warning If the pad is not configured for input (or input and output) the returned value is always 0.
503 *
504 * @param hw Peripheral GPIO hardware instance address.
505 * @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);
506 *
507 * @return
508 * - 0 the GPIO input level is 0
509 * - 1 the GPIO input level is 1
510 */
gpio_ll_get_level(gpio_dev_t * hw,uint32_t gpio_num)511 static inline int gpio_ll_get_level(gpio_dev_t *hw, uint32_t gpio_num)
512 {
513 if (gpio_num < 32) {
514 return (hw->in >> gpio_num) & 0x1;
515 } else {
516 return (HAL_FORCE_READ_U32_REG_FIELD(hw->in1, data) >> (gpio_num - 32)) & 0x1;
517 }
518 }
519
520 /**
521 * @brief Enable GPIO wake-up function.
522 *
523 * @param hw Peripheral GPIO hardware instance address.
524 * @param gpio_num GPIO number.
525 */
gpio_ll_wakeup_enable(gpio_dev_t * hw,uint32_t gpio_num)526 static inline void gpio_ll_wakeup_enable(gpio_dev_t *hw, uint32_t gpio_num)
527 {
528 hw->pin[gpio_num].wakeup_enable = 0x1;
529 }
530
531 /**
532 * @brief Disable GPIO wake-up function.
533 *
534 * @param hw Peripheral GPIO hardware instance address.
535 * @param gpio_num GPIO number
536 */
gpio_ll_wakeup_disable(gpio_dev_t * hw,uint32_t gpio_num)537 static inline void gpio_ll_wakeup_disable(gpio_dev_t *hw, uint32_t gpio_num)
538 {
539 hw->pin[gpio_num].wakeup_enable = 0;
540 }
541
542 /**
543 * @brief Set GPIO pad drive capability
544 *
545 * @param hw Peripheral GPIO hardware instance address.
546 * @param gpio_num GPIO number, only support output GPIOs
547 * @param strength Drive capability of the pad
548 */
gpio_ll_set_drive_capability(gpio_dev_t * hw,uint32_t gpio_num,gpio_drive_cap_t strength)549 static inline void gpio_ll_set_drive_capability(gpio_dev_t *hw, uint32_t gpio_num, gpio_drive_cap_t strength)
550 {
551 SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, strength, FUN_DRV_S);
552 }
553
554 /**
555 * @brief Get GPIO pad drive capability
556 *
557 * @param hw Peripheral GPIO hardware instance address.
558 * @param gpio_num GPIO number, only support output GPIOs
559 * @param strength Pointer to accept drive capability of the pad
560 */
gpio_ll_get_drive_capability(gpio_dev_t * hw,uint32_t gpio_num,gpio_drive_cap_t * strength)561 static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_num, gpio_drive_cap_t *strength)
562 {
563 *strength = (gpio_drive_cap_t)GET_PERI_REG_BITS2(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, FUN_DRV_S);
564 }
565
566 /**
567 * @brief Enable all digital gpio pad hold function during Deep-sleep.
568 *
569 * @param hw Peripheral GPIO hardware instance address.
570 */
gpio_ll_deep_sleep_hold_en(gpio_dev_t * hw)571 static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw)
572 {
573 CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
574 SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
575 }
576
577 /**
578 * @brief Disable all digital gpio pad hold function during Deep-sleep.
579 *
580 * @param hw Peripheral GPIO hardware instance address.
581 */
gpio_ll_deep_sleep_hold_dis(gpio_dev_t * hw)582 static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw)
583 {
584 CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
585 }
586
587 /**
588 * @brief Get deep sleep hold status
589 *
590 * @param hw Peripheral GPIO hardware instance address.
591 *
592 * @return
593 * - true deep sleep hold is enabled
594 * - false deep sleep hold is disabled
595 */
596 __attribute__((always_inline))
gpio_ll_deep_sleep_hold_is_en(gpio_dev_t * hw)597 static inline bool gpio_ll_deep_sleep_hold_is_en(gpio_dev_t *hw)
598 {
599 return !GET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD) && GET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
600 }
601
602 /**
603 * @brief Enable gpio pad hold function.
604 *
605 * @param hw Peripheral GPIO hardware instance address.
606 * @param gpio_num GPIO number, only support output GPIOs
607 */
gpio_ll_hold_en(gpio_dev_t * hw,uint32_t gpio_num)608 static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num)
609 {
610 SET_PERI_REG_MASK(RTC_IO_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
611 }
612
613 /**
614 * @brief Disable gpio pad hold function.
615 *
616 * @param hw Peripheral GPIO hardware instance address.
617 * @param gpio_num GPIO number, only support output GPIOs
618 */
gpio_ll_hold_dis(gpio_dev_t * hw,uint32_t gpio_num)619 static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num)
620 {
621 CLEAR_PERI_REG_MASK(RTC_IO_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
622 }
623
624 /**
625 * @brief Get digital gpio pad hold status.
626 *
627 * @param hw Peripheral GPIO hardware instance address.
628 * @param gpio_num GPIO number, only support output GPIOs
629 *
630 * @note caller must ensure that gpio_num is a digital io pad
631 *
632 * @return
633 * - true digital gpio pad is held
634 * - false digital gpio pad is unheld
635 */
636 __attribute__((always_inline))
gpio_ll_is_digital_io_hold(gpio_dev_t * hw,uint32_t gpio_num)637 static inline bool gpio_ll_is_digital_io_hold(gpio_dev_t *hw, uint32_t gpio_num)
638 {
639 uint32_t mask = 0;
640
641 switch (gpio_num) {
642 case 1: mask = BIT(1); break;
643 case 3: mask = BIT(0); break;
644 case 5: mask = BIT(8); break;
645 case 6 ... 11 : mask = BIT(gpio_num - 4); break;
646 case 16 ... 19:
647 case 21 ... 23: mask = BIT(gpio_num - 7); break;
648 default: break;
649 }
650
651 return GET_PERI_REG_MASK(RTC_IO_DIG_PAD_HOLD_REG, mask);
652 }
653
654 /**
655 * @brief Set pad input to a peripheral signal through the IOMUX.
656 *
657 * @param hw Peripheral GPIO hardware instance address.
658 * @param gpio_num GPIO number of the pad.
659 * @param signal_idx Peripheral signal id to input. One of the ``*_IN_IDX`` signals in ``soc/gpio_sig_map.h``.
660 */
661 __attribute__((always_inline))
gpio_ll_iomux_in(gpio_dev_t * hw,uint32_t gpio,uint32_t signal_idx)662 static inline void gpio_ll_iomux_in(gpio_dev_t *hw, uint32_t gpio, uint32_t signal_idx)
663 {
664 hw->func_in_sel_cfg[signal_idx].sig_in_sel = 0;
665 PIN_INPUT_ENABLE(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio]);
666 }
667
668 /**
669 * @brief Select a function for the pin in the IOMUX
670 *
671 * @param pin_name Pin name to configure
672 * @param func Function to assign to the pin
673 */
gpio_ll_iomux_func_sel(uint32_t pin_name,uint32_t func)674 static inline __attribute__((always_inline)) void gpio_ll_iomux_func_sel(uint32_t pin_name, uint32_t func)
675 {
676 PIN_FUNC_SELECT(pin_name, func);
677 }
678
679 /**
680 * @brief Control the pin in the IOMUX
681 *
682 * @param val Control value
683 */
gpio_ll_iomux_pin_ctrl(uint32_t val)684 static inline __attribute__((always_inline)) void gpio_ll_iomux_pin_ctrl(uint32_t val)
685 {
686 WRITE_PERI_REG(PIN_CTRL, val);
687 }
688
689 /**
690 * @brief Set peripheral output to an GPIO pad through the IOMUX.
691 *
692 * @param hw Peripheral GPIO hardware instance address.
693 * @param gpio_num gpio_num GPIO number of the pad.
694 * @param func The function number of the peripheral pin to output pin.
695 * One of the ``FUNC_X_*`` of specified pin (X) in ``soc/io_mux_reg.h``.
696 * @param oen_inv True if the output enable needs to be inverted, otherwise False.
697 */
gpio_ll_iomux_out(gpio_dev_t * hw,uint8_t gpio_num,int func,uint32_t oen_inv)698 static inline void gpio_ll_iomux_out(gpio_dev_t *hw, uint8_t gpio_num, int func, uint32_t oen_inv)
699 {
700 hw->func_out_sel_cfg[gpio_num].oen_sel = 0;
701 hw->func_out_sel_cfg[gpio_num].oen_inv_sel = oen_inv;
702 gpio_ll_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], func);
703 }
704
705 /**
706 * @brief Get the GPIO number that is routed to the input peripheral signal through GPIO matrix.
707 *
708 * @param hw Peripheral GPIO hardware instance address.
709 * @param in_sig_idx Peripheral signal index (tagged as input attribute).
710 *
711 * @return
712 * - -1 Signal bypassed GPIO matrix
713 * - Others GPIO number
714 */
gpio_ll_get_in_signal_connected_io(gpio_dev_t * hw,uint32_t in_sig_idx)715 static inline int gpio_ll_get_in_signal_connected_io(gpio_dev_t *hw, uint32_t in_sig_idx)
716 {
717 typeof(hw->func_in_sel_cfg[in_sig_idx]) reg;
718 reg.val = hw->func_in_sel_cfg[in_sig_idx].val;
719 return (reg.sig_in_sel ? reg.func_sel : -1);
720 }
721
722 #ifdef __cplusplus
723 }
724 #endif
725