mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
refactor(gpio): split GPIO HAL into separate component
cleaned up some includes in GPIO peripheral files
This commit is contained in:
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "riscv/csr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*fast gpio*/
|
||||
#define CSR_GPIO_OEN_USER 0x803
|
||||
#define CSR_GPIO_IN_USER 0x804
|
||||
#define CSR_GPIO_OUT_USER 0x805
|
||||
|
||||
/*!< The dedicated GPIO (a.k.a. fast GPIO) is featured by some customized CPU instructions, which is always enabled */
|
||||
#define DEDIC_GPIO_CPU_LL_PERIPH_ALWAYS_ENABLE 1
|
||||
|
||||
__attribute__((always_inline))
|
||||
static inline void dedic_gpio_cpu_ll_enable_output(uint32_t mask)
|
||||
{
|
||||
RV_WRITE_CSR(CSR_GPIO_OEN_USER, mask);
|
||||
}
|
||||
|
||||
static inline void dedic_gpio_cpu_ll_write_all(uint32_t value)
|
||||
{
|
||||
RV_WRITE_CSR(CSR_GPIO_OUT_USER, value);
|
||||
}
|
||||
|
||||
__attribute__((always_inline))
|
||||
static inline uint32_t dedic_gpio_cpu_ll_read_in(void)
|
||||
{
|
||||
uint32_t value = RV_READ_CSR(CSR_GPIO_IN_USER);
|
||||
return value;
|
||||
}
|
||||
|
||||
__attribute__((always_inline))
|
||||
static inline uint32_t dedic_gpio_cpu_ll_read_out(void)
|
||||
{
|
||||
uint32_t value = RV_READ_CSR(CSR_GPIO_OUT_USER);
|
||||
return value;
|
||||
}
|
||||
|
||||
__attribute__((always_inline))
|
||||
static inline void dedic_gpio_cpu_ll_write_mask(uint32_t mask, uint32_t value)
|
||||
{
|
||||
RV_SET_CSR(CSR_GPIO_OUT_USER, mask & value);
|
||||
RV_CLEAR_CSR(CSR_GPIO_OUT_USER, mask & ~(value));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "hal/assert.h"
|
||||
#include "hal/misc.h"
|
||||
#include "soc/gpio_ext_struct.h"
|
||||
#include "soc/soc_etm_source.h"
|
||||
|
||||
#define GPIO_LL_ETM_EVENT_ID_POS_EDGE(ch) (GPIO_EVT_CH0_RISE_EDGE + (ch))
|
||||
#define GPIO_LL_ETM_EVENT_ID_NEG_EDGE(ch) (GPIO_EVT_CH0_FALL_EDGE + (ch))
|
||||
#define GPIO_LL_ETM_EVENT_ID_ANY_EDGE(ch) (GPIO_EVT_CH0_ANY_EDGE + (ch))
|
||||
|
||||
#define GPIO_LL_ETM_TASK_ID_SET(ch) (GPIO_TASK_CH0_SET + (ch))
|
||||
#define GPIO_LL_ETM_TASK_ID_CLR(ch) (GPIO_TASK_CH0_CLEAR + (ch))
|
||||
#define GPIO_LL_ETM_TASK_ID_TOG(ch) (GPIO_TASK_CH0_TOGGLE + (ch))
|
||||
|
||||
#define GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP 8
|
||||
#define GPIO_LL_ETM_TASK_CHANNELS_PER_GROUP 8
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set which GPIO to be bound to the event channel
|
||||
*
|
||||
* @note Different channels can be bound to one GPIO
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan GPIO ETM Event channel number
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_etm_event_channel_set_gpio(gpio_etm_dev_t *dev, uint32_t chan, uint32_t gpio_num)
|
||||
{
|
||||
dev->etm_event_chn_cfg[chan].ext_etm_chn_event_sel = gpio_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Whether to enable the event channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan GPIO ETM Event channel number
|
||||
* @param enable True to enable, false to disable
|
||||
*/
|
||||
static inline void gpio_ll_etm_enable_event_channel(gpio_etm_dev_t *dev, uint32_t chan, bool enable)
|
||||
{
|
||||
dev->etm_event_chn_cfg[chan].ext_etm_chn_event_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get which GPIO is bound to the event channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan GPIO ETM Event channel number
|
||||
* @return GPIO number
|
||||
*/
|
||||
static inline uint32_t gpio_ll_etm_event_channel_get_gpio(gpio_etm_dev_t *dev, uint32_t chan)
|
||||
{
|
||||
return dev->etm_event_chn_cfg[chan].ext_etm_chn_event_sel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set which GPIO to be bound to the task channel
|
||||
*
|
||||
* @note One channel can be bound to multiple different GPIOs
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan GPIO ETM Task channel number
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_etm_gpio_set_task_channel(gpio_etm_dev_t *dev, uint32_t gpio_num, uint32_t chan)
|
||||
{
|
||||
int g_p = gpio_num / 5;
|
||||
int g_idx = gpio_num % 5;
|
||||
uint32_t reg_val = dev->etm_task_pn_cfg[g_p].val;
|
||||
reg_val &= ~(0x07 << (g_idx * 6));
|
||||
reg_val |= ((chan & 0x07) << (g_idx * 6));
|
||||
dev->etm_task_pn_cfg[g_p].val = reg_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Whether to enable the GPIO to be managed by the task channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param gpio_num GPIO number
|
||||
* @param enable True to enable, false to disable
|
||||
*/
|
||||
static inline void gpio_ll_etm_enable_task_gpio(gpio_etm_dev_t *dev, uint32_t gpio_num, bool enable)
|
||||
{
|
||||
int g_p = gpio_num / 5;
|
||||
int g_idx = gpio_num % 5;
|
||||
uint32_t reg_val = dev->etm_task_pn_cfg[g_p].val;
|
||||
reg_val &= ~(0x01 << (g_idx * 6 + 5));
|
||||
reg_val |= ((enable & 0x01) << (g_idx * 6 + 5));
|
||||
dev->etm_task_pn_cfg[g_p].val = reg_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether a GPIO has been enabled and managed by a task channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param gpio_num GPIO number
|
||||
* @return True if enabled, false otherwise
|
||||
*/
|
||||
static inline bool gpio_ll_etm_is_task_gpio_enabled(gpio_etm_dev_t *dev, uint32_t gpio_num)
|
||||
{
|
||||
int g_p = gpio_num / 5;
|
||||
int g_idx = gpio_num % 5;
|
||||
return dev->etm_task_pn_cfg[g_p].val & (0x01 << (g_idx * 6 + 5));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the channel number that the GPIO is bound to
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param gpio_num GPIO number
|
||||
* @return GPIO ETM Task channel number
|
||||
*/
|
||||
static inline uint32_t gpio_ll_etm_gpio_get_task_channel(gpio_etm_dev_t *dev, uint32_t gpio_num)
|
||||
{
|
||||
int g_p = gpio_num / 5;
|
||||
int g_idx = gpio_num % 5;
|
||||
return (dev->etm_task_pn_cfg[g_p].val >> (g_idx * 6)) & 0x07;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "hal/assert.h"
|
||||
#include "soc/gpio_ext_struct.h"
|
||||
|
||||
#define GPIO_LL_GLITCH_FILTER_MAX_WINDOW 64
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable GPIO glitch filter
|
||||
*
|
||||
* @param hw Glitch filter register base address
|
||||
* @param filter_idx Glitch filter index
|
||||
* @param enable True to enable, false to disable
|
||||
*/
|
||||
static inline void gpio_ll_glitch_filter_enable(gpio_glitch_filter_dev_t *hw, uint32_t filter_idx, bool enable)
|
||||
{
|
||||
hw->glitch_filter_chn[filter_idx].ext_filter_chn_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the input GPIO for the glitch filter
|
||||
*
|
||||
* @param hw Glitch filter register base address
|
||||
* @param filter_idx Glitch filter index
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_glitch_filter_set_gpio(gpio_glitch_filter_dev_t *hw, uint32_t filter_idx, uint32_t gpio_num)
|
||||
{
|
||||
hw->glitch_filter_chn[filter_idx].ext_filter_chn_input_io_num = gpio_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the coefficient of the glitch filter window
|
||||
*
|
||||
* @param hw Glitch filter register base address
|
||||
* @param filter_idx Glitch filter index
|
||||
* @param window_width Window width, in IOMUX clock ticks
|
||||
* @param window_threshold Window threshold, in IOMUX clock ticks
|
||||
*/
|
||||
static inline void gpio_ll_glitch_filter_set_window_coeff(gpio_glitch_filter_dev_t *hw, uint32_t filter_idx, uint32_t window_width, uint32_t window_thres)
|
||||
{
|
||||
HAL_ASSERT(window_thres <= window_width);
|
||||
hw->glitch_filter_chn[filter_idx].ext_filter_chn_window_width = window_width - 1;
|
||||
hw->glitch_filter_chn[filter_idx].ext_filter_chn_window_thres = window_thres - 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,738 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The LL layer for ESP32-H4 GPIO register operations
|
||||
* The hal is not public api, don't use in application code.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/gpio_struct.h"
|
||||
#include "soc/lp_aon_struct.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "soc/io_mux_struct.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/usb_serial_jtag_struct.h"
|
||||
#include "soc/usb_wrap_struct.h"
|
||||
#include "soc/pcr_struct.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "hal/misc.h"
|
||||
#include "hal/assert.h"
|
||||
#include "hal/config.h"
|
||||
#include "rom/gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Get GPIO hardware instance with giving gpio num
|
||||
#define GPIO_LL_GET_HW(num) (((num) == 0) ? (&GPIO) : NULL)
|
||||
|
||||
#define GPIO_LL_PRO_CPU_INTR_ENA (BIT(0))
|
||||
#define GPIO_LL_PRO_CPU_2_INTR_ENA (BIT(1))
|
||||
#define GPIO_LL_INTR_SOURCE0 ETS_GPIO_INTERRUPT_PRO_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;
|
||||
io_config->pu = IO_MUX.gpio[gpio_num].fun_wpu;
|
||||
io_config->pd = IO_MUX.gpio[gpio_num].fun_wpd;
|
||||
io_config->ie = IO_MUX.gpio[gpio_num].fun_ie;
|
||||
io_config->oe = (((gpio_num < 32) ? hw->enable.val : hw->enable1.val) & bit_mask) >> bit_shift;
|
||||
io_config->oe_ctrl_by_periph = !(hw->funcn_out_sel_cfg[gpio_num].oe_sel);
|
||||
io_config->oe_inv = hw->funcn_out_sel_cfg[gpio_num].oe_inv_sel;
|
||||
io_config->od = hw->pinn[gpio_num].pinn_pad_driver;
|
||||
io_config->drv = (gpio_drive_cap_t)IO_MUX.gpio[gpio_num].fun_drv;
|
||||
io_config->fun_sel = IO_MUX.gpio[gpio_num].mcu_sel;
|
||||
io_config->sig_out = hw->funcn_out_sel_cfg[gpio_num].out_sel;
|
||||
io_config->slp_sel = IO_MUX.gpio[gpio_num].slp_sel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].fun_wpu = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
// The pull-up value of the USB pins are controlled by the pins’ pull-up value together with USB pull-up value
|
||||
// USB DP pin is default to PU enabled
|
||||
// Note that esp32h4 has supported USB_EXCHG_PINS feature. If this efuse is burnt, the gpio pin
|
||||
// which should be checked is USB_INT_PHY0_DM_GPIO_NUM instead.
|
||||
// TODO: read the specific efuse with efuse_ll.h
|
||||
|
||||
// One more noticeable point is H4 has two internal PHYs connecting to USJ and USB_WRAP(OTG1.1) separately.
|
||||
// We only consider the default connection here: PHY0 -> USJ, PHY1 -> USB_OTG
|
||||
if (gpio_num == USB_USJ_INT_PHY_DP_GPIO_NUM) {
|
||||
USB_SERIAL_JTAG.serial_jtag_conf0.serial_jtag_pad_pull_override = 1;
|
||||
USB_SERIAL_JTAG.serial_jtag_conf0.serial_jtag_dp_pullup = 0;
|
||||
} else if (gpio_num == USB_OTG_INT_PHY_DP_GPIO_NUM) {
|
||||
USB_WRAP.wrap_otg_conf.wrap_pad_pull_override = 1;
|
||||
USB_WRAP.wrap_otg_conf.wrap_dp_pullup = 0;
|
||||
}
|
||||
|
||||
IO_MUX.gpio[gpio_num].fun_wpu = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].fun_wpd = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].fun_wpd = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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->pinn[gpio_num].pinn_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)
|
||||
{
|
||||
(void)core_id;
|
||||
*status = hw->procpu_int.procpu_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 = hw->procpu_int1.procpu_int1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.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)
|
||||
{
|
||||
hw->status1_w1tc.status1_w1tc = 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)
|
||||
{
|
||||
(void)core_id;
|
||||
GPIO.pinn[gpio_num].pinn_int_ena = GPIO_LL_PRO_CPU_INTR_ENA; //enable 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->pinn[gpio_num].pinn_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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].fun_ie = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable input mode on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].fun_ie = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable GPIO pin filter
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number of the pad.
|
||||
*/
|
||||
static inline void gpio_ll_pin_filter_enable(gpio_dev_t *hw, uint32_t gpio_num)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].filter_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable GPIO pin filter
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number of the pad.
|
||||
*/
|
||||
static inline void gpio_ll_pin_filter_disable(gpio_dev_t *hw, uint32_t gpio_num)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].filter_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.enable_w1tc = (0x1 << gpio_num);
|
||||
} else {
|
||||
hw->enable1_w1tc.enable1_w1tc = (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.enable_w1ts = (0x1 << gpio_num);
|
||||
} else {
|
||||
hw->enable1_w1ts.enable1_w1ts = (0x1 << (gpio_num - 32));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable open-drain mode on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_od_disable(gpio_dev_t *hw, uint32_t gpio_num)
|
||||
{
|
||||
hw->pinn[gpio_num].pinn_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->pinn[gpio_num].pinn_pad_driver = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 HAL_CONFIG(GPIO_USE_ROM_API)
|
||||
rom_gpio_set_output_level(gpio_num, level);
|
||||
#else
|
||||
if (level) {
|
||||
if (gpio_num < 32) {
|
||||
hw->out_w1ts.val = (1 << gpio_num);
|
||||
} else {
|
||||
hw->out1_w1ts.val = (1 << (gpio_num - 32));
|
||||
}
|
||||
} else {
|
||||
if (gpio_num < 32) {
|
||||
hw->out_w1tc.val = (1 << gpio_num);
|
||||
} else {
|
||||
hw->out1_w1tc.val = (1 << (gpio_num - 32));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 HAL_CONFIG(GPIO_USE_ROM_API)
|
||||
return rom_gpio_get_input_level(gpio_num);
|
||||
#else
|
||||
if (gpio_num < 32) {
|
||||
return (hw->in.in_data_next >> gpio_num) & 0x1;
|
||||
} else {
|
||||
return (hw->in1.in1_data_next >> (gpio_num - 32)) & 0x1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @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->pinn[gpio_num].pinn_wakeup_enable = 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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->pinn[gpio_num].pinn_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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].fun_drv = strength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)(IO_MUX.gpio[gpio_num].fun_drv);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
if (gpio_num < 32) {
|
||||
LP_AON.gpio_hold0.gpio_hold0 |= GPIO_HOLD_MASK[gpio_num];
|
||||
} else {
|
||||
LP_AON.gpio_hold1.gpio_hold1 |= 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)
|
||||
{
|
||||
if (gpio_num < 32) {
|
||||
LP_AON.gpio_hold0.gpio_hold0 &= ~GPIO_HOLD_MASK[gpio_num];
|
||||
} else {
|
||||
LP_AON.gpio_hold1.gpio_hold1 &= ~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)
|
||||
{
|
||||
if (gpio_num < 32) {
|
||||
return !!(LP_AON.gpio_hold0.gpio_hold0 & BIT(gpio_num));
|
||||
} else {
|
||||
return !!(LP_AON.gpio_hold1.gpio_hold1 & BIT(gpio_num - 32));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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_in_sel = gpio_num;
|
||||
hw->func_in_sel_cfg[signal_idx].func_in_inv_sel = 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)
|
||||
{
|
||||
gpio_func_in_sel_cfg_reg_t reg = {
|
||||
.val = hw->func_in_sel_cfg[in_sig_idx].val,
|
||||
};
|
||||
return (reg.sig_in_sel ? reg.func_in_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->funcn_out_sel_cfg[gpio_num].oe_inv_sel = oen_inv; // control valid only when using gpio matrix to route signal to the IO
|
||||
hw->funcn_out_sel_cfg[gpio_num].oe_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->funcn_out_sel_cfg[gpio_num].out_sel = signal_idx;
|
||||
hw->funcn_out_sel_cfg[gpio_num].out_inv_sel = out_inv;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
// Disable USB PHY configuration if pins (13, 14) (21, 22) needs to select an IOMUX function
|
||||
// P4 has two internal PHYs connecting to USJ and USB_WRAP(OTG1.1) separately.
|
||||
// We only consider the default connection here: PHY0 -> USJ, PHY1 -> USB_OTG
|
||||
if (gpio_num == USB_USJ_INT_PHY_DM_GPIO_NUM || gpio_num == USB_USJ_INT_PHY_DP_GPIO_NUM) {
|
||||
USB_SERIAL_JTAG.serial_jtag_conf0.serial_jtag_usb_pad_enable = 0;
|
||||
} else if (gpio_num == USB_OTG_INT_PHY_DM_GPIO_NUM || gpio_num == USB_OTG_INT_PHY_DP_GPIO_NUM) {
|
||||
USB_WRAP.wrap_otg_conf.wrap_usb_pad_enable = 0;
|
||||
}
|
||||
IO_MUX.gpio[gpio_num].mcu_sel = func;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set clock source of IO MUX module
|
||||
*
|
||||
* @param src IO MUX clock source (only a subset of soc_module_clk_t values are valid)
|
||||
*/
|
||||
static inline void gpio_ll_iomux_set_clk_src(soc_module_clk_t src)
|
||||
{
|
||||
switch (src) {
|
||||
case SOC_MOD_CLK_XTAL:
|
||||
PCR.iomux_clk_conf.iomux_func_clk_sel = 0;
|
||||
break;
|
||||
case SOC_MOD_CLK_RC_FAST:
|
||||
PCR.iomux_clk_conf.iomux_func_clk_sel = 1;
|
||||
break;
|
||||
case SOC_MOD_CLK_PLL_F48M:
|
||||
PCR.iomux_clk_conf.iomux_func_clk_sel = 2;
|
||||
break;
|
||||
default:
|
||||
// Unsupported IO_MUX clock source
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Force hold all digital(VDDPST2) and lp(VDDPST1) io pads.
|
||||
* @note GPIO force hold, whether the chip in sleep mode or wakeup mode.
|
||||
*/
|
||||
static inline void gpio_ll_force_hold_all(void)
|
||||
{
|
||||
// WT flags, they get self-cleared after the configuration is done
|
||||
PMU.imm.pad_hold_all.tie_high_hp_pad_hold_all = 1;
|
||||
PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Force unhold all digital(VDDPST2) and lp(VDDPST1) io pads.
|
||||
* @note GPIO force unhold, whether the chip in sleep mode or wakeup mode.
|
||||
*/
|
||||
static inline void gpio_ll_force_unhold_all(void)
|
||||
{
|
||||
// WT flags, they get self-cleared after the configuration is done
|
||||
PMU.imm.pad_hold_all.tie_low_hp_pad_hold_all = 1;
|
||||
PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable GPIO pin to use sleep mode pin functions during light 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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].slp_sel = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable GPIO pin to use sleep mode pin functions during light sleep.
|
||||
* Pin functions remains the same in both normal execution and in light-sleep mode.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].slp_sel = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].mcu_wpu = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].mcu_wpu = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].mcu_wpd = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].mcu_wpd = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].mcu_ie = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].mcu_ie = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].mcu_oe = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
IO_MUX.gpio[gpio_num].mcu_oe = 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,447 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 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 <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/pcr_struct.h"
|
||||
#include "soc/lp_iomux_struct.h"
|
||||
#include "soc/lp_aon_struct.h"
|
||||
#include "soc/lp_gpio_struct.h"
|
||||
#include "soc/lpperi_struct.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "hal/misc.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RTCIO_LL_PIN_FUNC 1
|
||||
|
||||
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)
|
||||
{
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_mcu_sel = func;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable LP_GPIO peripheral clock.
|
||||
*
|
||||
* @param enable true to enable the clock / false to disable the clock
|
||||
*/
|
||||
static inline void _rtcio_ll_enable_io_clock(bool enable)
|
||||
{
|
||||
LPPERI.clk_en.lp_io_ck_en = enable;
|
||||
while (LPPERI.clk_en.lp_io_ck_en != enable) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
#define rtcio_ll_enable_io_clock(...) do { \
|
||||
(void)__DECLARE_RCC_ATOMIC_ENV; \
|
||||
_rtcio_ll_enable_io_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Select the rtcio function.
|
||||
*
|
||||
* @note The RTC function must be selected before the pad analog function is enabled.
|
||||
* @note The clock gating 'PCR.iomux_conf.iomux_clk_en' is the gate of both 'lp_io' and 'etm_gpio'
|
||||
* And it's default to be turned on, so we don't need to operate this clock gate here additionally
|
||||
*
|
||||
* @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.
|
||||
uint32_t sel_mask = LP_AON.gpio_mux.gpio_mux_sel;
|
||||
sel_mask |= BIT(rtcio_num);
|
||||
LP_AON.gpio_mux.gpio_mux_sel = sel_mask;
|
||||
// LP_GPIO is FUNC 1
|
||||
rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC);
|
||||
} else if (func == RTCIO_LL_FUNC_DIGITAL) {
|
||||
// Clear the bit to use digital GPIO module
|
||||
uint32_t sel_mask = LP_AON.gpio_mux.gpio_mux_sel;
|
||||
sel_mask &= ~BIT(rtcio_num);
|
||||
LP_AON.gpio_mux.gpio_mux_sel = sel_mask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable rtcio output.
|
||||
*
|
||||
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
|
||||
*/
|
||||
static inline void rtcio_ll_output_enable(int rtcio_num)
|
||||
{
|
||||
LP_GPIO.enable_w1ts.val = BIT(rtcio_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable rtcio output.
|
||||
*
|
||||
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
|
||||
*/
|
||||
static inline void rtcio_ll_output_disable(int rtcio_num)
|
||||
{
|
||||
LP_GPIO.enable_w1tc.val = BIT(rtcio_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 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) {
|
||||
LP_GPIO.out_w1ts.val = BIT(rtcio_num);
|
||||
} else {
|
||||
LP_GPIO.out_w1tc.val = BIT(rtcio_num);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable rtcio input.
|
||||
*
|
||||
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
|
||||
*/
|
||||
static inline void rtcio_ll_input_enable(int rtcio_num)
|
||||
{
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_fun_ie = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable rtcio input.
|
||||
*
|
||||
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
|
||||
*/
|
||||
static inline void rtcio_ll_input_disable(int rtcio_num)
|
||||
{
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_fun_ie = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 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 (LP_GPIO.in.in_data_next >> 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)
|
||||
{
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_fun_drv = strength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 LP_IO_MUX.gpion[rtcio_num].gpion_fun_drv;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
LP_GPIO.pinn[rtcio_num].pinn_pad_driver = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTC GPIO pullup enable.
|
||||
*
|
||||
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
|
||||
*/
|
||||
static inline void rtcio_ll_pullup_enable(int rtcio_num)
|
||||
{
|
||||
/* Enable internal weak pull-up */
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_fun_wpu = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTC GPIO pullup disable.
|
||||
*
|
||||
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
|
||||
*/
|
||||
static inline void rtcio_ll_pullup_disable(int rtcio_num)
|
||||
{
|
||||
/* Disable internal weak pull-up */
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_fun_wpu = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
static inline bool rtcio_ll_is_pullup_enabled(int rtcio_num)
|
||||
{
|
||||
return LP_IO_MUX.gpion[rtcio_num].gpion_fun_wpu;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTC GPIO pulldown enable.
|
||||
*
|
||||
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
|
||||
*/
|
||||
static inline void rtcio_ll_pulldown_enable(int rtcio_num)
|
||||
{
|
||||
/* Enable internal weak pull-down */
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_fun_wpd = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTC GPIO pulldown disable.
|
||||
*
|
||||
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
|
||||
*/
|
||||
static inline void rtcio_ll_pulldown_disable(int rtcio_num)
|
||||
{
|
||||
/* Enable internal weak pull-down */
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_fun_wpd = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
static inline bool rtcio_ll_is_pulldown_enabled(int rtcio_num)
|
||||
{
|
||||
return LP_IO_MUX.gpion[rtcio_num].gpion_fun_wpd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable force hold function for 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)
|
||||
{
|
||||
LP_AON.gpio_hold0.gpio_hold0 |= BIT(rtcio_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 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)
|
||||
{
|
||||
LP_AON.gpio_hold0.gpio_hold0 &= ~BIT(rtcio_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable force hold function for 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.
|
||||
*/
|
||||
static inline void rtcio_ll_force_hold_all(void)
|
||||
{
|
||||
PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable hold function fon all RTC IO pads
|
||||
*
|
||||
* @note If disable the pad hold, the status of pad maybe changed in sleep mode.
|
||||
*/
|
||||
static inline void rtcio_ll_force_unhold_all(void)
|
||||
{
|
||||
PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable wakeup function and set wakeup type from light sleep or deep sleep 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)
|
||||
{
|
||||
LP_GPIO.pinn[rtcio_num].pinn_wakeup_enable = 1;
|
||||
LP_GPIO.pinn[rtcio_num].pinn_int_type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable wakeup function from light sleep or deep sleep for rtcio.
|
||||
*
|
||||
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
|
||||
*/
|
||||
static inline void rtcio_ll_wakeup_disable(int rtcio_num)
|
||||
{
|
||||
LP_GPIO.pinn[rtcio_num].pinn_wakeup_enable = 0;
|
||||
LP_GPIO.pinn[rtcio_num].pinn_int_type = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt function and set interrupt type
|
||||
*
|
||||
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
|
||||
* @param type Interrupt type on high level or low level.
|
||||
*/
|
||||
|
||||
static inline void rtcio_ll_intr_enable(int rtcio_num, gpio_int_type_t type)
|
||||
{
|
||||
LP_GPIO.pinn[rtcio_num].pinn_int_type = type;
|
||||
|
||||
/* Work around for HW issue,
|
||||
need to also enable this clk, so that LP_GPIO.status.status_interrupt can get updated,
|
||||
and trigger the interrupt on the LP Core
|
||||
*/
|
||||
LP_GPIO.clock_gate.clk_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 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)
|
||||
{
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_mcu_oe = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 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)
|
||||
{
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_mcu_oe = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 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)
|
||||
{
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_mcu_ie = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 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)
|
||||
{
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_mcu_ie = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 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)
|
||||
{
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_slp_sel = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 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)
|
||||
{
|
||||
LP_IO_MUX.gpion[rtcio_num].gpion_slp_sel = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the status of whether an IO is used for sleep wake-up.
|
||||
*
|
||||
* @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
|
||||
* @return True if the pin is enabled to wake up from deep-sleep
|
||||
*/
|
||||
static inline bool rtcio_ll_wakeup_is_enabled(int rtcio_num)
|
||||
{
|
||||
HAL_ASSERT(rtcio_num >= 0 && rtcio_num < SOC_RTCIO_PIN_COUNT && "io does not support deep sleep wake-up function");
|
||||
return LP_GPIO.pinn[rtcio_num].pinn_wakeup_enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the rtc io interrupt status
|
||||
*
|
||||
* @return bit 0~5 corresponding to 0 ~ SOC_RTCIO_PIN_COUNT.
|
||||
*/
|
||||
static inline uint32_t rtcio_ll_get_interrupt_status(void)
|
||||
{
|
||||
return LP_GPIO.status.status_interrupt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear all LP IO pads status
|
||||
*/
|
||||
static inline void rtcio_ll_clear_interrupt_status(void)
|
||||
{
|
||||
LP_GPIO.status_w1tc.val = 0x3F;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 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_ext_struct.h"
|
||||
#include "soc/gpio_ext_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_EXT_SD0_PRESCALE_V + 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)
|
||||
{
|
||||
hw->misc.ext_sigmadelta_clk_en = en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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], ext_sdn_in, (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], ext_sdn_prescale, prescale - 1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user