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