mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feat/esp_ldo_regulator_public_api' into 'master'
Introduce esp ldo regulator public API See merge request espressif/esp-idf!29691
This commit is contained in:
commit
52137a2b55
@ -19,7 +19,6 @@
|
|||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "driver/sdmmc_host.h"
|
#include "driver/sdmmc_host.h"
|
||||||
#include "esp_private/periph_ctrl.h"
|
#include "esp_private/periph_ctrl.h"
|
||||||
#include "esp_private/esp_ldo.h"
|
|
||||||
#include "sdmmc_private.h"
|
#include "sdmmc_private.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
@ -55,7 +54,6 @@ typedef struct slot_ctx_t {
|
|||||||
size_t slot_width;
|
size_t slot_width;
|
||||||
sdmmc_slot_io_info_t slot_gpio_num;
|
sdmmc_slot_io_info_t slot_gpio_num;
|
||||||
bool use_gpio_matrix;
|
bool use_gpio_matrix;
|
||||||
esp_ldo_unit_handle_t ldo_unit;
|
|
||||||
} slot_ctx_t;
|
} slot_ctx_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,7 +39,7 @@ void sdmmc_test_board_get_config_sdmmc(int slot_index, sdmmc_host_t *out_host_co
|
|||||||
#define SDMMC_PWR_LDO_CHANNEL 4
|
#define SDMMC_PWR_LDO_CHANNEL 4
|
||||||
|
|
||||||
sd_pwr_ctrl_ldo_config_t ldo_config = {
|
sd_pwr_ctrl_ldo_config_t ldo_config = {
|
||||||
.ldo_unit_id = SDMMC_PWR_LDO_CHANNEL,
|
.ldo_chan_id = SDMMC_PWR_LDO_CHANNEL,
|
||||||
};
|
};
|
||||||
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
|
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
|
||||||
|
|
||||||
|
@ -73,11 +73,8 @@ if(NOT BOOTLOADER_BUILD)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_MULTI_USAGE_LDO_SUPPORTED)
|
if(CONFIG_SOC_GP_LDO_SUPPORTED)
|
||||||
list(APPEND srcs "ldo/esp_ldo.c")
|
list(APPEND srcs "ldo/esp_ldo.c" "ldo/esp_ldo_regulator.c")
|
||||||
if(CONFIG_SPIRAM OR CONFIG_SOC_CLK_MPLL_SUPPORTED)
|
|
||||||
list(APPEND srcs "ldo/esp_ldo_psram.c")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED)
|
if(CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED)
|
||||||
@ -168,7 +165,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
INCLUDE_DIRS include include/soc include/soc/${target} dma/include
|
INCLUDE_DIRS include include/soc include/soc/${target} dma/include ldo/include
|
||||||
PRIV_INCLUDE_DIRS port/include include/esp_private
|
PRIV_INCLUDE_DIRS port/include include/esp_private
|
||||||
REQUIRES ${requires}
|
REQUIRES ${requires}
|
||||||
PRIV_REQUIRES "${priv_requires}"
|
PRIV_REQUIRES "${priv_requires}"
|
||||||
|
@ -331,10 +331,7 @@ menu "Hardware Settings"
|
|||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
menu "LDO Config"
|
orsource "./port/$IDF_TARGET/Kconfig.ldo"
|
||||||
depends on SOC_MULTI_USAGE_LDO_SUPPORTED
|
|
||||||
orsource "./port/$IDF_TARGET/Kconfig.ldo"
|
|
||||||
endmenu
|
|
||||||
|
|
||||||
# Invisible bringup bypass options for esp_hw_support component
|
# Invisible bringup bypass options for esp_hw_support component
|
||||||
config ESP_BRINGUP_BYPASS_CPU_CLK_SETTING
|
config ESP_BRINGUP_BYPASS_CPU_CLK_SETTING
|
||||||
|
@ -7,11 +7,11 @@
|
|||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include "clk_ctrl_os.h"
|
#include "clk_ctrl_os.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
|
#include "esp_ldo_regulator.h"
|
||||||
#include "esp_private/esp_clk_tree_common.h"
|
#include "esp_private/esp_clk_tree_common.h"
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#if SOC_CLK_MPLL_SUPPORTED
|
#if SOC_CLK_MPLL_SUPPORTED
|
||||||
#include "rtc_clk.h"
|
#include "rtc_clk.h"
|
||||||
#include "esp_private/esp_ldo_psram.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SOC_CLK_APLL_SUPPORTED || SOC_CLK_MPLL_SUPPORTED
|
#if SOC_CLK_APLL_SUPPORTED || SOC_CLK_MPLL_SUPPORTED
|
||||||
@ -30,7 +30,7 @@ static int s_apll_ref_cnt = 0;
|
|||||||
#if SOC_CLK_MPLL_SUPPORTED
|
#if SOC_CLK_MPLL_SUPPORTED
|
||||||
static uint32_t s_cur_mpll_freq = 0;
|
static uint32_t s_cur_mpll_freq = 0;
|
||||||
static int s_mpll_ref_cnt = 0;
|
static int s_mpll_ref_cnt = 0;
|
||||||
static esp_ldo_unit_handle_t s_ldo_unit_hndl = NULL;
|
static esp_ldo_channel_handle_t s_ldo_chan = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool periph_rtc_dig_clk8m_enable(void)
|
bool periph_rtc_dig_clk8m_enable(void)
|
||||||
@ -125,7 +125,7 @@ esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq, uint32_t *real_freq)
|
|||||||
|
|
||||||
if (need_config) {
|
if (need_config) {
|
||||||
ESP_LOGD(TAG, "APLL will working at %"PRIu32" Hz with coefficients [sdm0] %"PRIu32" [sdm1] %"PRIu32" [sdm2] %"PRIu32" [o_div] %"PRIu32"",
|
ESP_LOGD(TAG, "APLL will working at %"PRIu32" Hz with coefficients [sdm0] %"PRIu32" [sdm1] %"PRIu32" [sdm2] %"PRIu32" [o_div] %"PRIu32"",
|
||||||
apll_freq, sdm0, sdm1, sdm2, o_div);
|
apll_freq, sdm0, sdm1, sdm2, o_div);
|
||||||
/* Set coefficients for APLL, notice that it doesn't mean APLL will start */
|
/* Set coefficients for APLL, notice that it doesn't mean APLL will start */
|
||||||
rtc_clk_apll_coeff_set(o_div, sdm0, sdm1, sdm2);
|
rtc_clk_apll_coeff_set(o_div, sdm0, sdm1, sdm2);
|
||||||
} else {
|
} else {
|
||||||
@ -137,51 +137,34 @@ esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq, uint32_t *real_freq)
|
|||||||
#endif // SOC_CLK_APLL_SUPPORTED
|
#endif // SOC_CLK_APLL_SUPPORTED
|
||||||
|
|
||||||
#if SOC_CLK_MPLL_SUPPORTED
|
#if SOC_CLK_MPLL_SUPPORTED
|
||||||
void periph_rtc_mpll_early_acquire(void)
|
|
||||||
{
|
|
||||||
portENTER_CRITICAL(&periph_spinlock);
|
|
||||||
s_mpll_ref_cnt++;
|
|
||||||
if (s_mpll_ref_cnt == 1) {
|
|
||||||
#if SOC_PSRAM_VDD_POWER_MPLL
|
|
||||||
// configure MPPL power (MPLL power pin is the same as for the PSRAM)
|
|
||||||
s_ldo_unit_hndl = esp_ldo_vdd_psram_early_init();
|
|
||||||
#endif
|
|
||||||
// For the first time enable MPLL, need to set power up
|
|
||||||
rtc_clk_mpll_enable();
|
|
||||||
}
|
|
||||||
portEXIT_CRITICAL(&periph_spinlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t periph_rtc_mpll_acquire(void)
|
esp_err_t periph_rtc_mpll_acquire(void)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
// power up LDO for the MPLL
|
||||||
|
#if defined(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN) && CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN != -1
|
||||||
|
esp_ldo_channel_config_t ldo_mpll_config = {
|
||||||
|
.chan_id = CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN,
|
||||||
|
.voltage_mv = CONFIG_ESP_LDO_VOLTAGE_PSRAM_DOMAIN,
|
||||||
|
};
|
||||||
|
ESP_RETURN_ON_ERROR(esp_ldo_acquire_channel(&ldo_mpll_config, &s_ldo_chan), TAG, "acquire internal LDO for MPLL failed");
|
||||||
|
#endif
|
||||||
|
|
||||||
portENTER_CRITICAL(&periph_spinlock);
|
portENTER_CRITICAL(&periph_spinlock);
|
||||||
s_mpll_ref_cnt++;
|
s_mpll_ref_cnt++;
|
||||||
if (s_mpll_ref_cnt == 1) {
|
if (s_mpll_ref_cnt == 1) {
|
||||||
#if SOC_PSRAM_VDD_POWER_MPLL
|
|
||||||
// configure MPPL power (MPLL power pin is the same as for the PSRAM)
|
|
||||||
ret = esp_ldo_vdd_psram_init(&s_ldo_unit_hndl);
|
|
||||||
// external power supply in use is a valid condition
|
|
||||||
if (ret == ESP_ERR_INVALID_STATE) {
|
|
||||||
ret = ESP_OK;
|
|
||||||
} else if (ret != ESP_OK ) {
|
|
||||||
portEXIT_CRITICAL(&periph_spinlock);
|
|
||||||
ESP_LOGE(TAG, "failed to initialize PSRAM internal LDO");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// For the first time enable MPLL, need to set power up
|
// For the first time enable MPLL, need to set power up
|
||||||
rtc_clk_mpll_enable();
|
rtc_clk_mpll_enable();
|
||||||
}
|
}
|
||||||
portEXIT_CRITICAL(&periph_spinlock);
|
portEXIT_CRITICAL(&periph_spinlock);
|
||||||
#if SOC_PSRAM_VDD_POWER_MPLL
|
return ESP_OK;
|
||||||
err:
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void periph_rtc_mpll_release(void)
|
void periph_rtc_mpll_release(void)
|
||||||
{
|
{
|
||||||
|
#if defined(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN) && CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN != -1
|
||||||
|
if (s_ldo_chan) {
|
||||||
|
esp_ldo_release_channel(s_ldo_chan);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
portENTER_CRITICAL(&periph_spinlock);
|
portENTER_CRITICAL(&periph_spinlock);
|
||||||
assert(s_mpll_ref_cnt > 0);
|
assert(s_mpll_ref_cnt > 0);
|
||||||
s_mpll_ref_cnt--;
|
s_mpll_ref_cnt--;
|
||||||
@ -189,11 +172,6 @@ void periph_rtc_mpll_release(void)
|
|||||||
// If there is no peripheral using MPLL, shut down the power
|
// If there is no peripheral using MPLL, shut down the power
|
||||||
s_cur_mpll_freq = 0;
|
s_cur_mpll_freq = 0;
|
||||||
rtc_clk_mpll_disable();
|
rtc_clk_mpll_disable();
|
||||||
#if SOC_PSRAM_VDD_POWER_MPLL
|
|
||||||
if (s_ldo_unit_hndl) {
|
|
||||||
esp_ldo_vdd_psram_deinit(s_ldo_unit_hndl);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
portEXIT_CRITICAL(&periph_spinlock);
|
portEXIT_CRITICAL(&periph_spinlock);
|
||||||
}
|
}
|
||||||
|
@ -73,11 +73,6 @@ esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq, uint32_t *real_freq);
|
|||||||
#endif // SOC_CLK_APLL_SUPPORTED
|
#endif // SOC_CLK_APLL_SUPPORTED
|
||||||
|
|
||||||
#if SOC_CLK_MPLL_SUPPORTED
|
#if SOC_CLK_MPLL_SUPPORTED
|
||||||
/**
|
|
||||||
* @brief Enable MPLL power if it has not enabled (early version)
|
|
||||||
*/
|
|
||||||
void periph_rtc_mpll_early_acquire(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enable MPLL power if it has not enabled
|
* @brief Enable MPLL power if it has not enabled
|
||||||
*/
|
*/
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_private/esp_ldo.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Init PSRAM VDD LDO during early stage
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - LDO unit handle on success
|
|
||||||
* - NULL when external power supply is configured to be used
|
|
||||||
*/
|
|
||||||
esp_ldo_unit_handle_t esp_ldo_vdd_psram_early_init(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Init PSRAM VDD LDO
|
|
||||||
*
|
|
||||||
* @param[out] ldo_unit LDO unit handle
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - ESP_OK Successful.
|
|
||||||
* - ESP_ERR_INVALID_STATE External power supply is configured to be used
|
|
||||||
* - ESP_ERR_INVALID_ARG Arguments is NULL or invalid LDO configuration.
|
|
||||||
* - other error codes from lower-level driver.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
esp_err_t esp_ldo_vdd_psram_init(esp_ldo_unit_handle_t *ldo_unit);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief De-init PSRAM VDD LDO
|
|
||||||
*
|
|
||||||
* @param[in] ldo_unit LDO unit handle
|
|
||||||
*/
|
|
||||||
esp_err_t esp_ldo_vdd_psram_deinit(esp_ldo_unit_handle_t ldo_unit);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "esp_attr.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "soc/soc_caps.h"
|
|
||||||
#include "hal/ldo_ll.h"
|
|
||||||
#include "esp_private/esp_ldo_psram.h"
|
|
||||||
|
|
||||||
static const char *TAG = "ldo_psram";
|
|
||||||
|
|
||||||
esp_ldo_unit_handle_t esp_ldo_vdd_psram_early_init(void)
|
|
||||||
{
|
|
||||||
if (CONFIG_ESP_VDD_PSRAM_LDO_ID != -1) {
|
|
||||||
esp_ldo_unit_init_cfg_t unit_cfg = {
|
|
||||||
.unit_id = CONFIG_ESP_VDD_PSRAM_LDO_ID,
|
|
||||||
.cfg = {
|
|
||||||
.voltage_mv = CONFIG_ESP_VDD_PSRAM_LDO_VOLTAGE_MV,
|
|
||||||
},
|
|
||||||
.flags.enable_unit = true,
|
|
||||||
.flags.shared_ldo = true,
|
|
||||||
};
|
|
||||||
esp_ldo_unit_handle_t early_unit = esp_ldo_init_unit_early(&unit_cfg);
|
|
||||||
assert(early_unit);
|
|
||||||
return early_unit;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_ldo_vdd_psram_init(esp_ldo_unit_handle_t *ldo_unit)
|
|
||||||
{
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
ESP_RETURN_ON_FALSE(ldo_unit, ESP_ERR_INVALID_ARG, TAG, "null pointer");
|
|
||||||
if (CONFIG_ESP_VDD_PSRAM_LDO_ID != -1) {
|
|
||||||
esp_ldo_unit_init_cfg_t unit_cfg = {
|
|
||||||
.unit_id = LDO_ID2UNIT(CONFIG_ESP_VDD_PSRAM_LDO_ID),
|
|
||||||
.cfg = {
|
|
||||||
.voltage_mv = CONFIG_ESP_VDD_PSRAM_LDO_VOLTAGE_MV,
|
|
||||||
},
|
|
||||||
.flags.enable_unit = true,
|
|
||||||
.flags.shared_ldo = true,
|
|
||||||
};
|
|
||||||
ESP_RETURN_ON_ERROR(esp_ldo_init_unit(&unit_cfg, ldo_unit), TAG, "internal LDO init failed");
|
|
||||||
} else {
|
|
||||||
ESP_LOGD(TAG, "internal LDO not initialized, external power supply is configured to be used");
|
|
||||||
*ldo_unit = NULL;
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_ldo_vdd_psram_deinit(esp_ldo_unit_handle_t ldo_unit)
|
|
||||||
{
|
|
||||||
return esp_ldo_deinit_unit(ldo_unit);
|
|
||||||
}
|
|
169
components/esp_hw_support/ldo/esp_ldo_regulator.c
Normal file
169
components/esp_hw_support/ldo/esp_ldo_regulator.c
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
#include "hal/ldo_ll.h"
|
||||||
|
#include "esp_ldo_regulator.h"
|
||||||
|
|
||||||
|
static const char *TAG = "ldo";
|
||||||
|
|
||||||
|
typedef struct ldo_regulator_channel_t {
|
||||||
|
int chan_id;
|
||||||
|
int voltage_mv;
|
||||||
|
int ref_cnt;
|
||||||
|
struct {
|
||||||
|
uint32_t adjustable : 1;
|
||||||
|
} flags;
|
||||||
|
} ldo_regulator_channel_t;
|
||||||
|
|
||||||
|
static portMUX_TYPE s_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
||||||
|
static const uint32_t s_ldo_channel_adjustable_mask = LDO_LL_ADJUSTABLE_CHAN_MASK; // each bit represents if the LDO channel is adjustable in hardware
|
||||||
|
|
||||||
|
static ldo_regulator_channel_t s_ldo_channels[LDO_LL_UNIT_NUM] = {
|
||||||
|
[0 ... LDO_LL_UNIT_NUM - 1] = {
|
||||||
|
.chan_id = -1,
|
||||||
|
.voltage_mv = 0,
|
||||||
|
.ref_cnt = 0,
|
||||||
|
.flags.adjustable = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
esp_err_t esp_ldo_acquire_channel(const esp_ldo_channel_config_t *config, esp_ldo_channel_handle_t *out_handle)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||||
|
ESP_RETURN_ON_FALSE(ldo_ll_is_valid_ldo_id(config->chan_id), ESP_ERR_INVALID_ARG, TAG, "invalid ldo channel ID");
|
||||||
|
ESP_RETURN_ON_FALSE(config->voltage_mv <= LDO_LL_MAX_VOLTAGE_MV,
|
||||||
|
ESP_ERR_INVALID_ARG, TAG, "invalid voltage value: %d", config->voltage_mv);
|
||||||
|
int unit_id = LDO_ID2UNIT(config->chan_id);
|
||||||
|
ldo_regulator_channel_t *channel = &s_ldo_channels[unit_id];
|
||||||
|
|
||||||
|
bool check_adjustable_constraint_valid = true;
|
||||||
|
bool check_voltage_constraint_valid = true;
|
||||||
|
portENTER_CRITICAL(&s_spinlock);
|
||||||
|
if (config->flags.adjustable) {
|
||||||
|
// the user wants to adjust it
|
||||||
|
// but the channel is marked as not adjustable
|
||||||
|
if (channel->flags.adjustable == 0) {
|
||||||
|
check_adjustable_constraint_valid = false;
|
||||||
|
} else if (channel->ref_cnt != 0) {
|
||||||
|
// or the channel is already in use by others
|
||||||
|
// but we don't allow different users to adjust the same LDO, in case they set to different voltages
|
||||||
|
// that's to say, if the LDO channel is adjustable, it can only have one reference
|
||||||
|
check_adjustable_constraint_valid = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// the user doesn't want to adjust the voltage
|
||||||
|
// but the channel is already in use by others
|
||||||
|
if (channel->ref_cnt != 0) {
|
||||||
|
if (channel->flags.adjustable) {
|
||||||
|
// we don't allow to have another non-adjustable user
|
||||||
|
check_adjustable_constraint_valid = false;
|
||||||
|
} else if (channel->voltage_mv != config->voltage_mv) {
|
||||||
|
// the voltage is different from us
|
||||||
|
check_voltage_constraint_valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (check_voltage_constraint_valid && check_adjustable_constraint_valid) {
|
||||||
|
if (channel->ref_cnt == 0) {
|
||||||
|
// if the channel is not in use, we need to set the voltage and enable it
|
||||||
|
ldo_ll_set_output_voltage_mv(unit_id, config->voltage_mv);
|
||||||
|
ldo_ll_enable(unit_id, true);
|
||||||
|
}
|
||||||
|
// update the channel attributes
|
||||||
|
channel->ref_cnt++;
|
||||||
|
channel->voltage_mv = config->voltage_mv;
|
||||||
|
channel->flags.adjustable = config->flags.adjustable;
|
||||||
|
channel->chan_id = config->chan_id;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL(&s_spinlock);
|
||||||
|
|
||||||
|
ESP_RETURN_ON_FALSE(check_voltage_constraint_valid, ESP_ERR_INVALID_ARG, TAG,
|
||||||
|
"can't change the voltage for a non-adjustable channel, expect:%dmV, current:%dmV",
|
||||||
|
config->voltage_mv, channel->voltage_mv);
|
||||||
|
ESP_RETURN_ON_FALSE(check_adjustable_constraint_valid, ESP_ERR_INVALID_ARG, TAG,
|
||||||
|
"can't acquire the channel, already in use by others or not adjustable");
|
||||||
|
|
||||||
|
if (out_handle) {
|
||||||
|
*out_handle = channel;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_ldo_release_channel(esp_ldo_channel_handle_t chan)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||||
|
int unit_id = LDO_ID2UNIT(chan->chan_id);
|
||||||
|
|
||||||
|
bool is_valid_state = true;
|
||||||
|
portENTER_CRITICAL(&s_spinlock);
|
||||||
|
if (chan->ref_cnt <= 0) {
|
||||||
|
is_valid_state = false;
|
||||||
|
} else {
|
||||||
|
chan->ref_cnt--;
|
||||||
|
if (chan->ref_cnt == 0) {
|
||||||
|
// if the channel is not in use, we need to disable it
|
||||||
|
ldo_ll_enable(unit_id, false);
|
||||||
|
// and reset the ldo voltage
|
||||||
|
chan->voltage_mv = 0;
|
||||||
|
chan->flags.adjustable = (s_ldo_channel_adjustable_mask & (1 << unit_id)) != 0;
|
||||||
|
chan->chan_id = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL(&s_spinlock);
|
||||||
|
|
||||||
|
ESP_RETURN_ON_FALSE(is_valid_state, ESP_ERR_INVALID_STATE, TAG, "LDO channel released too many times");
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_ldo_channel_adjust_voltage(esp_ldo_channel_handle_t chan, int voltage_mv)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||||
|
ESP_RETURN_ON_FALSE(chan->flags.adjustable, ESP_ERR_NOT_SUPPORTED, TAG, "LDO is not adjustable");
|
||||||
|
// check if the voltage is within the valid range
|
||||||
|
ESP_RETURN_ON_FALSE(voltage_mv >= LDO_LL_MIN_VOLTAGE_MV && voltage_mv <= LDO_LL_MAX_VOLTAGE_MV,
|
||||||
|
ESP_ERR_INVALID_ARG, TAG, "invalid voltage value: %d", voltage_mv);
|
||||||
|
|
||||||
|
// About Thread Safety:
|
||||||
|
// because there won't be more than 1 consumer for the same adjustable LDO channel (guaranteed by esp_ldo_acquire_channel)
|
||||||
|
// this function should be thread safe as long as the LDO channel handle is thread safe,
|
||||||
|
// i.e., the handle is not shared between threads without mutex protection
|
||||||
|
chan->voltage_mv = voltage_mv;
|
||||||
|
int unit_id = LDO_ID2UNIT(chan->chan_id);
|
||||||
|
ldo_ll_set_output_voltage_mv(unit_id, voltage_mv);
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_ldo_dump(FILE *stream)
|
||||||
|
{
|
||||||
|
char line[100];
|
||||||
|
fprintf(stream, "ESP LDO Channel State:\n");
|
||||||
|
fprintf(stream, "%-5s %-5s %-10s %-12s %-5s\n", "Index", "ID", "ref_cnt", "voltage_mv", "adjustable");
|
||||||
|
for (int i = 0; i < LDO_LL_UNIT_NUM; i++) {
|
||||||
|
char *buf = line;
|
||||||
|
size_t len = sizeof(line);
|
||||||
|
memset(line, 0x0, len);
|
||||||
|
snprintf(buf, len, "%-5d %-5d %-10d %-12d %-5s\n",
|
||||||
|
i,
|
||||||
|
s_ldo_channels[i].chan_id,
|
||||||
|
s_ldo_channels[i].ref_cnt,
|
||||||
|
s_ldo_channels[i].voltage_mv,
|
||||||
|
s_ldo_channels[i].flags.adjustable ? "yes" : "no");
|
||||||
|
fputs(line, stream);
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
90
components/esp_hw_support/ldo/include/esp_ldo_regulator.h
Normal file
90
components/esp_hw_support/ldo/include/esp_ldo_regulator.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "hal/ldo_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of LDO regulator channel handle
|
||||||
|
*/
|
||||||
|
typedef struct ldo_regulator_channel_t *esp_ldo_channel_handle_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief LDO channel configurations
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int chan_id; /*!< You must set the LDO channel ID according to the datasheet, e.g., set it to 1 for LDO_VO1 */
|
||||||
|
int voltage_mv; /*!< The voltage value to be set to the LDO channel */
|
||||||
|
|
||||||
|
/// Extra flags of a LDO channel
|
||||||
|
struct ldo_extra_flags {
|
||||||
|
uint32_t adjustable : 1; /*!< Whether the LDO channel is adjustable, and the voltage can be updated by `esp_ldo_channel_adjust_voltage` */
|
||||||
|
} flags; /*!< Flags for the LDO channel */
|
||||||
|
} esp_ldo_channel_config_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Acquire an LDO channel with the specified configuration
|
||||||
|
*
|
||||||
|
* @note This function can't automatically search a LDO channel for you, you must specify a LDO channel ID manually, based on your schematic.
|
||||||
|
* @note The same channel can be acquired multiple times in different places of the application code, however,
|
||||||
|
* if the LDO channel is adjustable, you can't acquire it multiple times, in case user A changes the voltage and breaks the voltage setting of user B.
|
||||||
|
* @note You should release the channel by `esp_ldo_release_channel` when it's no longer needed.
|
||||||
|
*
|
||||||
|
* @param[in] config The configuration of the LDO channel
|
||||||
|
* @param[out] out_handle The returned LDO channel handle
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Acquire the LDO channel successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Acquire the LDO channel failed due to invalid arguments
|
||||||
|
* - ESP_FAIL: Acquire the LDO channel failed due to other reasons
|
||||||
|
*/
|
||||||
|
esp_err_t esp_ldo_acquire_channel(const esp_ldo_channel_config_t *config, esp_ldo_channel_handle_t *out_handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release the LDO channel
|
||||||
|
*
|
||||||
|
* @param[in] chan The LDO channel handle returned from `esp_ldo_acquire_channel`
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Release the LDO channel successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Release the LDO channel failed due to invalid arguments
|
||||||
|
* - ESP_ERR_INVALID_STATE: Release the LDO channel failed due to invalid state, e.g., the channel handle is double released
|
||||||
|
* - ESP_FAIL: Release the LDO channel failed due to other reasons
|
||||||
|
*/
|
||||||
|
esp_err_t esp_ldo_release_channel(esp_ldo_channel_handle_t chan);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adjust the voltage of the LDO channel
|
||||||
|
*
|
||||||
|
* @param[in] chan The LDO channel handle returned from `esp_ldo_acquire_channel`
|
||||||
|
* @param[in] voltage_mv The voltage value to be set to the LDO channel, in millivolts
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Adjust the voltage of the LDO channel successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Adjust the voltage of the LDO channel failed due to invalid arguments
|
||||||
|
* - ESP_ERR_NOT_SUPPORTED: Adjust the voltage of the LDO channel failed due to the channel is not adjustable
|
||||||
|
* - ESP_FAIL: Adjust the voltage of the LDO channel failed due to other reasons
|
||||||
|
*/
|
||||||
|
esp_err_t esp_ldo_channel_adjust_voltage(esp_ldo_channel_handle_t chan, int voltage_mv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dump LDO channel status to the specified stream
|
||||||
|
*
|
||||||
|
* @param[in] stream IO stream. Can be stdout, stderr, or a file/string stream.
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Dump the LDO channel status successfully
|
||||||
|
* - ESP_FAIL: Dump the LDO channel status failed
|
||||||
|
*/
|
||||||
|
esp_err_t esp_ldo_dump(FILE *stream);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,4 +0,0 @@
|
|||||||
[mapping:ldo_driver]
|
|
||||||
archive: libesp_hw_support.a
|
|
||||||
entries:
|
|
||||||
esp_ldo: esp_ldo_init_unit_early (noflash)
|
|
@ -1,24 +1,53 @@
|
|||||||
config ESP_VDD_PSRAM_LDO_ID
|
menu "LDO Regulator Configurations"
|
||||||
int "PSRAM VDD connected LDO ID, set -1 for using external power supply and disable internal LDO"
|
depends on SOC_GP_LDO_SUPPORTED
|
||||||
default 2
|
|
||||||
range -1 4
|
|
||||||
help
|
|
||||||
PSRAM VDD pin connected LDO ID.
|
|
||||||
PSRAM VDD needs to be connected to an voltage output. This option selects the on-chip
|
|
||||||
LDO which is connected to the PSRAM VDD.
|
|
||||||
Set to -1 for connecting to external voltage output.
|
|
||||||
|
|
||||||
choice ESP_VDD_PSRAM_LDO_VOLTAGE_MV
|
config ESP_LDO_CHAN_SPI_NOR_FLASH_DOMAIN
|
||||||
prompt "PSRAM VDD connected LDO voltage"
|
int "LDO regulator channel that used to power SPI NOR Flash (READ HELP)"
|
||||||
depends on ESP_VDD_PSRAM_LDO_ID != -1
|
default 1
|
||||||
default ESP_VDD_PSRAM_LDO_VOLTAGE_MV_1900
|
range -1 4
|
||||||
help
|
help
|
||||||
Select the LDO (ESP_VDD_PSRAM_LDO_ID) voltage output
|
The internal LDO regulator can be used to power the SPI Flash specific power domain.
|
||||||
|
This option is to select which LDO channel to connect to that domain.
|
||||||
|
Please set this option correctly according to your schematic.
|
||||||
|
Set to -1 if the Flash is using any external power supply.
|
||||||
|
|
||||||
config ESP_VDD_PSRAM_LDO_VOLTAGE_MV_1900
|
choice ESP_LDO_VOLTAGE_SPI_NOR_FLASH_DOMAIN
|
||||||
bool "1.9V"
|
prompt "SPI NOR Flash power domain voltage"
|
||||||
endchoice
|
depends on ESP_LDO_CHAN_SPI_NOR_FLASH_DOMAIN != -1
|
||||||
|
default ESP_LDO_VOLTAGE_SPI_NOR_FLASH_3300_MV
|
||||||
|
help
|
||||||
|
Select the voltage used by the Flash power domain.
|
||||||
|
|
||||||
config ESP_VDD_PSRAM_LDO_VOLTAGE_MV
|
config ESP_LDO_VOLTAGE_SPI_NOR_FLASH_3300_MV
|
||||||
int
|
bool "3.3V"
|
||||||
default 1900 if ESP_VDD_PSRAM_LDO_VOLTAGE_MV_1900
|
endchoice
|
||||||
|
|
||||||
|
config ESP_LDO_VOLTAGE_SPI_NOR_FLASH_DOMAIN
|
||||||
|
int
|
||||||
|
default 3300 if ESP_LDO_VOLTAGE_SPI_NOR_FLASH_3300_MV
|
||||||
|
|
||||||
|
config ESP_LDO_CHAN_PSRAM_DOMAIN
|
||||||
|
int "LDO regulator channel that used to power PSRAM and MPLL (READ HELP)"
|
||||||
|
default 2
|
||||||
|
range -1 4
|
||||||
|
help
|
||||||
|
The internal LDO regulator can be used to power the PSRAM specific power domain.
|
||||||
|
This option is to select which LDO channel to connect to that domain.
|
||||||
|
Please set this option correctly according to your schematic.
|
||||||
|
Set to -1 if the PSRAM is using any external power supply.
|
||||||
|
|
||||||
|
choice ESP_LDO_VOLTAGE_PSRAM_DOMAIN
|
||||||
|
prompt "PSRAM power domain voltage"
|
||||||
|
depends on ESP_LDO_CHAN_PSRAM_DOMAIN != -1
|
||||||
|
default ESP_LDO_VOLTAGE_PSRAM_1900_MV
|
||||||
|
help
|
||||||
|
Select the voltage used by the PSRAM power domain.
|
||||||
|
|
||||||
|
config ESP_LDO_VOLTAGE_PSRAM_1900_MV
|
||||||
|
bool "1.9V"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config ESP_LDO_VOLTAGE_PSRAM_DOMAIN
|
||||||
|
int
|
||||||
|
default 1900 if ESP_LDO_VOLTAGE_PSRAM_1900_MV
|
||||||
|
endmenu
|
||||||
|
@ -9,7 +9,7 @@ set(srcs "test_app_main.c"
|
|||||||
"test_key_mgr.c"
|
"test_key_mgr.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CONFIG_SOC_MULTI_USAGE_LDO_SUPPORTED)
|
if(CONFIG_SOC_GP_LDO_SUPPORTED)
|
||||||
list(APPEND srcs "test_ldo.c")
|
list(APPEND srcs "test_ldo.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -1,74 +1,89 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "unity.h"
|
|
||||||
#include "esp_private/esp_ldo.h"
|
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "esp_ldo_regulator.h"
|
||||||
|
|
||||||
TEST_CASE("LDO unit early / normal allocation", "[LDO]")
|
TEST_CASE("LDO channel acquire and release (no adjustable)", "[LDO]")
|
||||||
{
|
{
|
||||||
esp_ldo_unit_init_cfg_t init_early_unit_cfg = {
|
esp_ldo_channel_handle_t success_ldo_chans[3] = {};
|
||||||
.unit_id = LDO_UNIT_3,
|
esp_ldo_channel_handle_t fail_ldo_chan = NULL;
|
||||||
.cfg = {
|
esp_ldo_channel_config_t ldo_chan_config = {
|
||||||
.voltage_mv = 1800,
|
.chan_id = 4,
|
||||||
},
|
.voltage_mv = 1800,
|
||||||
.flags.enable_unit = true,
|
|
||||||
};
|
};
|
||||||
esp_ldo_unit_handle_t early_unit = esp_ldo_init_unit_early(&init_early_unit_cfg);
|
for (int i = 0; i < 3; i++) {
|
||||||
TEST_ASSERT(esp_ldo_enable_unit(early_unit) == ESP_ERR_INVALID_STATE);
|
TEST_ESP_OK(esp_ldo_acquire_channel(&ldo_chan_config, &success_ldo_chans[i]));
|
||||||
TEST_ESP_OK(esp_ldo_disable_unit(early_unit));
|
}
|
||||||
|
TEST_ASSERT_EQUAL(success_ldo_chans[0], success_ldo_chans[1]);
|
||||||
esp_ldo_unit_handle_t unit = NULL;
|
TEST_ASSERT_EQUAL(success_ldo_chans[0], success_ldo_chans[2]);
|
||||||
esp_ldo_unit_init_cfg_t init_unit_cfg = {
|
// can't acquire with a different voltage
|
||||||
.unit_id = LDO_UNIT_4,
|
ldo_chan_config.voltage_mv = 3300;
|
||||||
.cfg = {
|
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_ldo_acquire_channel(&ldo_chan_config, &fail_ldo_chan));
|
||||||
.voltage_mv = 2500,
|
// the channel has been acquired as "not adjustable" before, so we can't acquire it as "adjustable" again
|
||||||
},
|
ldo_chan_config = (esp_ldo_channel_config_t) {
|
||||||
|
.chan_id = 4,
|
||||||
|
.voltage_mv = 1800,
|
||||||
|
.flags.adjustable = true,
|
||||||
};
|
};
|
||||||
TEST_ESP_OK(esp_ldo_init_unit(&init_unit_cfg, &unit));
|
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_ldo_acquire_channel(&ldo_chan_config, &fail_ldo_chan));
|
||||||
TEST_ESP_OK(esp_ldo_enable_unit(unit));
|
|
||||||
TEST_ESP_OK(esp_ldo_disable_unit(unit));
|
|
||||||
|
|
||||||
init_unit_cfg.flags.shared_ldo = true;
|
// can't change the voltage for a non-adjustable channel
|
||||||
esp_ldo_unit_handle_t shared_unit = NULL;
|
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ldo_channel_adjust_voltage(success_ldo_chans[0], 3300));
|
||||||
TEST_ESP_OK(esp_ldo_init_unit(&init_unit_cfg, &shared_unit));
|
|
||||||
|
|
||||||
TEST_ESP_OK(esp_ldo_deinit_unit(early_unit));
|
for (int i = 0; i < 3; i++) {
|
||||||
TEST_ESP_OK(esp_ldo_deinit_unit(shared_unit));
|
TEST_ESP_OK(esp_ldo_release_channel(success_ldo_chans[i]));
|
||||||
TEST_ESP_OK(esp_ldo_deinit_unit(unit));
|
}
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_ldo_release_channel(success_ldo_chans[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("LDO unit output", "[LDO][mannual][ignore]")
|
TEST_CASE("LDO channel acquire and release (adjustable)", "[LDO]")
|
||||||
{
|
{
|
||||||
esp_ldo_unit_init_cfg_t early_unit_cfg = {
|
esp_ldo_channel_handle_t success_ldo_chan = NULL;
|
||||||
.unit_id = LDO_UNIT_2,
|
esp_ldo_channel_handle_t fail_ldo_chan = NULL;
|
||||||
.cfg = {
|
esp_ldo_channel_config_t ldo_chan_config = {
|
||||||
.voltage_mv = 1800,
|
.chan_id = 4,
|
||||||
},
|
.voltage_mv = 1800,
|
||||||
.flags.shared_ldo = true,
|
.flags.adjustable = true,
|
||||||
.flags.enable_unit = true,
|
|
||||||
};
|
};
|
||||||
esp_ldo_unit_handle_t early_unit2 = esp_ldo_init_unit_early(&early_unit_cfg);
|
TEST_ESP_OK(esp_ldo_acquire_channel(&ldo_chan_config, &success_ldo_chan));
|
||||||
assert(early_unit2);
|
|
||||||
|
|
||||||
early_unit_cfg.unit_id = LDO_UNIT_3;
|
// can't acquire multiple handles for the same adjustable channel
|
||||||
early_unit_cfg.cfg.voltage_mv = 3300;
|
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_ldo_acquire_channel(&ldo_chan_config, &fail_ldo_chan));
|
||||||
esp_ldo_unit_handle_t early_unit3 = esp_ldo_init_unit_early(&early_unit_cfg);
|
// even we acquire another copy as non-adjustable, it's still not allowed
|
||||||
assert(early_unit3);
|
ldo_chan_config.flags.adjustable = false;
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_ldo_acquire_channel(&ldo_chan_config, &fail_ldo_chan));
|
||||||
|
|
||||||
early_unit_cfg.unit_id = LDO_UNIT_4;
|
// can change voltage for an adjustable channel
|
||||||
early_unit_cfg.cfg.voltage_mv = 1100;
|
TEST_ESP_OK(esp_ldo_channel_adjust_voltage(success_ldo_chan, 3300));
|
||||||
esp_ldo_unit_handle_t early_unit4 = esp_ldo_init_unit_early(&early_unit_cfg);
|
TEST_ESP_OK(esp_ldo_release_channel(success_ldo_chan));
|
||||||
assert(early_unit4);
|
}
|
||||||
|
|
||||||
esp_ldo_usage_dump(stdout);
|
TEST_CASE("LDO channel state dump", "[LDO][manual][ignore]")
|
||||||
|
{
|
||||||
|
esp_ldo_channel_handle_t success_ldo_chans[3] = {};
|
||||||
|
esp_ldo_channel_config_t ldo_chan_config = {
|
||||||
|
.chan_id = 2,
|
||||||
|
.voltage_mv = 1800,
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(esp_ldo_acquire_channel(&ldo_chan_config, &success_ldo_chans[0]));
|
||||||
|
|
||||||
|
ldo_chan_config.chan_id = 3;
|
||||||
|
ldo_chan_config.voltage_mv = 2500;
|
||||||
|
TEST_ESP_OK(esp_ldo_acquire_channel(&ldo_chan_config, &success_ldo_chans[1]));
|
||||||
|
|
||||||
|
ldo_chan_config.chan_id = 4;
|
||||||
|
ldo_chan_config.voltage_mv = 1100;
|
||||||
|
TEST_ESP_OK(esp_ldo_acquire_channel(&ldo_chan_config, &success_ldo_chans[2]));
|
||||||
|
|
||||||
|
esp_ldo_dump(stdout);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
vTaskDelay(1);
|
vTaskDelay(1);
|
||||||
|
@ -6,25 +6,21 @@
|
|||||||
|
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "test_mipi_dsi_board.h"
|
#include "test_mipi_dsi_board.h"
|
||||||
#include "esp_private/esp_ldo.h"
|
#include "esp_ldo_regulator.h"
|
||||||
|
|
||||||
static esp_ldo_unit_handle_t phy_pwr_unit = NULL;
|
static esp_ldo_channel_handle_t ldo_phy_chan = NULL;
|
||||||
|
|
||||||
void test_bsp_enable_dsi_phy_power(void)
|
void test_bsp_enable_dsi_phy_power(void)
|
||||||
{
|
{
|
||||||
// Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state
|
// Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state
|
||||||
esp_ldo_unit_init_cfg_t ldo_cfg = {
|
esp_ldo_channel_config_t ldo_cfg = {
|
||||||
.unit_id = TEST_MIPI_DSI_PHY_PWR_LDO_UNIT,
|
.chan_id = TEST_MIPI_DSI_PHY_PWR_LDO_CHAN,
|
||||||
.cfg = {
|
.voltage_mv = TEST_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV,
|
||||||
.voltage_mv = TEST_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
TEST_ESP_OK(esp_ldo_init_unit(&ldo_cfg, &phy_pwr_unit));
|
TEST_ESP_OK(esp_ldo_acquire_channel(&ldo_cfg, &ldo_phy_chan));
|
||||||
TEST_ESP_OK(esp_ldo_enable_unit(phy_pwr_unit));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_bsp_disable_dsi_phy_power(void)
|
void test_bsp_disable_dsi_phy_power(void)
|
||||||
{
|
{
|
||||||
TEST_ESP_OK(esp_ldo_disable_unit(phy_pwr_unit));
|
TEST_ESP_OK(esp_ldo_release_channel(ldo_phy_chan));
|
||||||
TEST_ESP_OK(esp_ldo_deinit_unit(phy_pwr_unit));
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ extern "C" {
|
|||||||
#define MIPI_DSI_LCD_VBP 16
|
#define MIPI_DSI_LCD_VBP 16
|
||||||
#define MIPI_DSI_LCD_VFP 16
|
#define MIPI_DSI_LCD_VFP 16
|
||||||
|
|
||||||
#define TEST_MIPI_DSI_PHY_PWR_LDO_UNIT 3
|
#define TEST_MIPI_DSI_PHY_PWR_LDO_CHAN 3
|
||||||
#define TEST_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV 2500
|
#define TEST_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV 2500
|
||||||
|
|
||||||
void test_bsp_enable_dsi_phy_power(void);
|
void test_bsp_enable_dsi_phy_power(void);
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_private/periph_ctrl.h"
|
#include "esp_private/periph_ctrl.h"
|
||||||
#include "esp_private/esp_ldo_psram.h"
|
|
||||||
#include "esp_private/mspi_timing_tuning.h"
|
#include "esp_private/mspi_timing_tuning.h"
|
||||||
#include "../esp_psram_impl.h"
|
#include "../esp_psram_impl.h"
|
||||||
#include "hal/psram_ctrlr_ll.h"
|
#include "hal/psram_ctrlr_ll.h"
|
||||||
@ -366,7 +365,7 @@ static void s_configure_psram_ecc(void)
|
|||||||
esp_err_t esp_psram_impl_enable(void)
|
esp_err_t esp_psram_impl_enable(void)
|
||||||
{
|
{
|
||||||
#if SOC_CLK_MPLL_SUPPORTED
|
#if SOC_CLK_MPLL_SUPPORTED
|
||||||
periph_rtc_mpll_early_acquire();
|
periph_rtc_mpll_acquire();
|
||||||
periph_rtc_mpll_freq_set(AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ * 1000000, NULL);
|
periph_rtc_mpll_freq_set(AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ * 1000000, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -76,7 +76,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "esp_private/rtc_clk.h"
|
#include "esp_private/rtc_clk.h"
|
||||||
#include "esp_private/esp_ldo_psram.h"
|
|
||||||
|
|
||||||
#if SOC_INT_CLIC_SUPPORTED
|
#if SOC_INT_CLIC_SUPPORTED
|
||||||
#include "hal/interrupt_clic_ll.h"
|
#include "hal/interrupt_clic_ll.h"
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "hal/assert.h"
|
#include "hal/assert.h"
|
||||||
#include "soc/pmu_struct.h"
|
#include "soc/pmu_struct.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -28,6 +27,11 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define LDO_LL_UNIT_NUM 4
|
#define LDO_LL_UNIT_NUM 4
|
||||||
|
|
||||||
|
#define LDO_LL_ADJUSTABLE_CHAN_MASK 0x0F // all the 4 channels can be adjustable
|
||||||
|
|
||||||
|
#define LDO_LL_MAX_VOLTAGE_MV 3300
|
||||||
|
#define LDO_LL_MIN_VOLTAGE_MV 500
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LDO LL macros, these macros are in the unit of mV
|
* LDO LL macros, these macros are in the unit of mV
|
||||||
*/
|
*/
|
||||||
|
@ -12,7 +12,7 @@ set(srcs "sdmmc_cmd.c"
|
|||||||
"sdmmc_sd.c"
|
"sdmmc_sd.c"
|
||||||
"sd_pwr_ctrl/sd_pwr_ctrl.c")
|
"sd_pwr_ctrl/sd_pwr_ctrl.c")
|
||||||
|
|
||||||
if(CONFIG_SOC_MULTI_USAGE_LDO_SUPPORTED)
|
if(CONFIG_SOC_GP_LDO_SUPPORTED)
|
||||||
list(APPEND srcs "sd_pwr_ctrl/sd_pwr_ctrl_by_on_chip_ldo.c")
|
list(APPEND srcs "sd_pwr_ctrl/sd_pwr_ctrl_by_on_chip_ldo.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ extern "C" {
|
|||||||
* @brief LDO configurations
|
* @brief LDO configurations
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int ldo_unit_id; ///< On-chip LDO ID
|
int ldo_chan_id; ///< On-chip LDO channel ID, e.g. set to `4` is the `LDO_VO4` is connected to power the SDMMC IO
|
||||||
} sd_pwr_ctrl_ldo_config_t;
|
} sd_pwr_ctrl_ldo_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,14 +12,14 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "esp_private/esp_ldo.h"
|
#include "esp_ldo_regulator.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "sd_pwr_ctrl.h"
|
#include "sd_pwr_ctrl.h"
|
||||||
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
|
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
|
||||||
#include "sd_pwr_ctrl_interface.h"
|
#include "sd_pwr_ctrl_interface.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
esp_ldo_unit_handle_t ldo_unit;
|
esp_ldo_channel_handle_t ldo_chan;
|
||||||
int voltage_mv;
|
int voltage_mv;
|
||||||
} sd_pwr_ctrl_ldo_ctx_t;
|
} sd_pwr_ctrl_ldo_ctx_t;
|
||||||
|
|
||||||
@ -37,19 +37,16 @@ esp_err_t sd_pwr_ctrl_new_on_chip_ldo(const sd_pwr_ctrl_ldo_config_t *configs, s
|
|||||||
sd_pwr_ctrl_ldo_ctx_t *ctx = (sd_pwr_ctrl_ldo_ctx_t *)heap_caps_calloc(1, sizeof(sd_pwr_ctrl_ldo_ctx_t), MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT);
|
sd_pwr_ctrl_ldo_ctx_t *ctx = (sd_pwr_ctrl_ldo_ctx_t *)heap_caps_calloc(1, sizeof(sd_pwr_ctrl_ldo_ctx_t), MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT);
|
||||||
ESP_GOTO_ON_FALSE(ctx, ESP_ERR_NO_MEM, err, TAG, "no mem for on-chip ldo control driver context");
|
ESP_GOTO_ON_FALSE(ctx, ESP_ERR_NO_MEM, err, TAG, "no mem for on-chip ldo control driver context");
|
||||||
|
|
||||||
esp_ldo_unit_init_cfg_t unit_cfg = {
|
esp_ldo_channel_config_t chan_cfg = {
|
||||||
.unit_id = configs->ldo_unit_id,
|
.chan_id = configs->ldo_chan_id,
|
||||||
.cfg = {
|
.flags.adjustable = true, // the SDMMC power control driver will adjust the voltage later according to different speed mode
|
||||||
.voltage_mv = 0, //will be adjusted dynamically by sdmmc driver later
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
esp_ldo_unit_handle_t ldo_unit = NULL;
|
esp_ldo_channel_handle_t ldo_chan = NULL;
|
||||||
ESP_GOTO_ON_ERROR(esp_ldo_init_unit(&unit_cfg, &ldo_unit), err, TAG, "failed to create an on-chip LDO unit handle");
|
ESP_GOTO_ON_ERROR(esp_ldo_acquire_channel(&chan_cfg, &ldo_chan), err, TAG, "failed to enable the on-chip LDO unit");
|
||||||
ESP_GOTO_ON_ERROR(esp_ldo_enable_unit(ldo_unit), err, TAG, "failed to enable the on-chip LDO unit");
|
|
||||||
|
|
||||||
driver->set_io_voltage = s_ldo_set_voltage;
|
driver->set_io_voltage = s_ldo_set_voltage;
|
||||||
driver->ctx = ctx;
|
driver->ctx = ctx;
|
||||||
ctx->ldo_unit = ldo_unit;
|
ctx->ldo_chan = ldo_chan;
|
||||||
ctx->voltage_mv = 0;
|
ctx->voltage_mv = 0;
|
||||||
*ret_drv = driver;
|
*ret_drv = driver;
|
||||||
|
|
||||||
@ -66,8 +63,7 @@ esp_err_t sd_pwr_ctrl_del_on_chip_ldo(sd_pwr_ctrl_handle_t handle)
|
|||||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid arg: null pointer");
|
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid arg: null pointer");
|
||||||
|
|
||||||
sd_pwr_ctrl_ldo_ctx_t *ctx = handle->ctx;
|
sd_pwr_ctrl_ldo_ctx_t *ctx = handle->ctx;
|
||||||
ESP_RETURN_ON_ERROR(esp_ldo_disable_unit(ctx->ldo_unit), TAG, "failed to disable the on-chip LDO unit");
|
ESP_RETURN_ON_ERROR(esp_ldo_release_channel(ctx->ldo_chan), TAG, "failed to release the on-chip LDO channel");
|
||||||
ESP_RETURN_ON_ERROR(esp_ldo_deinit_unit(ctx->ldo_unit), TAG, "failed to deinit the LDO unit handle");
|
|
||||||
free(handle->ctx);
|
free(handle->ctx);
|
||||||
handle->ctx = NULL;
|
handle->ctx = NULL;
|
||||||
free(handle);
|
free(handle);
|
||||||
@ -80,7 +76,7 @@ static esp_err_t s_ldo_set_voltage(void *arg, int voltage_mv)
|
|||||||
{
|
{
|
||||||
//API checks done by caller
|
//API checks done by caller
|
||||||
sd_pwr_ctrl_ldo_ctx_t *ctx = arg;
|
sd_pwr_ctrl_ldo_ctx_t *ctx = arg;
|
||||||
ESP_RETURN_ON_ERROR(esp_ldo_set_voltage(ctx->ldo_unit, voltage_mv), TAG, "failed to set LDO unit output voltage");
|
ESP_RETURN_ON_ERROR(esp_ldo_channel_adjust_voltage(ctx->ldo_chan, voltage_mv), TAG, "failed to set LDO unit output voltage");
|
||||||
ctx->voltage_mv = voltage_mv;
|
ctx->voltage_mv = voltage_mv;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ config SOC_SPI_FLASH_SUPPORTED
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config SOC_MULTI_USAGE_LDO_SUPPORTED
|
config SOC_GP_LDO_SUPPORTED
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@
|
|||||||
#define SOC_SPI_FLASH_SUPPORTED 1
|
#define SOC_SPI_FLASH_SUPPORTED 1
|
||||||
// #define SOC_TOUCH_SENSOR_SUPPORTED 1 //TODO: IDF-7477
|
// #define SOC_TOUCH_SENSOR_SUPPORTED 1 //TODO: IDF-7477
|
||||||
// #define SOC_RNG_SUPPORTED 1 //TODO: IDF-6522
|
// #define SOC_RNG_SUPPORTED 1 //TODO: IDF-6522
|
||||||
#define SOC_MULTI_USAGE_LDO_SUPPORTED 1
|
#define SOC_GP_LDO_SUPPORTED 1 // General purpose LDO
|
||||||
// #define SOC_PPA_SUPPORTED 1 //TODO: IDF-6878
|
// #define SOC_PPA_SUPPORTED 1 //TODO: IDF-6878
|
||||||
#define SOC_LIGHT_SLEEP_SUPPORTED 1
|
#define SOC_LIGHT_SLEEP_SUPPORTED 1
|
||||||
// #define SOC_DEEP_SLEEP_SUPPORTED 1 //TODO: IDF-7529
|
// #define SOC_DEEP_SLEEP_SUPPORTED 1 //TODO: IDF-7529
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -15,6 +15,7 @@
|
|||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "hal/spi_types.h"
|
#include "hal/spi_types.h"
|
||||||
#include "esp_private/spi_share_hw_ctrl.h"
|
#include "esp_private/spi_share_hw_ctrl.h"
|
||||||
|
#include "esp_ldo_regulator.h"
|
||||||
#include "hal/spi_flash_hal.h"
|
#include "hal/spi_flash_hal.h"
|
||||||
#include "hal/gpio_hal.h"
|
#include "hal/gpio_hal.h"
|
||||||
#include "esp_flash_internal.h"
|
#include "esp_flash_internal.h"
|
||||||
@ -420,6 +421,19 @@ esp_err_t esp_flash_init_default_chip(void)
|
|||||||
esp_err_t esp_flash_app_init(void)
|
esp_err_t esp_flash_app_init(void)
|
||||||
{
|
{
|
||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
|
|
||||||
|
// Acquire the LDO channel used by the SPI NOR flash
|
||||||
|
// in case the LDO voltage is changed by other users
|
||||||
|
#if defined(CONFIG_ESP_LDO_CHAN_SPI_NOR_FLASH_DOMAIN) && CONFIG_ESP_LDO_CHAN_SPI_NOR_FLASH_DOMAIN != -1
|
||||||
|
static esp_ldo_channel_handle_t s_ldo_chan = NULL;
|
||||||
|
esp_ldo_channel_config_t ldo_config = {
|
||||||
|
.chan_id = CONFIG_ESP_LDO_CHAN_SPI_NOR_FLASH_DOMAIN,
|
||||||
|
.voltage_mv = CONFIG_ESP_LDO_VOLTAGE_SPI_NOR_FLASH_DOMAIN,
|
||||||
|
};
|
||||||
|
err = esp_ldo_acquire_channel(&ldo_config, &s_ldo_chan);
|
||||||
|
if (err != ESP_OK) return err;
|
||||||
|
#endif
|
||||||
|
|
||||||
spi_flash_init_lock();
|
spi_flash_init_lock();
|
||||||
spi_flash_guard_set(&g_flash_guard_default_ops);
|
spi_flash_guard_set(&g_flash_guard_default_ops);
|
||||||
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
|
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
|
||||||
|
@ -102,6 +102,8 @@ DAC_DOCS = ['api-reference/peripherals/dac.rst']
|
|||||||
|
|
||||||
ETM_DOCS = ['api-reference/peripherals/etm.rst']
|
ETM_DOCS = ['api-reference/peripherals/etm.rst']
|
||||||
|
|
||||||
|
LDO_DOCS = ['api-reference/peripherals/ldo_regulator.rst']
|
||||||
|
|
||||||
TEMP_SENSOR_DOCS = ['api-reference/peripherals/temp_sensor.rst']
|
TEMP_SENSOR_DOCS = ['api-reference/peripherals/temp_sensor.rst']
|
||||||
|
|
||||||
TOUCH_SENSOR_DOCS = ['api-reference/peripherals/touch_pad.rst']
|
TOUCH_SENSOR_DOCS = ['api-reference/peripherals/touch_pad.rst']
|
||||||
@ -251,6 +253,7 @@ conditional_include_dict = {'SOC_BT_SUPPORTED':BT_DOCS,
|
|||||||
'SOC_SPI_SUPPORT_SLAVE_HD_VER2':SPI_SLAVE_HD_DOCS,
|
'SOC_SPI_SUPPORT_SLAVE_HD_VER2':SPI_SLAVE_HD_DOCS,
|
||||||
'SOC_WIFI_NAN_SUPPORT':NAN_DOCS,
|
'SOC_WIFI_NAN_SUPPORT':NAN_DOCS,
|
||||||
'SOC_JPEG_CODEC_SUPPORTED':JPEG_DOCS,
|
'SOC_JPEG_CODEC_SUPPORTED':JPEG_DOCS,
|
||||||
|
'SOC_GP_LDO_SUPPORTED':LDO_DOCS,
|
||||||
'esp32':ESP32_DOCS,
|
'esp32':ESP32_DOCS,
|
||||||
'esp32s2':ESP32S2_DOCS,
|
'esp32s2':ESP32S2_DOCS,
|
||||||
'esp32s3':ESP32S3_DOCS,
|
'esp32s3':ESP32S3_DOCS,
|
||||||
|
@ -173,6 +173,7 @@ INPUT = \
|
|||||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_mac.h \
|
$(PROJECT_PATH)/components/esp_hw_support/include/esp_mac.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_random.h \
|
$(PROJECT_PATH)/components/esp_hw_support/include/esp_random.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_sleep.h \
|
$(PROJECT_PATH)/components/esp_hw_support/include/esp_sleep.h \
|
||||||
|
$(PROJECT_PATH)/components/esp_hw_support/ldo/include/esp_ldo_regulator.h \
|
||||||
$(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_io.h \
|
$(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_io.h \
|
||||||
$(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_ops.h \
|
$(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_ops.h \
|
||||||
$(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_vendor.h \
|
$(PROJECT_PATH)/components/esp_lcd/include/esp_lcd_panel_vendor.h \
|
||||||
|
@ -32,7 +32,7 @@ Hardware
|
|||||||
|
|
||||||
Some PSRAM chips are 1.8 V devices and some are 3.3 V. Consult the datasheet for your PSRAM chip and {IDF_TARGET_NAME} device to find out the working voltages.
|
Some PSRAM chips are 1.8 V devices and some are 3.3 V. Consult the datasheet for your PSRAM chip and {IDF_TARGET_NAME} device to find out the working voltages.
|
||||||
|
|
||||||
By default, the PSRAM is powered up by the on-chip LDO2. You can use :ref:`CONFIG_ESP_VDD_PSRAM_LDO_ID` to switch the LDO ID accordingly. Set this value to -1 to use an external power supply, which means the on-chip LDO will not be used. By default, the PSRAM connected to LDO is set to the correct voltage based on the Espressif module used. You can still use :ref:`CONFIG_ESP_VDD_PSRAM_LDO_VOLTAGE_MV` to select the LDO output voltage if you are not using an Espressif module. When using an external power supply, this option does not exist.
|
By default, the PSRAM is powered up by the on-chip LDO2. You can use :ref:`CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN` to switch the LDO channel accordingly. Set this value to -1 to use an external power supply, which means the on-chip LDO will not be used. By default, the PSRAM connected to LDO is set to the correct voltage based on the Espressif module used. You can still use :ref:`CONFIG_ESP_LDO_VOLTAGE_PSRAM_DOMAIN` to select the LDO output voltage if you are not using an Espressif module. When using an external power supply, this option does not exist.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ Application Example
|
|||||||
|
|
||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
* Emulate UART/I2C/SPI peripherals in assembly with dedicate CPU instructions designed for manipulating the GPIOs: :example:`peripherals/dedicated_gpio`.
|
* Software emulation (bit banging) of the UART/I2C/SPI protocols in assembly using the dedicated GPIOs and their associated CPU instructions: :example:`peripherals/dedicated_gpio`.
|
||||||
:SOC_DEDIC_GPIO_HAS_INTERRUPT: * Matrix keyboard example based on dedicated GPIO: :example:`peripherals/gpio/matrix_keyboard`.
|
:SOC_DEDIC_GPIO_HAS_INTERRUPT: * Matrix keyboard example based on dedicated GPIO: :example:`peripherals/gpio/matrix_keyboard`.
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ Peripherals API
|
|||||||
i2c
|
i2c
|
||||||
:SOC_I2S_SUPPORTED: i2s
|
:SOC_I2S_SUPPORTED: i2s
|
||||||
lcd/index
|
lcd/index
|
||||||
|
:SOC_GP_LDO_SUPPORTED: ldo_regulator
|
||||||
ledc
|
ledc
|
||||||
:SOC_MCPWM_SUPPORTED: mcpwm
|
:SOC_MCPWM_SUPPORTED: mcpwm
|
||||||
:SOC_PARLIO_SUPPORTED: parlio
|
:SOC_PARLIO_SUPPORTED: parlio
|
||||||
|
59
docs/en/api-reference/peripherals/ldo_regulator.rst
Normal file
59
docs/en/api-reference/peripherals/ldo_regulator.rst
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
Low Dropout Voltage Regulator (LDO)
|
||||||
|
===================================
|
||||||
|
|
||||||
|
:link_to_translation:`zh_CN:[中文]`
|
||||||
|
|
||||||
|
{IDF_TARGET_LDO_CHANNELS:default="unknown", esp32p4="4"}
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
The {IDF_TARGET_NAME} chip internally integrates {IDF_TARGET_LDO_CHANNELS} channels of low-dropout voltage regulators (LDOs). Each channel's voltage is programmable. In our hardware reference designs, some of these LDO outputs are typically used to power the internal Flash and PSRAM, while the remaining LDOs can be used to supply external devices.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
It's essential to read the manual first and ensure that the required current does not exceed the chip's specifications.
|
||||||
|
|
||||||
|
Functional Overview
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The description of the LDO driver is divided into the following sections:
|
||||||
|
|
||||||
|
- :ref:`ldo-channel-acquisition` - Introduces the types of LDO channels and how to apply for LDO channel resources.
|
||||||
|
- :ref:`ldo-adjust-voltage` - Describes how to adjust the voltage of the LDO channel.
|
||||||
|
|
||||||
|
.. _ldo-channel-acquisition:
|
||||||
|
|
||||||
|
LDO Channel Acquisition
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
LDO channels can be classified into two types: fixed voltage and adjustable voltage. For a fixed voltage channel, it allows multiple users to simultaneously use it (in software, we allow a variable to have multiple immutable references ). However, for an adjustable voltage channel, only one user is allowed to use it at a time (in software, we don't allow a variable to have multiple mutable references or coexistence of mutable and immutable references).
|
||||||
|
|
||||||
|
In the driver, the LDO channel is represented by the :cpp:type:`esp_ldo_channel_handle_t`. You can use the :cpp:func:`esp_ldo_acquire_channel` function to request LDO channel resources. Upon successful acquisition, a handle for the LDO channel will be returned, which can be used for subsequent voltage adjustment operations. When applying for a channel, the :cpp:type:`esp_ldo_channel_config_t` structure is used to specify the basic information of the LDO channel, including the channel ID, the desired output voltage, and whether the voltage can be dynamically adjusted.
|
||||||
|
|
||||||
|
- :cpp:member:`esp_ldo_channel_config_t::chan_id` - LDO channels are uniquely identified by a label, which is used to distinguish different LDO channels. Please note that this information needs to be determined based on the circuit schematic and chip datasheet. For example, an LDO channel labeled as ``LDO_VO3`` corresponds to an ID of ``3``.
|
||||||
|
- :cpp:member:`esp_ldo_channel_config_t::voltage_mv` - The desired output voltage of the LDO channel, in millivolts.
|
||||||
|
- :cpp:member:`esp_ldo_channel_config_t::ldo_extra_flags::adjustable` - Whether the LDO channel's output voltage can be dynamically adjusted. Only when it is set to `true`, can the :cpp:func:`esp_ldo_channel_adjust_voltage` function be used to dynamically adjust the output voltage.
|
||||||
|
|
||||||
|
Since multiple users are allowed to use a fixed voltage LDO channel simultaneously, the driver internally maintains a reference counter. The LDO channel will be automatically closed when the last user releases the LDO channel resources. The function to release LDO channel resources is :cpp:func:`esp_ldo_release_channel`. Additionally, it is important to note that the acquisition and release of LDO channels should appear in pairs during usage.
|
||||||
|
|
||||||
|
.. _ldo-adjust-voltage:
|
||||||
|
|
||||||
|
LDO Voltage Adjustment
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
:cpp:func:`esp_ldo_channel_adjust_voltage` function is used to adjust the output voltage of an LDO channel at runtime. However, please note that this function can only be used for LDO channels with adjustable voltage. Attempting to use this function on a fixed voltage LDO channel will result in an error.
|
||||||
|
|
||||||
|
Also, it is important to keep in mind that due to hardware limitations, the LDO channel voltage may have a deviation of approximately 50-100mV. Therefore, it is not advisable to rely on the LDO channel's output voltage for precise analog control.
|
||||||
|
|
||||||
|
Application Examples
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
.. list::
|
||||||
|
|
||||||
|
:SOC_MIPI_DSI_SUPPORTED: * Use the internal LDO channel to power up the MIPI DPHY: :example:`peripherals/lcd/mipi_dsi`
|
||||||
|
|
||||||
|
API Reference
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. include-build-file:: inc/esp_ldo_regulator.inc
|
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
请查询相应 PSRAM 芯片以及 {IDF_TARGET_NAME} 的技术规格书获取准确的工作电压。
|
请查询相应 PSRAM 芯片以及 {IDF_TARGET_NAME} 的技术规格书获取准确的工作电压。
|
||||||
|
|
||||||
PSRAM 默认由片上 LDO2 供电。可设置 :ref:`CONFIG_ESP_VDD_PSRAM_LDO_ID` 来切换相应的 LDO ID,将该值设为 -1 表示使用外部电源,即不使用片上 LDO。默认情况下,连接到 LDO 的 PSRAM 会基于所使用的乐鑫模组设置正确电压。如果未使用乐鑫模组,仍可设置 :ref:`CONFIG_ESP_VDD_PSRAM_LDO_VOLTAGE_MV` 来选择 LDO 输出电压。使用外部电源时,该选项不存在。
|
PSRAM 默认由片上 LDO2 供电。可设置 :ref:`CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN` 来切换相应的 LDO 输出通道,将该值设为 -1 表示使用外部电源,即不使用片上 LDO。默认情况下,连接到 LDO 的 PSRAM 会基于所使用的乐鑫模组设置正确电压。如果未使用乐鑫模组,仍可设置 :ref:`CONFIG_ESP_LDO_VOLTAGE_PSRAM_DOMAIN` 来选择 LDO 输出电压。使用外部电源时,该选项不存在。
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ GPIO 捆绑包操作
|
|||||||
|
|
||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
* 通过汇编代码使用专用的 CPU 指令来操作 GPIO 以模拟 UART/I2C/SPI 外设 :example:`peripherals/dedicated_gpio`.
|
* 通过汇编代码使用专用的 CPU 指令来操作 GPIO 以模拟 UART/I2C/SPI 协议(Bit Banging) :example:`peripherals/dedicated_gpio`.
|
||||||
:SOC_DEDIC_GPIO_HAS_INTERRUPT: * 基于专用 GPIO 驱动的矩阵键盘::example:`peripherals/gpio/matrix_keyboard`.
|
:SOC_DEDIC_GPIO_HAS_INTERRUPT: * 基于专用 GPIO 驱动的矩阵键盘::example:`peripherals/gpio/matrix_keyboard`.
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
i2c
|
i2c
|
||||||
:SOC_I2S_SUPPORTED: i2s
|
:SOC_I2S_SUPPORTED: i2s
|
||||||
lcd/index
|
lcd/index
|
||||||
|
:SOC_GP_LDO_SUPPORTED: ldo_regulator
|
||||||
ledc
|
ledc
|
||||||
:SOC_MCPWM_SUPPORTED: mcpwm
|
:SOC_MCPWM_SUPPORTED: mcpwm
|
||||||
:SOC_PARLIO_SUPPORTED: parlio
|
:SOC_PARLIO_SUPPORTED: parlio
|
||||||
|
59
docs/zh_CN/api-reference/peripherals/ldo_regulator.rst
Normal file
59
docs/zh_CN/api-reference/peripherals/ldo_regulator.rst
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
低压差线性稳压器 (LDO)
|
||||||
|
======================
|
||||||
|
|
||||||
|
:link_to_translation:`en:[English]`
|
||||||
|
|
||||||
|
{IDF_TARGET_LDO_CHANNELS:default="unknown", esp32p4="4"}
|
||||||
|
|
||||||
|
简介
|
||||||
|
----
|
||||||
|
|
||||||
|
{IDF_TARGET_NAME} 芯片内部集成了 {IDF_TARGET_LDO_CHANNELS} 路低压差线性稳压器 (LDO),每路的电压都是可编程调节的。在硬件的参考设计中,我们通常会将其中一些的 LDO 输出作为内部 Flash 和 PSRAM 的电源,剩余的一些 LDO 可以用于给外部设备供电。
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
使用前请阅读手册,确保你需要的电流不会超过芯片的规格。
|
||||||
|
|
||||||
|
功能概述
|
||||||
|
--------
|
||||||
|
|
||||||
|
下文将分节介绍 LDO 驱动的功能:
|
||||||
|
|
||||||
|
- :ref:`ldo-channel-acquisition` - 介绍LDO通道的种类以及如何申请 LDO 通道资源
|
||||||
|
- :ref:`ldo-adjust-voltage` - 介绍如何调节 LDO 通道的输出电压
|
||||||
|
|
||||||
|
.. _ldo-channel-acquisition:
|
||||||
|
|
||||||
|
LDO 通道申请
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
LDO 通道可以分为两种,一种是电压固定的,另一种是电压可调的。对于同一个输出通道,如果电压固定,那么可以允许有多个用户同时使用(软件允许一个变量拥有多个不可变引用)。如果电压可调,那么只能允许一个用户使用(软件上不允许一个变量有多个可变引用或者可变和不可变引用同时存在)。
|
||||||
|
|
||||||
|
LDO 通道在驱动软件中由 :cpp:type:`esp_ldo_channel_handle_t` 句柄表示。申请 LDO 通道资源的函数是 :cpp:func:`esp_ldo_acquire_channel`。申请成功后,会返回一个 LDO 通道的句柄,这个句柄可以用于后续的电压调节操作。在申请通道的时候,我们需要通过 :cpp:type:`esp_ldo_channel_config_t` 结构体来指定 LDO 通道的基本信息,包括通道 ID,期望的输出电压,以及电压是否可以动态调节。
|
||||||
|
|
||||||
|
- :cpp:member:`esp_ldo_channel_config_t::chan_id` - LDO 通道的唯一标记,用于区分不同的 LDO 通道。注意,这需要你根据电路原理图和芯片数据手册来确定。比如,一个标记着 "LDO_VO3" 的 LDO 通道,对应的 ID 是 3。
|
||||||
|
- :cpp:member:`esp_ldo_channel_config_t::voltage_mv` - 期望的输出电压,单位是毫伏。
|
||||||
|
- :cpp:member:`esp_ldo_channel_config_t::ldo_extra_flags::adjustable` - 是否允许调节输出电压。只有设置为 `true`,才允许使用 :cpp:func:`esp_ldo_channel_adjust_voltage` 函数来动态地调节输出电压。
|
||||||
|
|
||||||
|
由于允许多个用户同时使用固定电压的 LDO 通道,所以驱动内部会维持一个引用计数器。当最后一个用户释放 LDO 通道资源时,LDO 通道会被自动关闭。释放 LDO 通道资源的函数是 :cpp:func:`esp_ldo_release_channel`。另外还需要注意,申请和释放 LDO 通道在使用的时候需要成对出现。
|
||||||
|
|
||||||
|
.. _ldo-adjust-voltage:
|
||||||
|
|
||||||
|
LDO 通道电压调节
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
:cpp:func:`esp_ldo_channel_adjust_voltage` 函数用来在运行时调整 LDO 通道的输出电压。但是,这个函数只能用于可调节电压的 LDO 通道,否则会返回错误。
|
||||||
|
|
||||||
|
注意,由于硬件限制,LDO 通道电压的精度可能会 50~100mV 左右的偏差,请勿依赖于 LDO 通道的输出电压来进行精确的模拟量控制。
|
||||||
|
|
||||||
|
应用示例
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. list::
|
||||||
|
|
||||||
|
:SOC_MIPI_DSI_SUPPORTED: * Use the internal LDO channel to power up the MIPI DPHY: :example:`peripherals/lcd/mipi_dsi`
|
||||||
|
|
||||||
|
API 参考
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. include-build-file:: inc/esp_ldo_regulator.inc
|
@ -1,3 +1,3 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
lvgl/lvgl: "~9.0.0"
|
lvgl/lvgl: "^9.0.0"
|
||||||
esp_lcd_ili9881c: "*"
|
esp_lcd_ili9881c: "*"
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "esp_private/esp_ldo.h"
|
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "esp_lcd_panel_ops.h"
|
#include "esp_lcd_panel_ops.h"
|
||||||
#include "esp_lcd_mipi_dsi.h"
|
#include "esp_lcd_mipi_dsi.h"
|
||||||
#include "esp_lcd_ili9881c.h"
|
#include "esp_lcd_ili9881c.h"
|
||||||
|
#include "esp_ldo_regulator.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
@ -43,8 +43,8 @@ static const char *TAG = "example";
|
|||||||
//////////////////// Please update the following configuration according to your Board Design //////////////////////////
|
//////////////////// Please update the following configuration according to your Board Design //////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// The "VDD_MIPI_DPHY" should be supplied with 2.5V, it can source from the integrated LDO unit or from external LDO chip
|
// The "VDD_MIPI_DPHY" should be supplied with 2.5V, it can source from the internal LDO regulator or from external LDO chip
|
||||||
#define EXAMPLE_MIPI_DSI_PHY_PWR_LDO_UNIT 3 // LDO_VO3 is connected to VDD_MIPI_DPHY
|
#define EXAMPLE_MIPI_DSI_PHY_PWR_LDO_CHAN 3 // LDO_VO3 is connected to VDD_MIPI_DPHY
|
||||||
#define EXAMPLE_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV 2500
|
#define EXAMPLE_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV 2500
|
||||||
#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 1
|
#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 1
|
||||||
#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
|
#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
|
||||||
@ -126,17 +126,13 @@ static bool example_notify_lvgl_flush_ready(esp_lcd_panel_handle_t panel, esp_lc
|
|||||||
static void example_bsp_enable_dsi_phy_power(void)
|
static void example_bsp_enable_dsi_phy_power(void)
|
||||||
{
|
{
|
||||||
// Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state
|
// Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state
|
||||||
esp_ldo_unit_handle_t phy_pwr_unit = NULL;
|
esp_ldo_channel_handle_t ldo_mipi_phy = NULL;
|
||||||
#if EXAMPLE_MIPI_DSI_PHY_PWR_LDO_UNIT > 0
|
#ifdef EXAMPLE_MIPI_DSI_PHY_PWR_LDO_CHAN
|
||||||
esp_ldo_unit_init_cfg_t ldo_cfg = {
|
esp_ldo_channel_config_t ldo_mipi_phy_config = {
|
||||||
.unit_id = EXAMPLE_MIPI_DSI_PHY_PWR_LDO_UNIT,
|
.chan_id = EXAMPLE_MIPI_DSI_PHY_PWR_LDO_CHAN,
|
||||||
.cfg = {
|
.voltage_mv = EXAMPLE_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV,
|
||||||
.voltage_mv = EXAMPLE_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(esp_ldo_init_unit(&ldo_cfg, &phy_pwr_unit));
|
ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy));
|
||||||
ESP_ERROR_CHECK(esp_ldo_enable_unit(phy_pwr_unit));
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "MIPI DSI PHY Powered on");
|
ESP_LOGI(TAG, "MIPI DSI PHY Powered on");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ void app_main(void)
|
|||||||
*/
|
*/
|
||||||
#if CONFIG_EXAMPLE_SDMMC_IO_POWER_INTERNAL_LDO
|
#if CONFIG_EXAMPLE_SDMMC_IO_POWER_INTERNAL_LDO
|
||||||
sd_pwr_ctrl_ldo_config_t ldo_config = {
|
sd_pwr_ctrl_ldo_config_t ldo_config = {
|
||||||
.ldo_unit_id = 4,
|
.ldo_chan_id = 4, // `LDO_VO4` is used as the SDMMC IO power
|
||||||
};
|
};
|
||||||
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
|
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user