mirror of
https://github.com/espressif/esp-idf.git
synced 2026-05-04 11:55:21 +02:00
components/pm: Add slp gpio configure workaround
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The HAL layer for GPIO (common part)
|
||||
//
|
||||
#include "esp_attr.h"
|
||||
#include "soc/soc.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
|
||||
typedef struct gpio_slp_mode_cfg {
|
||||
volatile uint16_t fun_pu[((SOC_GPIO_PIN_COUNT-1) >> 4) + 1];
|
||||
volatile uint16_t fun_pd[((SOC_GPIO_PIN_COUNT-1) >> 4) + 1];
|
||||
} gpio_slp_mode_cfg_t;
|
||||
|
||||
static void gpio_hal_sleep_mode_setup_wrapper(
|
||||
gpio_hal_context_t *hal,
|
||||
gpio_num_t gpio_num,
|
||||
void (*opt)(gpio_hal_context_t *, gpio_num_t, void *)
|
||||
)
|
||||
{
|
||||
static DRAM_ATTR gpio_slp_mode_cfg_t gpio_cfg;
|
||||
if (opt) {
|
||||
(*opt)(hal, gpio_num, (void *)&gpio_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO pu/pd information backup function
|
||||
* @param hal gpio hal
|
||||
* @param gpio_num gpio num
|
||||
* @param args pointer for bitmap to backup GPIO pu/pd information
|
||||
*/
|
||||
static void gpio_hal_fun_pupd_backup(gpio_hal_context_t *hal, gpio_num_t gpio_num, void *args)
|
||||
{
|
||||
/* On ESP32, setting SLP_PU, SLP_PD couldn`t change GPIO status
|
||||
* from FUN_PU, FUN_PD to SLP_PU, SLP_PD at sleep.
|
||||
* On the ESP32S2, it does.
|
||||
* The following code emulates ESP32S2`s behavior:
|
||||
*/
|
||||
gpio_slp_mode_cfg_t *pcfg = (gpio_slp_mode_cfg_t *)args;
|
||||
|
||||
if (gpio_ll_sleep_sel_is_enabled(hal->dev, gpio_num)) {
|
||||
/* Record fun_pu and fun_pd state in bitmap */
|
||||
if (gpio_ll_pullup_is_enabled(hal->dev, gpio_num)) {
|
||||
pcfg->fun_pu[gpio_num >> 4] |= BIT(gpio_num & 0xf);
|
||||
} else {
|
||||
pcfg->fun_pu[gpio_num >> 4] &= ~BIT(gpio_num & 0xf);
|
||||
}
|
||||
if (gpio_ll_pulldown_is_enabled(hal->dev, gpio_num)) {
|
||||
pcfg->fun_pd[gpio_num >> 4] |= BIT(gpio_num & 0xf);
|
||||
} else {
|
||||
pcfg->fun_pd[gpio_num >> 4] &= ~BIT(gpio_num & 0xf);
|
||||
}
|
||||
|
||||
if (gpio_ll_sleep_pullup_is_enabled(hal->dev, gpio_num)) {
|
||||
gpio_ll_pullup_en(hal->dev, gpio_num);
|
||||
} else {
|
||||
gpio_ll_pullup_dis(hal->dev, gpio_num);
|
||||
}
|
||||
if (gpio_ll_sleep_pulldown_is_enabled(hal->dev, gpio_num)) {
|
||||
gpio_ll_pulldown_en(hal->dev, gpio_num);
|
||||
} else {
|
||||
gpio_ll_pulldown_dis(hal->dev, gpio_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO pu/pd information backup function
|
||||
* @param hal gpio hal
|
||||
* @param gpio_num gpio num
|
||||
* @param args pointer for bitmap to restore GPIO pu/pd information
|
||||
*/
|
||||
static void gpio_hal_fun_pupd_restore(gpio_hal_context_t *hal, gpio_num_t gpio_num, void *args)
|
||||
{
|
||||
/* On ESP32, setting SLP_PU, SLP_PD couldn`t change GPIO status
|
||||
* from SLP_PU, SLP_PD to FUN_PU, FUN_PD when it wakes up.
|
||||
* On the ESP32S2, it does.
|
||||
* The following code emulates ESP32S2`s behavior:
|
||||
*/
|
||||
gpio_slp_mode_cfg_t *pcfg = (gpio_slp_mode_cfg_t *)args;
|
||||
|
||||
if (gpio_ll_sleep_sel_is_enabled(hal->dev, gpio_num)) {
|
||||
if (pcfg->fun_pu[gpio_num >> 4] & BIT(gpio_num & 0xf)) {
|
||||
gpio_ll_pullup_en(hal->dev, gpio_num);
|
||||
} else {
|
||||
gpio_ll_pullup_dis(hal->dev, gpio_num);
|
||||
}
|
||||
if (pcfg->fun_pd[gpio_num >> 4] & BIT(gpio_num & 0xf)) {
|
||||
gpio_ll_pulldown_en(hal->dev, gpio_num);
|
||||
} else {
|
||||
gpio_ll_pulldown_dis(hal->dev, gpio_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_hal_sleep_pupd_config_apply(gpio_hal_context_t *hal, gpio_num_t gpio_num)
|
||||
{
|
||||
gpio_hal_sleep_mode_setup_wrapper(hal, gpio_num, gpio_hal_fun_pupd_backup);
|
||||
}
|
||||
|
||||
void gpio_hal_sleep_pupd_config_unapply(gpio_hal_context_t *hal, gpio_num_t gpio_num)
|
||||
{
|
||||
gpio_hal_sleep_mode_setup_wrapper(hal, gpio_num, gpio_hal_fun_pupd_restore);
|
||||
}
|
||||
#endif
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
@@ -63,6 +64,18 @@ static inline void gpio_ll_pullup_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
REG_CLR_BIT(GPIO_PIN_MUX_REG[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, gpio_num_t gpio_num)
|
||||
{
|
||||
return REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable pull-down on GPIO.
|
||||
*
|
||||
@@ -85,6 +98,120 @@ static inline void gpio_ll_pulldown_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
REG_CLR_BIT(GPIO_PIN_MUX_REG[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, gpio_num_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
|
||||
*/
|
||||
static inline void gpio_ll_sleep_sel_en(gpio_dev_t *hw, gpio_num_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
|
||||
*/
|
||||
static inline void gpio_ll_sleep_sel_dis(gpio_dev_t *hw, gpio_num_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
|
||||
*/
|
||||
static inline bool gpio_ll_sleep_sel_is_enabled(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
return REG_GET_BIT(GPIO_PIN_MUX_REG[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
|
||||
*/
|
||||
static inline void gpio_ll_sleep_pullup_dis(gpio_dev_t *hw, gpio_num_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
|
||||
*/
|
||||
static inline void gpio_ll_sleep_pullup_en(gpio_dev_t *hw, gpio_num_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
|
||||
*/
|
||||
static inline bool gpio_ll_sleep_pullup_is_enabled(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
return REG_GET_BIT(GPIO_PIN_MUX_REG[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
|
||||
*/
|
||||
static inline void gpio_ll_sleep_pulldown_en(gpio_dev_t *hw, gpio_num_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
|
||||
*/
|
||||
static inline void gpio_ll_sleep_pulldown_dis(gpio_dev_t *hw, gpio_num_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
|
||||
*/
|
||||
static inline bool gpio_ll_sleep_pulldown_is_enabled(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
return REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], SLP_PD) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO set interrupt trigger type
|
||||
*
|
||||
@@ -226,6 +353,50 @@ static inline void gpio_ll_output_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable GPIO input in sleep mode.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_sleep_input_disable(gpio_dev_t *hw, gpio_num_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
|
||||
*/
|
||||
static inline void gpio_ll_sleep_input_enable(gpio_dev_t *hw, gpio_num_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
|
||||
*/
|
||||
static inline void gpio_ll_sleep_output_disable(gpio_dev_t *hw, gpio_num_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
|
||||
*/
|
||||
static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
PIN_SLP_OUTPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable open-drain mode on GPIO.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user