Merge branch 'refactor/esp_hal_gpio' into 'master'

refactor(gpio): split GPIO HAL into separate component

Closes IDF-14089

See merge request espressif/esp-idf!43215
This commit is contained in:
morris
2025-12-01 10:40:07 +08:00
279 changed files with 972 additions and 692 deletions
-756
View File
@@ -1,756 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The LL layer for ESP32 GPIO register operations
#pragma once
#include <stdbool.h>
#include "soc/soc.h"
#include "soc/gpio_periph.h"
#include "soc/gpio_struct.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "hal/gpio_types.h"
#include "hal/misc.h"
#ifdef __cplusplus
extern "C" {
#endif
// the address of esp32's IO_MUX_GPIOx_REGs are not incremented as the gpio number increments(address are out of order)
extern const uint8_t GPIO_PIN_MUX_REG_OFFSET[SOC_GPIO_PIN_COUNT];
// Get GPIO hardware instance with giving gpio num
#define GPIO_LL_GET_HW(num) (((num) == 0) ? (&GPIO) : NULL)
// the gpio matrix signal routing const time
#define GPIO_LL_MATRIX_DELAY_NS 25
#define GPIO_LL_APP_CPU_INTR_ENA (BIT(0))
#define GPIO_LL_APP_CPU_NMI_INTR_ENA (BIT(1))
#define GPIO_LL_PRO_CPU_INTR_ENA (BIT(2))
#define GPIO_LL_PRO_CPU_NMI_INTR_ENA (BIT(3))
#define GPIO_LL_SDIO_EXT_INTR_ENA (BIT(4))
#define GPIO_LL_INTR_SOURCE0 ETS_GPIO_INTR_SOURCE
/**
* @brief Get the configuration for an IO
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @param[out] io_config Pointer to the structure that saves the specific IO configuration
*/
static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio_io_config_t *io_config)
{
uint32_t bit_shift = (gpio_num < 32) ? gpio_num : (gpio_num - 32);
uint32_t bit_mask = 1 << bit_shift;
uint32_t iomux_reg_val = REG_READ(GPIO_PIN_MUX_REG[gpio_num]);
io_config->pu = (iomux_reg_val & FUN_PU_M) >> FUN_PU_S;
io_config->pd = (iomux_reg_val & FUN_PD_M) >> FUN_PD_S;
io_config->ie = (iomux_reg_val & FUN_IE_M) >> FUN_IE_S;
io_config->oe = (((gpio_num < 32) ? hw->enable : hw->enable1.val) & bit_mask) >> bit_shift;
io_config->oe_ctrl_by_periph = !(hw->func_out_sel_cfg[gpio_num].oen_sel);
io_config->oe_inv = hw->func_out_sel_cfg[gpio_num].oen_inv_sel;
io_config->od = hw->pin[gpio_num].pad_driver;
io_config->drv = (gpio_drive_cap_t)((iomux_reg_val & FUN_DRV_M) >> FUN_DRV_S);
io_config->fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
io_config->sig_out = hw->func_out_sel_cfg[gpio_num].func_sel;
io_config->slp_sel = (iomux_reg_val & SLP_SEL_M) >> SLP_SEL_S;
}
/**
* @brief Enable pull-up on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_pullup_en(gpio_dev_t *hw, uint32_t gpio_num)
{
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
}
/**
* @brief Disable pull-up on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_pullup_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
REG_CLR_BIT(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num], FUN_PU);
}
/**
* @brief Return pull-up status on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @return if GPIO gpio_num`s FUN_PU is true
*/
static inline bool gpio_ll_pullup_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
{
return REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU) ? true : false;
}
/**
* @brief Enable pull-down on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_pulldown_en(gpio_dev_t *hw, uint32_t gpio_num)
{
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
}
/**
* @brief Disable pull-down on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_pulldown_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
REG_CLR_BIT(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num], FUN_PD);
}
/**
* @brief Return pull-down status on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @return if GPIO gpio_num`s FUN_PD is true
*/
static inline bool gpio_ll_pulldown_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
{
return REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD) ? true : false;
}
/**
* @brief Enable GPIO pin used for wakeup from sleep.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_sel_en(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_SEL_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO pin used for wakeup from sleep.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_sel_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_SEL_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Return slp-sel status on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @return if GPIO gpio_num`s SLP_SEL is true
*/
__attribute__((always_inline))
static inline bool gpio_ll_sleep_sel_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
{
return REG_GET_BIT(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num], SLP_SEL) ? true : false;
}
/**
* @brief Disable GPIO pull-up in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_pullup_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_PULLUP_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Enable GPIO pull-up in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_pullup_en(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_PULLUP_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Return slp-pull-up status on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @return if GPIO gpio_num`s SLP_PU is true
*/
__attribute__((always_inline))
static inline bool gpio_ll_sleep_pullup_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
{
return REG_GET_BIT(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num], SLP_PU) ? true : false;
}
/**
* @brief Enable GPIO pull-down in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_pulldown_en(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_PULLDOWN_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO pull-down in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_pulldown_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_PULLDOWN_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Return slp-pull-down status on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @return if GPIO gpio_num`s SLP_PD is true
*/
__attribute__((always_inline))
static inline bool gpio_ll_sleep_pulldown_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
{
return REG_GET_BIT(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num], SLP_PD) ? true : false;
}
/**
* @brief GPIO set interrupt trigger type
*
* @param hw Peripheral GPIO hardware instance address.
* @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);
* @param intr_type Interrupt type, select from gpio_int_type_t
*/
static inline void gpio_ll_set_intr_type(gpio_dev_t *hw, uint32_t gpio_num, gpio_int_type_t intr_type)
{
hw->pin[gpio_num].int_type = intr_type;
}
/**
* @brief Get GPIO interrupt status
*
* @param hw Peripheral GPIO hardware instance address.
* @param core_id interrupt core id
* @param status interrupt status
*/
__attribute__((always_inline))
static inline void gpio_ll_get_intr_status(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
{
*status = (core_id == 0) ? hw->pcpu_int : hw->acpu_int;
}
/**
* @brief Get GPIO interrupt status high
*
* @param hw Peripheral GPIO hardware instance address.
* @param core_id interrupt core id
* @param status interrupt status high
*/
__attribute__((always_inline))
static inline void gpio_ll_get_intr_status_high(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
{
*status = (core_id == 0) ? HAL_FORCE_READ_U32_REG_FIELD(hw->pcpu_int1, intr) : HAL_FORCE_READ_U32_REG_FIELD(hw->acpu_int1, intr);
}
/**
* @brief Clear GPIO interrupt status
*
* @param hw Peripheral GPIO hardware instance address.
* @param mask interrupt status clear mask
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_intr_status(gpio_dev_t *hw, uint32_t mask)
{
hw->status_w1tc = mask;
}
/**
* @brief Clear GPIO interrupt status high
*
* @param hw Peripheral GPIO hardware instance address.
* @param mask interrupt status high clear mask
*/
__attribute__((always_inline))
static inline void gpio_ll_clear_intr_status_high(gpio_dev_t *hw, uint32_t mask)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->status1_w1tc, intr_st, mask);
}
/**
* @brief Enable GPIO module interrupt signal
*
* @param hw Peripheral GPIO hardware instance address.
* @param core_id Interrupt enabled CPU to corresponding ID
* @param gpio_num GPIO number. If you want to enable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
*/
__attribute__((always_inline))
static inline void gpio_ll_intr_enable_on_core(gpio_dev_t *hw, uint32_t core_id, uint32_t gpio_num)
{
if (core_id == 0) {
hw->pin[gpio_num].int_ena = GPIO_LL_PRO_CPU_INTR_ENA; //enable pro cpu intr
} else {
hw->pin[gpio_num].int_ena = GPIO_LL_APP_CPU_INTR_ENA; //enable app cpu intr
}
}
/**
* @brief Disable GPIO module interrupt signal
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number. If you want to disable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
*/
__attribute__((always_inline))
static inline void gpio_ll_intr_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
hw->pin[gpio_num].int_ena = 0; //disable GPIO intr
}
/**
* @brief Disable input mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_input_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_INPUT_DISABLE(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num]);
}
/**
* @brief Enable input mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_INPUT_ENABLE(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num]);
}
/**
* @brief Disable output mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_output_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
if (gpio_num < 32) {
hw->enable_w1tc = (0x1 << gpio_num);
} else {
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->enable1_w1tc, data, (0x1 << (gpio_num - 32)));
}
}
/**
* @brief Enable output mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_output_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
if (gpio_num < 32) {
hw->enable_w1ts = (0x1 << gpio_num);
} else {
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->enable1_w1ts, data, (0x1 << (gpio_num - 32)));
}
}
/**
* @brief Disable GPIO input in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_input_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_INPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Enable GPIO input in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_input_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable GPIO output in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_output_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_OUTPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Enable GPIO output in sleep mode.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
PIN_SLP_OUTPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
/**
* @brief Disable open-drain mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
__attribute__((always_inline))
static inline void gpio_ll_od_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
hw->pin[gpio_num].pad_driver = 0;
}
/**
* @brief Enable open-drain mode on GPIO.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_od_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
hw->pin[gpio_num].pad_driver = 1;
}
/**
* @brief Select a function for the pin in the IOMUX
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
* @param func Function to assign to the pin
*/
__attribute__((always_inline))
static inline void gpio_ll_func_sel(gpio_dev_t *hw, uint8_t gpio_num, uint32_t func)
{
PIN_FUNC_SELECT(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num], func);
}
/**
* @brief GPIO set output level
*
* @param hw Peripheral GPIO hardware instance address.
* @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);
* @param level Output level. 0: low ; 1: high
*/
__attribute__((always_inline))
static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t level)
{
if (level) {
if (gpio_num < 32) {
hw->out_w1ts = 1 << gpio_num;
} else {
hw->out1_w1ts.val = 1 << (gpio_num - 32);
}
} else {
if (gpio_num < 32) {
hw->out_w1tc = 1 << gpio_num;
} else {
hw->out1_w1tc.val = 1 << (gpio_num - 32);
}
}
}
/**
* @brief GPIO get input level
*
* @warning If the pad is not configured for input (or input and output) the returned value is always 0.
*
* @param hw Peripheral GPIO hardware instance address.
* @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);
*
* @return
* - 0 the GPIO input level is 0
* - 1 the GPIO input level is 1
*/
__attribute__((always_inline))
static inline int gpio_ll_get_level(gpio_dev_t *hw, uint32_t gpio_num)
{
if (gpio_num < 32) {
return (hw->in >> gpio_num) & 0x1;
} else {
return (HAL_FORCE_READ_U32_REG_FIELD(hw->in1, data) >> (gpio_num - 32)) & 0x1;
}
}
/**
* @brief Enable GPIO wake-up function.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number.
*/
static inline void gpio_ll_wakeup_enable(gpio_dev_t *hw, uint32_t gpio_num)
{
hw->pin[gpio_num].wakeup_enable = 1;
}
/**
* @brief Disable GPIO wake-up function.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number
*/
static inline void gpio_ll_wakeup_disable(gpio_dev_t *hw, uint32_t gpio_num)
{
hw->pin[gpio_num].wakeup_enable = 0;
}
/**
* @brief Set GPIO pad drive capability
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
* @param strength Drive capability of the pad
*/
static inline void gpio_ll_set_drive_capability(gpio_dev_t *hw, uint32_t gpio_num, gpio_drive_cap_t strength)
{
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, strength, FUN_DRV_S);
}
/**
* @brief Get GPIO pad drive capability
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
* @param strength Pointer to accept drive capability of the pad
*/
static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_num, gpio_drive_cap_t *strength)
{
*strength = (gpio_drive_cap_t)GET_PERI_REG_BITS2(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, FUN_DRV_S);
}
/**
* @brief Enable all digital gpio pad hold function during Deep-sleep.
*
* @param hw Peripheral GPIO hardware instance address.
*/
static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
}
/**
* @brief Disable all digital gpio pad hold function during Deep-sleep.
*
* @param hw Peripheral GPIO hardware instance address.
*/
static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
}
/**
* @brief Get deep sleep hold status
*
* @param hw Peripheral GPIO hardware instance address.
*
* @return
* - true deep sleep hold is enabled
* - false deep sleep hold is disabled
*/
__attribute__((always_inline))
static inline bool gpio_ll_deep_sleep_hold_is_en(gpio_dev_t *hw)
{
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);
}
/**
* @brief Enable gpio pad hold function.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
*/
static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num)
{
SET_PERI_REG_MASK(RTC_IO_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
}
/**
* @brief Disable gpio pad hold function.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
*/
static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num)
{
CLEAR_PERI_REG_MASK(RTC_IO_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
}
/**
* @brief Get digital gpio pad hold status.
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number, only support output GPIOs
*
* @note caller must ensure that gpio_num is a digital io pad
*
* @return
* - true digital gpio pad is held
* - false digital gpio pad is unheld
*/
__attribute__((always_inline))
static inline bool gpio_ll_is_digital_io_hold(gpio_dev_t *hw, uint32_t gpio_num)
{
uint32_t mask = 0;
switch (gpio_num) {
case 1: mask = BIT(1); break;
case 3: mask = BIT(0); break;
case 5: mask = BIT(8); break;
case 6 ... 11 : mask = BIT(gpio_num - 4); break;
case 16 ... 19:
case 21 ... 23: mask = BIT(gpio_num - 7); break;
default: break;
}
return GET_PERI_REG_MASK(RTC_IO_DIG_PAD_HOLD_REG, mask);
}
/**
* @brief Configure peripheral signal input whether to bypass GPIO matrix.
*
* @param hw Peripheral GPIO hardware instance address.
* @param signal_idx Peripheral signal id to input. One of the ``*_IN_IDX`` signals in ``soc/gpio_sig_map.h``.
* @param from_gpio_matrix True if not to bypass GPIO matrix, otherwise False.
*/
__attribute__((always_inline))
static inline void gpio_ll_set_input_signal_from(gpio_dev_t *hw, uint32_t signal_idx, bool from_gpio_matrix)
{
hw->func_in_sel_cfg[signal_idx].sig_in_sel = from_gpio_matrix;
}
/**
* @brief Connect a GPIO input with a peripheral signal, which tagged as input attribute.
*
* @note There's no limitation on the number of signals that a GPIO can combine with.
*
* @param signal_idx Peripheral signal index (tagged as input attribute)
* @param gpio_num GPIO number, especially, `GPIO_MATRIX_CONST_ZERO_INPUT` means connect logic 0 to signal
* `GPIO_MATRIX_CONST_ONE_INPUT` means connect logic 1 to signal
* @param in_inv True if the GPIO input needs to be inverted, otherwise False.
*/
static inline void gpio_ll_set_input_signal_matrix_source(gpio_dev_t *hw, uint32_t signal_idx, uint32_t gpio_num, bool in_inv)
{
hw->func_in_sel_cfg[signal_idx].func_sel = gpio_num;
hw->func_in_sel_cfg[signal_idx].sig_in_inv = in_inv;
gpio_ll_set_input_signal_from(hw, signal_idx, true);
}
/**
* @brief Get the GPIO number that is routed to the input peripheral signal through GPIO matrix.
*
* @param hw Peripheral GPIO hardware instance address.
* @param in_sig_idx Peripheral signal index (tagged as input attribute).
*
* @return
* - -1 Signal bypassed GPIO matrix
* - Others GPIO number
*/
static inline int gpio_ll_get_in_signal_connected_io(gpio_dev_t *hw, uint32_t in_sig_idx)
{
typeof(hw->func_in_sel_cfg[in_sig_idx]) reg;
reg.val = hw->func_in_sel_cfg[in_sig_idx].val;
return (reg.sig_in_sel ? reg.func_sel : -1);
}
/**
* @brief Configure the source of output enable signal for the pad (only takes effect if func sel is selected to be GPIO).
*
* @param hw Peripheral GPIO hardware instance address.
* @param gpio_num GPIO number of the pad.
* @param ctrl_by_periph True if use output enable signal from peripheral, false if force the output enable signal to be sourced from bit n of GPIO_ENABLE_REG
* @param oen_inv True if the output enable needs to be inverted, otherwise False.
*/
static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_num, bool ctrl_by_periph, bool oen_inv)
{
hw->func_out_sel_cfg[gpio_num].oen_inv_sel = oen_inv; // control valid only when using gpio matrix to route signal to the IO
hw->func_out_sel_cfg[gpio_num].oen_sel = !ctrl_by_periph;
}
/**
* @brief Connect a peripheral signal which tagged as output attribute with a GPIO.
*
* @note There's no limitation on the number of signals that a GPIO can combine with.
*
* @param gpio_num GPIO number
* @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level.
* @param out_inv True if the signal output needs to be inverted, otherwise False.
*/
static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv)
{
hw->func_out_sel_cfg[gpio_num].func_sel = signal_idx;
hw->func_out_sel_cfg[gpio_num].inv_sel = out_inv;
}
/**
* @brief Control the pin in the IOMUX
*
* @param bmap write mask of control value
* @param val Control value
* @param shift write mask shift of control value
*/
__attribute__((always_inline))
static inline void gpio_ll_set_pin_ctrl(uint32_t val, uint32_t bmap, uint32_t shift)
{
SET_PERI_REG_BITS(PIN_CTRL, bmap, val, shift);
}
#ifdef __cplusplus
}
#endif
@@ -1,412 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
#pragma once
#include <stdbool.h>
#include <stdlib.h>
#include "hal/gpio_types.h"
#include "hal/assert.h"
#include "soc/rtc_io_struct.h"
#include "soc/rtc_io_reg.h"
#include "soc/rtc_periph.h"
#define RTCIO_LL_PIN_FUNC 0
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
RTCIO_LL_FUNC_RTC = 0x0, /*!< The pin controlled by RTC module. */
RTCIO_LL_FUNC_DIGITAL = 0x1, /*!< The pin controlled by DIGITAL module. */
} rtcio_ll_func_t;
typedef enum {
RTCIO_LL_OUTPUT_NORMAL = 0, /*!< RTCIO output mode is normal. */
RTCIO_LL_OUTPUT_OD = 0x1, /*!< RTCIO output mode is open-drain. */
} rtcio_ll_out_mode_t;
/**
* @brief Select a RTC IOMUX function for the RTC IO
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param func Function to assign to the pin
*/
static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func)
{
SET_PERI_REG_BITS(rtc_io_desc[rtcio_num].reg, 0x3, func, rtc_io_desc[rtcio_num].func);
}
/**
* @brief Select the rtcio function.
*
* @note The RTC function must be selected before the pad analog function is enabled.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param func Select pin function.
*/
static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func)
{
if (func == RTCIO_LL_FUNC_RTC) {
// 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module.
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux));
//0:RTC FUNCTION 1,2,3:Reserved
rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC);
} else if (func == RTCIO_LL_FUNC_DIGITAL) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux));
}
}
/**
* Enable rtcio output.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_output_enable(int rtcio_num)
{
RTCIO.enable_w1ts.val = (1U << (rtcio_num + RTC_GPIO_ENABLE_W1TS_S));
}
/**
* Disable rtcio output.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_output_disable(int rtcio_num)
{
RTCIO.enable_w1tc.val = (1U << (rtcio_num + RTC_GPIO_ENABLE_W1TC_S));
}
/**
* Set RTCIO output level.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param level 0: output low; ~0: output high.
*/
static inline void rtcio_ll_set_level(int rtcio_num, uint32_t level)
{
if (level) {
RTCIO.out_w1ts.val = (1U << (rtcio_num + RTC_GPIO_OUT_DATA_W1TS_S));
} else {
RTCIO.out_w1tc.val = (1U << (rtcio_num + RTC_GPIO_OUT_DATA_W1TC_S));
}
}
/**
* Enable rtcio input.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_input_enable(int rtcio_num)
{
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].ie);
}
/**
* Disable rtcio input.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_input_disable(int rtcio_num)
{
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].ie);
}
/**
* Get RTCIO input level.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @return 0: input low; ~0: input high.
*/
static inline uint32_t rtcio_ll_get_level(int rtcio_num)
{
return (uint32_t)(RTCIO.in_val.in >> rtcio_num) & 0x1;
}
/**
* @brief Set RTC GPIO pad drive capability
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param strength Drive capability of the pad. Range: 0 ~ 3.
*/
static inline void rtcio_ll_set_drive_capability(int rtcio_num, uint32_t strength)
{
if (rtc_io_desc[rtcio_num].drv_v) {
SET_PERI_REG_BITS(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].drv_v, strength, rtc_io_desc[rtcio_num].drv_s);
}
}
/**
* @brief Get RTC GPIO pad drive capability.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @return Drive capability of the pad. Range: 0 ~ 3.
*/
static inline uint32_t rtcio_ll_get_drive_capability(int rtcio_num)
{
return GET_PERI_REG_BITS2(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].drv_v, rtc_io_desc[rtcio_num].drv_s);
}
/**
* @brief Set RTC GPIO pad output mode.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @return mode Output mode.
*/
static inline void rtcio_ll_output_mode_set(int rtcio_num, rtcio_ll_out_mode_t mode)
{
RTCIO.pin[rtcio_num].pad_driver = mode;
}
/**
* @brief RTC GPIO pullup enable.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
__attribute__((always_inline))
static inline void rtcio_ll_pullup_enable(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].pullup) {
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pullup);
}
}
/**
* @brief RTC GPIO pullup disable.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
__attribute__((always_inline))
static inline void rtcio_ll_pullup_disable(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].pullup) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pullup);
}
}
/**
* @brief Get RTC GPIO pad pullup status.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @return Whether the pullup of the pad is enabled or not.
*/
__attribute__((always_inline))
static inline bool rtcio_ll_is_pullup_enabled(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].pullup) {
return GET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pullup);
} else {
return false;
}
}
/**
* @brief RTC GPIO pulldown enable.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
__attribute__((always_inline))
static inline void rtcio_ll_pulldown_enable(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].pulldown) {
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pulldown);
}
}
/**
* @brief RTC GPIO pulldown disable.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
__attribute__((always_inline))
static inline void rtcio_ll_pulldown_disable(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].pulldown) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pulldown);
}
}
/**
* @brief Get RTC GPIO pad pulldown status.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @return Whether the pulldown of the pad is enabled or not.
*/
__attribute__((always_inline))
static inline bool rtcio_ll_is_pulldown_enabled(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].pulldown) {
return GET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].pulldown);
} else {
return false;
}
}
/**
* Enable force hold function on an RTC IO pad.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
* This function is useful when going into light or deep sleep mode to prevent
* the pin configuration from changing.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_force_hold_enable(int rtcio_num)
{
REG_SET_BIT(RTC_CNTL_HOLD_FORCE_REG, rtc_io_desc[rtcio_num].hold_force);
REG_SET_BIT(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].hold);
}
/**
* Disable hold function on an RTC IO pad.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_force_hold_disable(int rtcio_num)
{
REG_CLR_BIT(RTC_CNTL_HOLD_FORCE_REG, rtc_io_desc[rtcio_num].hold_force);
REG_CLR_BIT(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].hold);
}
/**
* Enable force hold function on all RTC IO pads.
*
* Enabling HOLD function will cause the pad to lock current status, such as,
* input/output enable, input/output value, function, drive strength values.
* This function is useful when going into light or deep sleep mode to prevent
* the pin configuration from changing.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_force_hold_all(void)
{
SET_PERI_REG_BITS(RTC_CNTL_HOLD_FORCE_REG, 0x3FFFF, 0x3FFFF, 0);
}
/**
* Disable hold function on all RTC IO pads.
*
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_force_unhold_all(void)
{
SET_PERI_REG_BITS(RTC_CNTL_HOLD_FORCE_REG, 0x3FFFF, 0, 0);
}
/**
* Enable wakeup function and set wakeup type from light sleep status for rtcio.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param type Wakeup on high level or low level.
*/
static inline void rtcio_ll_wakeup_enable(int rtcio_num, gpio_int_type_t type)
{
HAL_ASSERT(type == GPIO_INTR_LOW_LEVEL || type == GPIO_INTR_HIGH_LEVEL);
RTCIO.pin[rtcio_num].wakeup_enable = 1;
RTCIO.pin[rtcio_num].int_type = type;
}
/**
* Disable wakeup function from light sleep status for rtcio.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_wakeup_disable(int rtcio_num)
{
RTCIO.pin[rtcio_num].wakeup_enable = 0;
RTCIO.pin[rtcio_num].int_type = 0;
}
/**
* Enable rtc io output in deep sleep.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_enable_output_in_sleep(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].slpoe) {
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpoe);
}
}
/**
* Disable rtc io output in deep sleep.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_disable_output_in_sleep(int rtcio_num)
{
if (rtc_io_desc[rtcio_num].slpoe) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpoe);
}
}
/**
* Enable rtc io input in deep sleep.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_enable_input_in_sleep(int rtcio_num)
{
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpie);
}
/**
* Disable rtc io input in deep sleep.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_disable_input_in_sleep(int rtcio_num)
{
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpie);
}
/**
* Enable rtc io keep another setting in deep sleep.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_enable_sleep_setting(int rtcio_num)
{
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpsel);
}
/**
* Disable rtc io keep another setting in deep sleep. (Default)
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
*/
static inline void rtcio_ll_disable_sleep_setting(int rtcio_num)
{
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, rtc_io_desc[rtcio_num].slpsel);
}
/**
* Set specific logic level on an RTC IO pin as a ext0 wakeup trigger.
*
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
* @param level Logic level (0)
*/
static inline void rtcio_ll_ext0_set_wakeup_pin(int rtcio_num, int level)
{
REG_SET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL, rtcio_num);
// Set level which will trigger wakeup
SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1,
level , RTC_CNTL_EXT_WAKEUP0_LV_S);
}
#ifdef __cplusplus
}
#endif
-67
View File
@@ -1,67 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/gpio_sd_struct.h"
#include "soc/gpio_sd_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
// Get SDM register base address with giving group number
#define SDM_LL_GET_HW(group_id) ((group_id == 0) ? (&SDM) : NULL)
#define SDM_LL_PRESCALE_MAX (GPIO_SD0_PRESCALE_V + 1)
// Support APB as function clock
#define SDM_LL_FUNC_CLOCK_SUPPORT_APB 1
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sdm_ll_enable_clock(gpio_sd_dev_t *hw, bool en)
{
// The clk enable register does not exist on ESP32.
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param density Sigma-delta quantized density of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
__attribute__((always_inline))
static inline void sdm_ll_set_pulse_density(gpio_sd_dev_t *hw, int channel, int8_t density)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)density);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param prescale The divider of source clock, ranges from 1 to 256
*/
static inline void sdm_ll_set_prescale(gpio_sd_dev_t *hw, int channel, uint32_t prescale)
{
HAL_ASSERT(prescale && prescale <= SDM_LL_PRESCALE_MAX);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale - 1);
}
#ifdef __cplusplus
}
#endif