mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
Merge branch 'feat/support_lp_debug_probe' into 'master'
feat(esp_hw_support): support esp32p4 VDD_BAT sleep mode main power control by LP_Probe Closes IDF-15413 See merge request espressif/esp-idf!46509
This commit is contained in:
@@ -634,12 +634,36 @@ FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_down_wait_cycle(pmu_dev_t
|
|||||||
|
|
||||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle)
|
FORCE_INLINE_ATTR void pmu_ll_lp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle)
|
||||||
{
|
{
|
||||||
|
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
|
||||||
|
HAL_ASSERT(slow_clk_cycle <= 1020);
|
||||||
|
uint32_t target = 0, expand = 0;
|
||||||
|
if (slow_clk_cycle <= 255) {
|
||||||
|
target = slow_clk_cycle;
|
||||||
|
expand = 0;
|
||||||
|
} else if (slow_clk_cycle <= 510) {
|
||||||
|
expand = 1;
|
||||||
|
target = (slow_clk_cycle + 1) >> 1;
|
||||||
|
} else if (slow_clk_cycle <= 1020) {
|
||||||
|
expand = 2;
|
||||||
|
target = (slow_clk_cycle + 3) >> 2;
|
||||||
|
}
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target, target);
|
||||||
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target_expand, expand);
|
||||||
|
#else
|
||||||
|
HAL_ASSERT(slow_clk_cycle <= 255);
|
||||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target, slow_clk_cycle);
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target, slow_clk_cycle);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_analog_wait_target_cycle(pmu_dev_t *hw)
|
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_analog_wait_target_cycle(pmu_dev_t *hw)
|
||||||
{
|
{
|
||||||
|
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
|
||||||
|
uint32_t target = HAL_FORCE_READ_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target);
|
||||||
|
uint32_t expand = HAL_FORCE_READ_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target_expand);
|
||||||
|
return target << expand;
|
||||||
|
#else
|
||||||
return HAL_FORCE_READ_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target);
|
return HAL_FORCE_READ_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE_ATTR void pmu_ll_set_xtal_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
FORCE_INLINE_ATTR void pmu_ll_set_xtal_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ typedef enum {
|
|||||||
#define VBAT_LL_CHARGER_MASK (BIT(27)|BIT(28))
|
#define VBAT_LL_CHARGER_MASK (BIT(27)|BIT(28))
|
||||||
#define VBAT_LL_DETECT_MASK (BIT(30))
|
#define VBAT_LL_DETECT_MASK (BIT(30))
|
||||||
|
|
||||||
|
#define VBAT_LL_LP_SLEEP_PROBE_ID (9)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -16,6 +16,10 @@
|
|||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "soc/debug_probe_periph.h"
|
#include "soc/debug_probe_periph.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
|
#if SOC_DEBUG_PROBE_NUM_UNIT >= 2 && SOC_LP_GPIO_MATRIX_SUPPORTED
|
||||||
|
#include "driver/rtc_io.h"
|
||||||
|
#include "driver/lp_io.h"
|
||||||
|
#endif
|
||||||
#include "hal/debug_probe_ll.h"
|
#include "hal/debug_probe_ll.h"
|
||||||
#include "esp_private/debug_probe.h"
|
#include "esp_private/debug_probe.h"
|
||||||
#include "esp_private/gpio.h"
|
#include "esp_private/gpio.h"
|
||||||
@@ -28,9 +32,10 @@ typedef struct debug_probe_unit_t debug_probe_unit_t;
|
|||||||
typedef struct debug_probe_channel_t debug_probe_channel_t;
|
typedef struct debug_probe_channel_t debug_probe_channel_t;
|
||||||
|
|
||||||
struct debug_probe_unit_t {
|
struct debug_probe_unit_t {
|
||||||
int unit_id; // unit id
|
debug_probe_unit_id_t unit_id; // unit id
|
||||||
debug_probe_channel_t *channels[DEBUG_PROBE_LL_CHANNELS_PER_UNIT]; // channels installed in this unit
|
debug_probe_channel_t *channels[DEBUG_PROBE_LL_CHANNELS_PER_UNIT]; // channels installed in this unit
|
||||||
uint64_t pin_bit_mask; // bit-mask of the GPIOs used by this unit
|
uint64_t pin_bit_mask; // bit-mask of the GPIOs used by this unit
|
||||||
|
uint32_t probe_out_inv_mask; // bit i set = invert i-th probe signal
|
||||||
};
|
};
|
||||||
|
|
||||||
struct debug_probe_channel_t {
|
struct debug_probe_channel_t {
|
||||||
@@ -45,9 +50,31 @@ typedef struct debug_probe_platform_t {
|
|||||||
|
|
||||||
static debug_probe_platform_t s_platform; // singleton platform
|
static debug_probe_platform_t s_platform; // singleton platform
|
||||||
|
|
||||||
|
static esp_err_t connect_probe_out_to_pin(debug_probe_unit_id_t unit_id, int pin, unsigned sig_idx, bool out_inv)
|
||||||
|
{
|
||||||
|
if (unit_id == DEBUG_PROBE_UNIT_HP) {
|
||||||
|
esp_err_t ret = gpio_func_sel((gpio_num_t)pin, PIN_FUNC_GPIO);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
esp_rom_gpio_connect_out_signal(pin, debug_probe_periph_signals.units[0].out_sig[sig_idx], out_inv, false);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
#if SOC_DEBUG_PROBE_NUM_UNIT >= 2
|
||||||
|
if (!rtc_gpio_is_valid_gpio((gpio_num_t)pin)) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
esp_err_t ret = rtc_gpio_init((gpio_num_t)pin);
|
||||||
|
return (ret == ESP_OK) ? lp_gpio_connect_out_signal((gpio_num_t)pin,
|
||||||
|
debug_probe_periph_signals.units[1].out_sig[sig_idx], out_inv, false) : ret;
|
||||||
|
#else
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static esp_err_t debug_probe_unit_destroy(debug_probe_unit_t *unit)
|
static esp_err_t debug_probe_unit_destroy(debug_probe_unit_t *unit)
|
||||||
{
|
{
|
||||||
int unit_id = unit->unit_id;
|
debug_probe_unit_id_t unit_id = unit->unit_id;
|
||||||
|
|
||||||
// remove the unit from the platform
|
// remove the unit from the platform
|
||||||
_lock_acquire(&s_platform.mutex);
|
_lock_acquire(&s_platform.mutex);
|
||||||
@@ -57,6 +84,13 @@ static esp_err_t debug_probe_unit_destroy(debug_probe_unit_t *unit)
|
|||||||
// disable the probe output
|
// disable the probe output
|
||||||
debug_probe_ll_enable_unit(unit_id, false);
|
debug_probe_ll_enable_unit(unit_id, false);
|
||||||
esp_gpio_revoke(unit->pin_bit_mask);
|
esp_gpio_revoke(unit->pin_bit_mask);
|
||||||
|
#if SOC_DEBUG_PROBE_NUM_UNIT >= 2
|
||||||
|
if (unit_id == DEBUG_PROBE_UNIT_LP) {
|
||||||
|
for (uint64_t m = unit->pin_bit_mask; m; m &= m - 1) {
|
||||||
|
rtc_gpio_deinit((gpio_num_t)(__builtin_ffsll(m) - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// free the memory
|
// free the memory
|
||||||
free(unit);
|
free(unit);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@@ -65,21 +99,20 @@ static esp_err_t debug_probe_unit_destroy(debug_probe_unit_t *unit)
|
|||||||
esp_err_t debug_probe_new_unit(const debug_probe_unit_config_t *config, debug_probe_unit_handle_t *out_handle)
|
esp_err_t debug_probe_new_unit(const debug_probe_unit_config_t *config, debug_probe_unit_handle_t *out_handle)
|
||||||
{
|
{
|
||||||
debug_probe_unit_t *unit = NULL;
|
debug_probe_unit_t *unit = NULL;
|
||||||
int unit_id = -1;
|
debug_probe_unit_id_t unit_id = config->unit_id;
|
||||||
ESP_RETURN_ON_FALSE(config && out_handle, ESP_ERR_INVALID_ARG, TAG, "invalid args");
|
ESP_RETURN_ON_FALSE(config && out_handle && unit_id < SOC_DEBUG_PROBE_NUM_UNIT, ESP_ERR_INVALID_ARG, TAG, "invalid args");
|
||||||
|
|
||||||
// search for a free unit slot
|
/* Check the requested unit slot is free (unit_id from config->unit_id) */
|
||||||
_lock_acquire(&s_platform.mutex);
|
_lock_acquire(&s_platform.mutex);
|
||||||
for (int i = 0; i < SOC_DEBUG_PROBE_NUM_UNIT; i++) {
|
if (s_platform.units[unit_id] != NULL) {
|
||||||
if (s_platform.units[i] == NULL) {
|
_lock_release(&s_platform.mutex);
|
||||||
unit_id = i;
|
ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_FOUND, TAG, "unit slot in use");
|
||||||
unit = calloc(1, sizeof(debug_probe_unit_t));
|
}
|
||||||
s_platform.units[i] = unit;
|
unit = calloc(1, sizeof(debug_probe_unit_t));
|
||||||
break;
|
if (unit) {
|
||||||
}
|
s_platform.units[unit_id] = unit;
|
||||||
}
|
}
|
||||||
_lock_release(&s_platform.mutex);
|
_lock_release(&s_platform.mutex);
|
||||||
ESP_RETURN_ON_FALSE(unit_id >= 0, ESP_ERR_NOT_FOUND, TAG, "no free unit slot");
|
|
||||||
ESP_RETURN_ON_FALSE(unit, ESP_ERR_NO_MEM, TAG, "no mem for unit");
|
ESP_RETURN_ON_FALSE(unit, ESP_ERR_NO_MEM, TAG, "no mem for unit");
|
||||||
unit->unit_id = unit_id;
|
unit->unit_id = unit_id;
|
||||||
|
|
||||||
@@ -97,21 +130,32 @@ esp_err_t debug_probe_new_unit(const debug_probe_unit_config_t *config, debug_pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// connect the probe output signals to the GPIOs
|
// connect the probe output signals to the GPIOs
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
for (int i = 0; i < SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH; i++) {
|
for (int i = 0; i < SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH; i++) {
|
||||||
if (config->probe_out_gpio_nums[i] >= 0) {
|
int pin = config->probe_out_gpio_nums[i];
|
||||||
gpio_func_sel(config->probe_out_gpio_nums[i], PIN_FUNC_GPIO);
|
if (pin >= 0) {
|
||||||
esp_rom_gpio_connect_out_signal(config->probe_out_gpio_nums[i],
|
bool out_inv = !!(config->probe_out_inv_mask & BIT(i));
|
||||||
debug_probe_periph_signals.units[unit_id].out_sig[i],
|
ret = connect_probe_out_to_pin(unit_id, pin, (unsigned)i, out_inv);
|
||||||
false, false);
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Probe out pin %d failed: %s", pin, esp_err_to_name(ret));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
unit->pin_bit_mask = pin_bit_mask;
|
||||||
|
(void)debug_probe_unit_destroy(unit);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
unit->pin_bit_mask = pin_bit_mask;
|
unit->pin_bit_mask = pin_bit_mask;
|
||||||
|
unit->probe_out_inv_mask = config->probe_out_inv_mask;
|
||||||
|
|
||||||
// enable the probe unit
|
// enable the probe unit
|
||||||
debug_probe_ll_enable_unit(unit_id, true);
|
debug_probe_ll_enable_unit(unit_id, true);
|
||||||
|
|
||||||
*out_handle = unit;
|
*out_handle = unit;
|
||||||
return ESP_OK;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t debug_probe_del_unit(debug_probe_unit_handle_t unit)
|
esp_err_t debug_probe_del_unit(debug_probe_unit_handle_t unit)
|
||||||
@@ -134,7 +178,7 @@ esp_err_t debug_probe_del_unit(debug_probe_unit_handle_t unit)
|
|||||||
static esp_err_t debug_probe_channel_destroy(debug_probe_channel_t *chan)
|
static esp_err_t debug_probe_channel_destroy(debug_probe_channel_t *chan)
|
||||||
{
|
{
|
||||||
debug_probe_unit_t *unit = chan->unit;
|
debug_probe_unit_t *unit = chan->unit;
|
||||||
int unit_id = unit->unit_id;
|
debug_probe_unit_id_t unit_id = unit->unit_id;
|
||||||
int chan_id = chan->chan_id;
|
int chan_id = chan->chan_id;
|
||||||
|
|
||||||
// remove the channel from the unit
|
// remove the channel from the unit
|
||||||
@@ -154,7 +198,7 @@ esp_err_t debug_probe_new_channel(debug_probe_unit_handle_t unit, const debug_pr
|
|||||||
debug_probe_channel_t *chan = NULL;
|
debug_probe_channel_t *chan = NULL;
|
||||||
int chan_id = -1;
|
int chan_id = -1;
|
||||||
ESP_RETURN_ON_FALSE(unit && config && out_handle, ESP_ERR_INVALID_ARG, TAG, "invalid args");
|
ESP_RETURN_ON_FALSE(unit && config && out_handle, ESP_ERR_INVALID_ARG, TAG, "invalid args");
|
||||||
int unit_id = unit->unit_id;
|
debug_probe_unit_id_t unit_id = unit->unit_id;
|
||||||
|
|
||||||
// search for a free channel slot
|
// search for a free channel slot
|
||||||
_lock_acquire(&s_platform.mutex);
|
_lock_acquire(&s_platform.mutex);
|
||||||
@@ -173,7 +217,10 @@ esp_err_t debug_probe_new_channel(debug_probe_unit_handle_t unit, const debug_pr
|
|||||||
chan->unit = unit;
|
chan->unit = unit;
|
||||||
|
|
||||||
// one channel can only monitor one target module
|
// one channel can only monitor one target module
|
||||||
debug_probe_ll_channel_set_target_module(unit_id, chan_id, config->target_module);
|
uint8_t target_module = (unit_id == DEBUG_PROBE_UNIT_HP)
|
||||||
|
? (uint8_t)config->target_module.hp_target
|
||||||
|
: (uint8_t)config->target_module.lp_target;
|
||||||
|
debug_probe_ll_channel_set_target_module(unit_id, chan_id, target_module);
|
||||||
debug_probe_ll_enable_channel(unit_id, chan_id, true);
|
debug_probe_ll_enable_channel(unit_id, chan_id, true);
|
||||||
|
|
||||||
*out_handle = chan;
|
*out_handle = chan;
|
||||||
@@ -189,9 +236,10 @@ esp_err_t debug_probe_del_channel(debug_probe_channel_handle_t chan)
|
|||||||
esp_err_t debug_probe_chan_add_signal_by_byte(debug_probe_channel_handle_t chan, uint8_t byte_idx, uint8_t sig_group)
|
esp_err_t debug_probe_chan_add_signal_by_byte(debug_probe_channel_handle_t chan, uint8_t byte_idx, uint8_t sig_group)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid args");
|
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid args");
|
||||||
ESP_RETURN_ON_FALSE(byte_idx < 4, ESP_ERR_INVALID_ARG, TAG, "byte_idx out of range");
|
|
||||||
ESP_RETURN_ON_FALSE(sig_group < 16, ESP_ERR_INVALID_ARG, TAG, "sig_group out of range");
|
|
||||||
debug_probe_unit_t *unit = chan->unit;
|
debug_probe_unit_t *unit = chan->unit;
|
||||||
|
ESP_RETURN_ON_FALSE(byte_idx < ((unit->unit_id == DEBUG_PROBE_UNIT_LP) ? 2 : 4),
|
||||||
|
ESP_ERR_INVALID_ARG, TAG, "byte_idx out of range");
|
||||||
|
ESP_RETURN_ON_FALSE(sig_group < 16, ESP_ERR_INVALID_ARG, TAG, "sig_group out of range");
|
||||||
debug_probe_ll_channel_add_signal_group(unit->unit_id, chan->chan_id, byte_idx, sig_group);
|
debug_probe_ll_channel_add_signal_group(unit->unit_id, chan->chan_id, byte_idx, sig_group);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -199,18 +247,25 @@ esp_err_t debug_probe_chan_add_signal_by_byte(debug_probe_channel_handle_t chan,
|
|||||||
esp_err_t debug_probe_unit_merge16(debug_probe_unit_handle_t unit, debug_probe_channel_handle_t chan0, debug_probe_split_u16_t split_of_chan0,
|
esp_err_t debug_probe_unit_merge16(debug_probe_unit_handle_t unit, debug_probe_channel_handle_t chan0, debug_probe_split_u16_t split_of_chan0,
|
||||||
debug_probe_channel_handle_t chan1, debug_probe_split_u16_t split_of_chan1)
|
debug_probe_channel_handle_t chan1, debug_probe_split_u16_t split_of_chan1)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE(unit && chan0 && chan1, ESP_ERR_INVALID_ARG, TAG, "invalid args");
|
ESP_RETURN_ON_FALSE(unit && chan0, ESP_ERR_INVALID_ARG, TAG, "invalid args");
|
||||||
ESP_RETURN_ON_FALSE(chan0->unit == unit && chan1->unit == unit, ESP_ERR_INVALID_ARG, TAG, "chan not belong to unit");
|
ESP_RETURN_ON_FALSE(chan0->unit == unit, ESP_ERR_INVALID_ARG, TAG, "chan0 not belong to unit");
|
||||||
int unit_id = unit->unit_id;
|
if (chan1 != NULL) {
|
||||||
|
ESP_RETURN_ON_FALSE(chan1->unit == unit, ESP_ERR_INVALID_ARG, TAG, "chan1 not belong to unit");
|
||||||
|
}
|
||||||
|
debug_probe_unit_id_t unit_id = unit->unit_id;
|
||||||
|
|
||||||
debug_probe_ll_set_lower16_output(unit_id, chan0->chan_id, split_of_chan0);
|
debug_probe_ll_set_lower16_output(unit_id, chan0->chan_id, split_of_chan0);
|
||||||
debug_probe_ll_set_upper16_output(unit_id, chan1->chan_id, split_of_chan1);
|
if (chan1 != NULL) {
|
||||||
|
debug_probe_ll_set_upper16_output(unit_id, chan1->chan_id, split_of_chan1);
|
||||||
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t debug_probe_unit_read(debug_probe_unit_handle_t unit, uint32_t *value)
|
esp_err_t debug_probe_unit_read(debug_probe_unit_handle_t unit, uint32_t *value)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE(unit && value, ESP_ERR_INVALID_ARG, TAG, "invalid args");
|
ESP_RETURN_ON_FALSE(unit && value, ESP_ERR_INVALID_ARG, TAG, "invalid args");
|
||||||
int unit_id = unit->unit_id;
|
debug_probe_unit_id_t unit_id = unit->unit_id;
|
||||||
*value = debug_probe_ll_read_output(unit_id);
|
uint32_t raw = debug_probe_ll_read_output(unit_id);
|
||||||
|
*value = raw ^ unit->probe_out_inv_mask;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -30,7 +30,9 @@ typedef struct debug_probe_channel_t *debug_probe_channel_handle_t;
|
|||||||
* @brief Configuration for a debug probe unit
|
* @brief Configuration for a debug probe unit
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
gpio_num_t probe_out_gpio_nums[DEBUG_PROBE_MAX_OUTPUT_WIDTH]; ///< GPIO numbers for probe output
|
debug_probe_unit_id_t unit_id; ///< DEBUG_PROBE_UNIT_HP or DEBUG_PROBE_UNIT_LP
|
||||||
|
gpio_num_t probe_out_gpio_nums[DEBUG_PROBE_MAX_OUTPUT_WIDTH]; ///< GPIO numbers for probe output
|
||||||
|
uint32_t probe_out_inv_mask; ///< Bit mask: bit i set = invert output for i-th probe signal (default 0 = no inversion)
|
||||||
} debug_probe_unit_config_t;
|
} debug_probe_unit_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,9 +62,13 @@ esp_err_t debug_probe_del_unit(debug_probe_unit_handle_t unit);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Configuration for a debug probe channel
|
* @brief Configuration for a debug probe channel
|
||||||
|
* @note Use hp_target for HP unit, lp_target for LP unit
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
debug_probe_target_t target_module; ///< Target module of the debug probe channel
|
union {
|
||||||
|
debug_probe_target_t hp_target; ///< Target when unit is HP
|
||||||
|
debug_probe_target_lp_t lp_target; ///< Target when unit is LP
|
||||||
|
} target_module;
|
||||||
} debug_probe_channel_config_t;
|
} debug_probe_channel_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,7 +109,7 @@ esp_err_t debug_probe_del_channel(debug_probe_channel_handle_t chan);
|
|||||||
* @note You can save up to 32 signals in a channel, but in the end, only the part of them (e.g. upper or lower 16 signals) can be output to the GPIO pads.
|
* @note You can save up to 32 signals in a channel, but in the end, only the part of them (e.g. upper or lower 16 signals) can be output to the GPIO pads.
|
||||||
*
|
*
|
||||||
* @param[in] chan Handle of the debug probe channel
|
* @param[in] chan Handle of the debug probe channel
|
||||||
* @param[in] byte_idx Byte index of the signals, ranges from 0 to 3
|
* @param[in] byte_idx Byte index (HP: 0-3, LP: 0-1)
|
||||||
* @param[in] sig_group Signal group of the signal, ranges from 0 to 15
|
* @param[in] sig_group Signal group of the signal, ranges from 0 to 15
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK on success
|
* - ESP_OK on success
|
||||||
@@ -128,8 +134,8 @@ esp_err_t debug_probe_chan_add_signal_by_byte(debug_probe_channel_handle_t chan,
|
|||||||
* @param[in] unit Handle of the debug probe unit
|
* @param[in] unit Handle of the debug probe unit
|
||||||
* @param[in] chan0 Handle of the debug probe channel 0, whose output will be merged to the lower 16 signals of the unit output
|
* @param[in] chan0 Handle of the debug probe channel 0, whose output will be merged to the lower 16 signals of the unit output
|
||||||
* @param[in] split_of_chan0 Part of the channel 0 output to be merged
|
* @param[in] split_of_chan0 Part of the channel 0 output to be merged
|
||||||
* @param[in] chan1 Handle of the debug probe channel 1, whose output will be merged to the upper 16 signals of the unit output
|
* @param[in] chan1 Handle of the debug probe channel 1 for upper 16 bits; can be NULL to ignore upper16
|
||||||
* @param[in] split_of_chan1 Part of the channel 1 output to be merged
|
* @param[in] split_of_chan1 Part of the channel 1 output (ignored when chan1 is NULL)
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK on success
|
* - ESP_OK on success
|
||||||
* - ESP_ERR_INVALID_ARG if the parameters are invalid
|
* - ESP_ERR_INVALID_ARG if the parameters are invalid
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -20,11 +20,15 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SOC_DEBUG_PROBE_SUPPORTED
|
#if SOC_DEBUG_PROBE_SUPPORTED
|
||||||
#define DEBUG_PROBE_MAX_OUTPUT_WIDTH SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH
|
#define DEBUG_PROBE_MAX_OUTPUT_WIDTH SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH
|
||||||
|
#define DEBUG_PROBE_GPIO_NUMS_NONE { [0 ... (SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH - 1)] = -1 }
|
||||||
typedef soc_debug_probe_target_t debug_probe_target_t;
|
typedef soc_debug_probe_target_t debug_probe_target_t;
|
||||||
|
typedef soc_debug_probe_target_lp_t debug_probe_target_lp_t;
|
||||||
#else
|
#else
|
||||||
#define DEBUG_PROBE_MAX_OUTPUT_WIDTH 16
|
#define DEBUG_PROBE_MAX_OUTPUT_WIDTH 16
|
||||||
|
#define DEBUG_PROBE_GPIO_NUMS_NONE { [0 ... 15] = -1 }
|
||||||
typedef int debug_probe_target_t;
|
typedef int debug_probe_target_t;
|
||||||
|
typedef int debug_probe_target_lp_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -237,7 +237,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t digital_power_supply_wait_cycle;
|
uint16_t digital_power_supply_wait_cycle;
|
||||||
uint8_t min_slp_slow_clk_cycle;
|
uint8_t min_slp_slow_clk_cycle;
|
||||||
uint8_t analog_wait_target_cycle;
|
uint16_t analog_wait_target_cycle;
|
||||||
uint8_t digital_power_down_wait_cycle;
|
uint8_t digital_power_down_wait_cycle;
|
||||||
uint8_t digital_power_up_wait_cycle;
|
uint8_t digital_power_up_wait_cycle;
|
||||||
} pmu_lp_param_t;
|
} pmu_lp_param_t;
|
||||||
@@ -526,11 +526,21 @@ typedef struct pmu_sleep_machine_constant {
|
|||||||
// DCDC startup, which saves more power compared to waiting in the Active state.
|
// DCDC startup, which saves more power compared to waiting in the Active state.
|
||||||
#define PMU_HP_ANA_WAIT_TIME_PU_TOP_US (PMU_HP_ANA_WAIT_TIME_PD_TOP_US + PMU_REGDMA_S2A_WORK_TIME_US) // 945
|
#define PMU_HP_ANA_WAIT_TIME_PU_TOP_US (PMU_HP_ANA_WAIT_TIME_PD_TOP_US + PMU_REGDMA_S2A_WORK_TIME_US) // 945
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||||
|
#define PMU_LP_ANA_WAIT_TIME_US MAX(154, CONFIG_ESP_VBAT_MAIN_POWER_WAKEUP_ADVANCE_US)
|
||||||
|
#else
|
||||||
|
#define PMU_LP_ANA_WAIT_TIME_US 154
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PMU_SLEEP_MC_DEFAULT() { \
|
#define PMU_SLEEP_MC_DEFAULT() { \
|
||||||
.lp = { \
|
.lp = { \
|
||||||
.min_slp_time_us = 450, \
|
.min_slp_time_us = 450, \
|
||||||
.wakeup_wait_cycle = 4, \
|
.wakeup_wait_cycle = 4, \
|
||||||
.analog_wait_time_us = 154, \
|
.analog_wait_time_us = PMU_LP_ANA_WAIT_TIME_US, \
|
||||||
.xtal_wait_stable_time_us = 250, \
|
.xtal_wait_stable_time_us = 250, \
|
||||||
.clk_switch_cycle = 1, \
|
.clk_switch_cycle = 1, \
|
||||||
.clk_power_on_wait_cycle = 1, \
|
.clk_power_on_wait_cycle = 1, \
|
||||||
|
|||||||
@@ -200,6 +200,48 @@ menu "Power Supplier"
|
|||||||
help
|
help
|
||||||
The resistor value of charger circuit.
|
The resistor value of charger circuit.
|
||||||
|
|
||||||
|
config ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||||
|
bool "Control main power (ESP_3V3) enable via GPIO when VBAT powers deep sleep"
|
||||||
|
default n
|
||||||
|
depends on ESP_VBAT_INIT_AUTO && SOC_MAIN_POWER_CONTROL_SUPPORTED
|
||||||
|
help
|
||||||
|
When enabled, after the chip enters deep sleep and switches to VDD_BAT (VBAT)
|
||||||
|
power, ESP_VBAT_MAIN_POWER_CTRL_PIN is used to disable the main power (ESP_3V3)
|
||||||
|
enable. The main power is re-enabled in advance before wakeup.
|
||||||
|
|
||||||
|
config ESP_VBAT_MAIN_POWER_CTRL_PIN
|
||||||
|
int "GPIO for main power (ESP_3V3) enable"
|
||||||
|
default 2
|
||||||
|
range 0 3 if !RTC_CLK_SRC_EXT_CRYS
|
||||||
|
range 2 3 if RTC_CLK_SRC_EXT_CRYS
|
||||||
|
depends on ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||||
|
help
|
||||||
|
RTC GPIO used to enable/disable the main power rail (ESP_3V3) when VBAT is active.
|
||||||
|
|
||||||
|
config ESP_VBAT_MAIN_POWER_CTRL_PIN_INV
|
||||||
|
bool "Invert main power control pin output (Output high to enable power by default)"
|
||||||
|
default n
|
||||||
|
depends on ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||||
|
help
|
||||||
|
When enabled, the ESP_VBAT_MAIN_POWER_CTRL_PIN logic for the main power control
|
||||||
|
pin is inverted. (n: output high to enable power; y = output low to enable power).
|
||||||
|
|
||||||
|
config ESP_VBAT_MAIN_POWER_WAKEUP_ADVANCE_US
|
||||||
|
int "Main power enable advance time before wakeup (us)"
|
||||||
|
default 1000
|
||||||
|
range 0 1500 if !RTC_CLK_SRC_EXT_CRYS && ESP32P4_SELECTS_REV_LESS_V3
|
||||||
|
range 0 7500 if RTC_CLK_SRC_EXT_CRYS && ESP32P4_SELECTS_REV_LESS_V3
|
||||||
|
range 0 6000 if !RTC_CLK_SRC_EXT_CRYS && !ESP32P4_SELECTS_REV_LESS_V3
|
||||||
|
range 0 30000 if RTC_CLK_SRC_EXT_CRYS && !ESP32P4_SELECTS_REV_LESS_V3
|
||||||
|
depends on ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||||
|
help
|
||||||
|
Advance time in microseconds to assert main power (ESP_3V3) enable before the
|
||||||
|
chip starts the wakeup sequence and switches to main voltage supply. The delay
|
||||||
|
allows the external main power rail to reach target voltage before chip exits
|
||||||
|
deep sleep. Set this value to be greater than or equal to your main power
|
||||||
|
supply's startup/settling time (from enable assertion to stable output voltage).
|
||||||
|
If too small, the main rail may not be ready when the chip wakes, which can
|
||||||
|
cause brownout or unstable boot.
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "hal/vbat_hal.h"
|
#include "hal/vbat_hal.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_private/debug_probe.h"
|
||||||
#include "esp_private/esp_sleep_internal.h"
|
#include "esp_private/esp_sleep_internal.h"
|
||||||
#include "esp_private/startup_internal.h"
|
#include "esp_private/startup_internal.h"
|
||||||
#include "esp_private/rtc_ctrl.h"
|
#include "esp_private/rtc_ctrl.h"
|
||||||
@@ -46,6 +47,10 @@
|
|||||||
#define VBAT_CHARGER_HYSTERESIS_THRESHOLD_HIGH (VBAT_CHARGER_HYSTERESIS_THRESHOLD_LOW + (VBAT_CHARGER_FILTER_TIME_US * SOC_CLK_RC_FAST_FREQ_APPROX) / MHZ)
|
#define VBAT_CHARGER_HYSTERESIS_THRESHOLD_HIGH (VBAT_CHARGER_HYSTERESIS_THRESHOLD_LOW + (VBAT_CHARGER_FILTER_TIME_US * SOC_CLK_RC_FAST_FREQ_APPROX) / MHZ)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||||
|
#define ESP_3V3_CTRL_PIN CONFIG_ESP_VBAT_MAIN_POWER_CTRL_PIN
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ESP_VBAT_USE_RECHARGEABLE_BATTERY
|
#if CONFIG_ESP_VBAT_USE_RECHARGEABLE_BATTERY
|
||||||
#if (VBAT_CHARGER_RESISTOR_VALUE < 1000 || VBAT_CHARGER_RESISTOR_VALUE > 4500 || VBAT_CHARGER_RESISTOR_VALUE % 500 != 0)
|
#if (VBAT_CHARGER_RESISTOR_VALUE < 1000 || VBAT_CHARGER_RESISTOR_VALUE > 4500 || VBAT_CHARGER_RESISTOR_VALUE % 500 != 0)
|
||||||
#error "vbat charger resistor (ESP_VBAT_CHARGER_CIRCUIT_RESISTOR_VAL) must be between 1000 and 4500 ohms and must be a multiple of 500."
|
#error "vbat charger resistor (ESP_VBAT_CHARGER_CIRCUIT_RESISTOR_VAL) must be between 1000 and 4500 ohms and must be a multiple of 500."
|
||||||
@@ -54,7 +59,7 @@
|
|||||||
#if (VBAT_BROWNOUT_DET_LVL >= VBAT_CHARGE_DET_LVL_LOW)
|
#if (VBAT_BROWNOUT_DET_LVL >= VBAT_CHARGE_DET_LVL_LOW)
|
||||||
#error "vbat charger low threshold is equal or lower than vbat brownout threshold, please put vbat brownout threshold lower than vbat charger low threshold"
|
#error "vbat charger low threshold is equal or lower than vbat brownout threshold, please put vbat brownout threshold lower than vbat charger low threshold"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif // CONFIG_ESP_VBAT_INIT_AUTO
|
||||||
|
|
||||||
ESP_LOG_ATTR_TAG(TAG, "VBAT");
|
ESP_LOG_ATTR_TAG(TAG, "VBAT");
|
||||||
#endif
|
#endif
|
||||||
@@ -171,6 +176,29 @@ esp_err_t esp_vbat_init(void)
|
|||||||
esp_sleep_sub_mode_force_disable(ESP_SLEEP_VBAT_POWER_DEEPSLEEP_MODE);
|
esp_sleep_sub_mode_force_disable(ESP_SLEEP_VBAT_POWER_DEEPSLEEP_MODE);
|
||||||
esp_sleep_sub_mode_config(ESP_SLEEP_VBAT_POWER_DEEPSLEEP_MODE, true);
|
esp_sleep_sub_mode_config(ESP_SLEEP_VBAT_POWER_DEEPSLEEP_MODE, true);
|
||||||
esp_sleep_enable_vbat_under_volt_wakeup();
|
esp_sleep_enable_vbat_under_volt_wakeup();
|
||||||
|
|
||||||
|
#if CONFIG_ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP
|
||||||
|
if (esp_reset_reason() != ESP_RST_DEEPSLEEP) {
|
||||||
|
debug_probe_unit_handle_t lp_probe_hdl;
|
||||||
|
debug_probe_unit_config_t unit_config = {
|
||||||
|
.unit_id = DEBUG_PROBE_UNIT_LP,
|
||||||
|
.probe_out_gpio_nums = DEBUG_PROBE_GPIO_NUMS_NONE,
|
||||||
|
};
|
||||||
|
debug_probe_channel_config_t chan_config = {0};
|
||||||
|
debug_probe_channel_handle_t lp_probe_channel_hdl;
|
||||||
|
chan_config.target_module.lp_target = DEBUG_PROBE_TARGET_LP_PMU;
|
||||||
|
unit_config.probe_out_gpio_nums[VBAT_LL_LP_SLEEP_PROBE_ID] = ESP_3V3_CTRL_PIN;
|
||||||
|
#if !CONFIG_ESP_VBAT_MAIN_POWER_CTRL_PIN_INV
|
||||||
|
unit_config.probe_out_inv_mask |= BIT(VBAT_LL_LP_SLEEP_PROBE_ID);
|
||||||
|
#endif
|
||||||
|
ESP_ERROR_CHECK(debug_probe_new_unit(&unit_config, &lp_probe_hdl));
|
||||||
|
ESP_ERROR_CHECK(debug_probe_new_channel(lp_probe_hdl, &chan_config, &lp_probe_channel_hdl));
|
||||||
|
ESP_ERROR_CHECK(debug_probe_chan_add_signal_by_byte(lp_probe_channel_hdl, 1, DEBUG_PROBE_TARGET_LP_PMU));
|
||||||
|
ESP_ERROR_CHECK(debug_probe_unit_merge16(lp_probe_hdl, lp_probe_channel_hdl, DEBUG_PROBE_SPLIT_UPPER16, NULL, 0));
|
||||||
|
}
|
||||||
|
// The LP Probe & LP IOMUX pathways depend on the LP_PERIPH power domain.
|
||||||
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||||
|
#endif
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+19
-14
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -15,21 +15,29 @@
|
|||||||
|
|
||||||
TEST_CASE("debug probe install & uninstall", "[debug_probe]")
|
TEST_CASE("debug probe install & uninstall", "[debug_probe]")
|
||||||
{
|
{
|
||||||
debug_probe_unit_config_t unit_config = {
|
|
||||||
.probe_out_gpio_nums = {0},
|
|
||||||
};
|
|
||||||
debug_probe_unit_handle_t probe_units[SOC_DEBUG_PROBE_NUM_UNIT] = {0};
|
debug_probe_unit_handle_t probe_units[SOC_DEBUG_PROBE_NUM_UNIT] = {0};
|
||||||
printf("install debug probe exhaustively\r\n");
|
printf("install debug probe exhaustively\r\n");
|
||||||
for (int i = 0; i < SOC_DEBUG_PROBE_NUM_UNIT; i++) {
|
for (int i = 0; i < SOC_DEBUG_PROBE_NUM_UNIT; i++) {
|
||||||
|
debug_probe_unit_config_t unit_config = {
|
||||||
|
.unit_id = (debug_probe_unit_id_t)i,
|
||||||
|
.probe_out_gpio_nums = {0},
|
||||||
|
};
|
||||||
TEST_ESP_OK(debug_probe_new_unit(&unit_config, &probe_units[i]));
|
TEST_ESP_OK(debug_probe_new_unit(&unit_config, &probe_units[i]));
|
||||||
}
|
}
|
||||||
|
debug_probe_unit_config_t unit_config = {
|
||||||
|
.unit_id = DEBUG_PROBE_UNIT_HP,
|
||||||
|
.probe_out_gpio_nums = {0},
|
||||||
|
};
|
||||||
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, debug_probe_new_unit(&unit_config, &probe_units[0]));
|
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, debug_probe_new_unit(&unit_config, &probe_units[0]));
|
||||||
|
|
||||||
debug_probe_channel_config_t chan_config = {
|
|
||||||
.target_module = 1,
|
|
||||||
};
|
|
||||||
debug_probe_channel_handle_t probe_chans[SOC_DEBUG_PROBE_NUM_UNIT][DEBUG_PROBE_LL_CHANNELS_PER_UNIT] = {0};
|
debug_probe_channel_handle_t probe_chans[SOC_DEBUG_PROBE_NUM_UNIT][DEBUG_PROBE_LL_CHANNELS_PER_UNIT] = {0};
|
||||||
for (int i = 0; i < SOC_DEBUG_PROBE_NUM_UNIT; i++) {
|
for (int i = 0; i < SOC_DEBUG_PROBE_NUM_UNIT; i++) {
|
||||||
|
debug_probe_channel_config_t chan_config = {0};
|
||||||
|
if (i == 0) {
|
||||||
|
chan_config.target_module.hp_target = DEBUG_PROBE_TARGET_AXI_GDMA;
|
||||||
|
} else {
|
||||||
|
chan_config.target_module.lp_target = DEBUG_PROBE_TARGET_LP_PMU;
|
||||||
|
}
|
||||||
for (int j = 0; j < DEBUG_PROBE_LL_CHANNELS_PER_UNIT; j++) {
|
for (int j = 0; j < DEBUG_PROBE_LL_CHANNELS_PER_UNIT; j++) {
|
||||||
TEST_ESP_OK(debug_probe_new_channel(probe_units[i], &chan_config, &probe_chans[i][j]));
|
TEST_ESP_OK(debug_probe_new_channel(probe_units[i], &chan_config, &probe_chans[i][j]));
|
||||||
}
|
}
|
||||||
@@ -47,10 +55,8 @@ TEST_CASE("debug probe install & uninstall", "[debug_probe]")
|
|||||||
TEST_CASE("debug probe read", "[debug_probe]")
|
TEST_CASE("debug probe read", "[debug_probe]")
|
||||||
{
|
{
|
||||||
debug_probe_unit_config_t unit_config = {
|
debug_probe_unit_config_t unit_config = {
|
||||||
.probe_out_gpio_nums = {
|
.unit_id = DEBUG_PROBE_UNIT_HP,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
.probe_out_gpio_nums = DEBUG_PROBE_GPIO_NUMS_NONE,
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
debug_probe_unit_handle_t probe_unit = NULL;
|
debug_probe_unit_handle_t probe_unit = NULL;
|
||||||
TEST_ESP_OK(debug_probe_new_unit(&unit_config, &probe_unit));
|
TEST_ESP_OK(debug_probe_new_unit(&unit_config, &probe_unit));
|
||||||
@@ -58,9 +64,8 @@ TEST_CASE("debug probe read", "[debug_probe]")
|
|||||||
// allocate two channels from the unit, each channel monitor different target module
|
// allocate two channels from the unit, each channel monitor different target module
|
||||||
debug_probe_channel_handle_t probe_chans[2] = {0};
|
debug_probe_channel_handle_t probe_chans[2] = {0};
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
debug_probe_channel_config_t chan_config = {
|
debug_probe_channel_config_t chan_config = {0};
|
||||||
.target_module = i + 1,
|
chan_config.target_module.hp_target = (debug_probe_target_t)(i + 1);
|
||||||
};
|
|
||||||
TEST_ESP_OK(debug_probe_new_channel(probe_unit, &chan_config, &probe_chans[i]));
|
TEST_ESP_OK(debug_probe_new_channel(probe_unit, &chan_config, &probe_chans[i]));
|
||||||
|
|
||||||
// group15[7:0] contains the debug target module ID
|
// group15[7:0] contains the debug target module ID
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "hal/misc.h"
|
#include "hal/misc.h"
|
||||||
#include "hal/assert.h"
|
#include "hal/assert.h"
|
||||||
#include "soc/debug_probe_targets.h"
|
|
||||||
#include "soc/hp_system_struct.h"
|
#include "soc/hp_system_struct.h"
|
||||||
|
#include "soc/lp_system_struct.h"
|
||||||
#include "hal/debug_probe_types.h"
|
#include "hal/debug_probe_types.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,39 +29,58 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* @brief Enable the debug probe module
|
* @brief Enable the debug probe module
|
||||||
*
|
*
|
||||||
|
* @param unit_id unit identifier, see debug_probe_unit_id_t
|
||||||
* @param en true: enable, false: disable
|
* @param en true: enable, false: disable
|
||||||
*/
|
*/
|
||||||
static inline void debug_probe_ll_enable_unit(int unit_id, bool en)
|
static inline void debug_probe_ll_enable_unit(debug_probe_unit_id_t unit_id, bool en)
|
||||||
{
|
{
|
||||||
HP_SYSTEM.probea_ctrl.reg_probe_global_en = en;
|
if (unit_id == DEBUG_PROBE_UNIT_HP) {
|
||||||
|
HP_SYSTEM.probea_ctrl.reg_probe_global_en = en;
|
||||||
|
} else {
|
||||||
|
LP_SYS.lp_probea_ctrl.probe_global_en = en;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enable a specific channel in the debug probe unit
|
* @brief Enable a specific channel in the debug probe unit
|
||||||
*
|
*
|
||||||
|
* @param unit_id unit identifier, see debug_probe_unit_id_t
|
||||||
* @param channel channel number (only support 0 and 1)
|
* @param channel channel number (only support 0 and 1)
|
||||||
* @param en true: enable, false: disable
|
* @param en true: enable, false: disable
|
||||||
*/
|
*/
|
||||||
static inline void debug_probe_ll_enable_channel(int unit_id, int channel, bool en)
|
static inline void debug_probe_ll_enable_channel(debug_probe_unit_id_t unit_id, int channel, bool en)
|
||||||
{
|
{
|
||||||
// channel 0 is always enabled
|
// channel 0 is always enabled
|
||||||
if (channel == 1) {
|
if (channel == 1) {
|
||||||
HP_SYSTEM.probeb_ctrl.reg_probe_b_en = en;
|
if (unit_id == DEBUG_PROBE_UNIT_HP) {
|
||||||
|
HP_SYSTEM.probeb_ctrl.reg_probe_b_en = en;
|
||||||
|
} else {
|
||||||
|
LP_SYS.lp_probeb_ctrl.probe_b_en = en;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the target module for a probe channel
|
* @brief Set the target module for a probe channel
|
||||||
*
|
*
|
||||||
|
* @param unit_id unit identifier, see debug_probe_unit_id_t
|
||||||
* @param channel channel number (only support 0 and 1)
|
* @param channel channel number (only support 0 and 1)
|
||||||
* @param target_module target module, see soc_debug_probe_target_t
|
* @param target_module HP: soc_debug_probe_target_t, LP: soc_debug_probe_target_lp_t
|
||||||
*/
|
*/
|
||||||
static inline void debug_probe_ll_channel_set_target_module(int unit_id, uint8_t channel, soc_debug_probe_target_t target_module)
|
static inline void debug_probe_ll_channel_set_target_module(debug_probe_unit_id_t unit_id, uint8_t channel, uint8_t target_module)
|
||||||
{
|
{
|
||||||
if (channel == 0) {
|
if (channel == 0) {
|
||||||
HP_SYSTEM.probea_ctrl.reg_probe_a_top_sel = target_module;
|
if (unit_id == DEBUG_PROBE_UNIT_HP) {
|
||||||
|
HP_SYSTEM.probea_ctrl.reg_probe_a_top_sel = target_module;
|
||||||
|
} else {
|
||||||
|
LP_SYS.lp_probea_ctrl.probe_a_top_sel = target_module;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
HP_SYSTEM.probeb_ctrl.reg_probe_b_top_sel = target_module;
|
if (unit_id == DEBUG_PROBE_UNIT_HP) {
|
||||||
|
HP_SYSTEM.probeb_ctrl.reg_probe_b_top_sel = target_module;
|
||||||
|
} else {
|
||||||
|
LP_SYS.lp_probeb_ctrl.probe_b_top_sel = target_module;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,14 +93,24 @@ static inline void debug_probe_ll_channel_set_target_module(int unit_id, uint8_t
|
|||||||
* @param sig_byte_idx signal byte index (0-3)
|
* @param sig_byte_idx signal byte index (0-3)
|
||||||
* @param sig_group signal group (0-15)
|
* @param sig_group signal group (0-15)
|
||||||
*/
|
*/
|
||||||
static inline void debug_probe_ll_channel_add_signal_group(int unit_id, uint8_t channel, uint8_t sig_byte_idx, uint8_t sig_group)
|
static inline void debug_probe_ll_channel_add_signal_group(debug_probe_unit_id_t unit_id, uint8_t channel, uint8_t sig_byte_idx, uint8_t sig_group)
|
||||||
{
|
{
|
||||||
if (channel == 0) {
|
if (unit_id == DEBUG_PROBE_UNIT_HP) {
|
||||||
HP_SYSTEM.probea_ctrl.reg_probe_a_mod_sel &= ~(0xf << (sig_byte_idx * 4));
|
if (channel == 0) {
|
||||||
HP_SYSTEM.probea_ctrl.reg_probe_a_mod_sel |= (sig_group << (sig_byte_idx * 4));
|
HP_SYSTEM.probea_ctrl.reg_probe_a_mod_sel &= ~(0xf << (sig_byte_idx * 4));
|
||||||
|
HP_SYSTEM.probea_ctrl.reg_probe_a_mod_sel |= (sig_group << (sig_byte_idx * 4));
|
||||||
|
} else {
|
||||||
|
HP_SYSTEM.probeb_ctrl.reg_probe_b_mod_sel &= ~(0xf << (sig_byte_idx * 4));
|
||||||
|
HP_SYSTEM.probeb_ctrl.reg_probe_b_mod_sel |= (sig_group << (sig_byte_idx * 4));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
HP_SYSTEM.probeb_ctrl.reg_probe_b_mod_sel &= ~(0xf << (sig_byte_idx * 4));
|
if (channel == 0) {
|
||||||
HP_SYSTEM.probeb_ctrl.reg_probe_b_mod_sel |= (sig_group << (sig_byte_idx * 4));
|
LP_SYS.lp_probea_ctrl.probe_a_mod_sel &= ~(0xf << (sig_byte_idx * 4));
|
||||||
|
LP_SYS.lp_probea_ctrl.probe_a_mod_sel |= (sig_group << (sig_byte_idx * 4));
|
||||||
|
} else {
|
||||||
|
LP_SYS.lp_probeb_ctrl.probe_b_mod_sel &= ~(0xf << (sig_byte_idx * 4));
|
||||||
|
LP_SYS.lp_probeb_ctrl.probe_b_mod_sel |= (sig_group << (sig_byte_idx * 4));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,18 +119,27 @@ static inline void debug_probe_ll_channel_add_signal_group(int unit_id, uint8_t
|
|||||||
*
|
*
|
||||||
* @param part where does the probe_top_out[15:0] come from
|
* @param part where does the probe_top_out[15:0] come from
|
||||||
*/
|
*/
|
||||||
static inline void debug_probe_ll_set_lower16_output(int unit_id, int channel, debug_probe_split_u16_t part)
|
static inline void debug_probe_ll_set_lower16_output(debug_probe_unit_id_t unit_id, int channel, debug_probe_split_u16_t part)
|
||||||
{
|
{
|
||||||
HP_SYSTEM.probea_ctrl.reg_probe_l_sel = channel * 2 + DEBUG_PROBE_LL_PART_TO_REG_VAL(part);
|
uint8_t val = (uint8_t)(channel * 2 + DEBUG_PROBE_LL_PART_TO_REG_VAL(part));
|
||||||
|
if (unit_id == DEBUG_PROBE_UNIT_HP) {
|
||||||
|
HP_SYSTEM.probea_ctrl.reg_probe_l_sel = val;
|
||||||
|
} else {
|
||||||
|
LP_SYS.lp_probea_ctrl.probe_l_sel = val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the upper 16 bits of the probe output
|
* @brief Set the upper 16 bits of the probe output
|
||||||
*
|
*
|
||||||
* @param part where does the probe_top_out[31:16] come from
|
* @param part where does the probe_top_out[31:16] come from
|
||||||
|
* @note No-op for LP unit: only 16 bits are routed to LP GPIO, so upper 16 selection has no effect.
|
||||||
*/
|
*/
|
||||||
static inline void debug_probe_ll_set_upper16_output(int unit_id, int channel, debug_probe_split_u16_t part)
|
static inline void debug_probe_ll_set_upper16_output(debug_probe_unit_id_t unit_id, int channel, debug_probe_split_u16_t part)
|
||||||
{
|
{
|
||||||
|
if (unit_id != DEBUG_PROBE_UNIT_HP) {
|
||||||
|
return; /* LP has only 16 bits to GPIO; probe_top_out[31:16] is not routed */
|
||||||
|
}
|
||||||
HP_SYSTEM.probea_ctrl.reg_probe_h_sel = channel * 2 + DEBUG_PROBE_LL_PART_TO_REG_VAL(part);
|
HP_SYSTEM.probea_ctrl.reg_probe_h_sel = channel * 2 + DEBUG_PROBE_LL_PART_TO_REG_VAL(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,9 +150,13 @@ static inline void debug_probe_ll_set_upper16_output(int unit_id, int channel,
|
|||||||
*
|
*
|
||||||
* @return the value that currently being probed
|
* @return the value that currently being probed
|
||||||
*/
|
*/
|
||||||
static inline uint32_t debug_probe_ll_read_output(int unit_id)
|
static inline uint32_t debug_probe_ll_read_output(debug_probe_unit_id_t unit_id)
|
||||||
{
|
{
|
||||||
return HP_SYSTEM.probe_out.reg_probe_top_out;
|
if (unit_id == DEBUG_PROBE_UNIT_HP) {
|
||||||
|
return HP_SYSTEM.probe_out.reg_probe_top_out;
|
||||||
|
} else {
|
||||||
|
return LP_SYS.lp_probe_out.probe_top_out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -10,6 +10,15 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Debug probe unit identifier (HP vs LP)
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
DEBUG_PROBE_UNIT_HP = 0,
|
||||||
|
DEBUG_PROBE_UNIT_LP = 1,
|
||||||
|
} debug_probe_unit_id_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The 32bit debug probe output can be split into two 16bit parts
|
* @brief The 32bit debug probe output can be split into two 16bit parts
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "soc/gpio_sig_map.h"
|
#include "soc/gpio_sig_map.h"
|
||||||
|
#include "soc/lp_gpio_sig_map.h"
|
||||||
#include "soc/debug_probe_periph.h"
|
#include "soc/debug_probe_periph.h"
|
||||||
|
|
||||||
const debug_probe_signal_conn_t debug_probe_periph_signals = {
|
const debug_probe_signal_conn_t debug_probe_periph_signals = {
|
||||||
@@ -28,6 +29,26 @@ const debug_probe_signal_conn_t debug_probe_periph_signals = {
|
|||||||
[14] = HP_PROBE_TOP_OUT14_IDX,
|
[14] = HP_PROBE_TOP_OUT14_IDX,
|
||||||
[15] = HP_PROBE_TOP_OUT15_IDX,
|
[15] = HP_PROBE_TOP_OUT15_IDX,
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
.out_sig = {
|
||||||
|
[0] = LP_PROBE_TOP_OUT0_IDX,
|
||||||
|
[1] = LP_PROBE_TOP_OUT1_IDX,
|
||||||
|
[2] = LP_PROBE_TOP_OUT2_IDX,
|
||||||
|
[3] = LP_PROBE_TOP_OUT3_IDX,
|
||||||
|
[4] = LP_PROBE_TOP_OUT4_IDX,
|
||||||
|
[5] = LP_PROBE_TOP_OUT5_IDX,
|
||||||
|
[6] = LP_PROBE_TOP_OUT6_IDX,
|
||||||
|
[7] = LP_PROBE_TOP_OUT7_IDX,
|
||||||
|
[8] = LP_PROBE_TOP_OUT8_IDX,
|
||||||
|
[9] = LP_PROBE_TOP_OUT9_IDX,
|
||||||
|
[10] = LP_PROBE_TOP_OUT10_IDX,
|
||||||
|
[11] = LP_PROBE_TOP_OUT11_IDX,
|
||||||
|
[12] = LP_PROBE_TOP_OUT12_IDX,
|
||||||
|
[13] = LP_PROBE_TOP_OUT13_IDX,
|
||||||
|
[14] = LP_PROBE_TOP_OUT14_IDX,
|
||||||
|
[15] = LP_PROBE_TOP_OUT15_IDX,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -745,7 +745,7 @@ config SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER
|
|||||||
|
|
||||||
config SOC_DEBUG_PROBE_NUM_UNIT
|
config SOC_DEBUG_PROBE_NUM_UNIT
|
||||||
int
|
int
|
||||||
default 1
|
default 2
|
||||||
|
|
||||||
config SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH
|
config SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH
|
||||||
int
|
int
|
||||||
@@ -1811,6 +1811,10 @@ config SOC_PM_RETENTION_MODULE_NUM
|
|||||||
int
|
int
|
||||||
default 64
|
default 64
|
||||||
|
|
||||||
|
config SOC_MAIN_POWER_CONTROL_SUPPORTED
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
|
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
*/
|
*/
|
||||||
@@ -49,6 +49,23 @@ typedef enum {
|
|||||||
DEBUG_PROBE_TARGET_PVT = 30, // PVT
|
DEBUG_PROBE_TARGET_PVT = 30, // PVT
|
||||||
} soc_debug_probe_target_t;
|
} soc_debug_probe_target_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief LP probe target module (probe_a_top_sel 0..10)
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
DEBUG_PROBE_TARGET_LP_PMU = 0, // LP PMU
|
||||||
|
DEBUG_PROBE_TARGET_LP_TCM_RAM = 1, // LP TCM RAM
|
||||||
|
DEBUG_PROBE_TARGET_LP_TCM_ROM = 2, // LP TCM ROM
|
||||||
|
DEBUG_PROBE_TARGET_LP_CORE = 3, // LP Core
|
||||||
|
DEBUG_PROBE_TARGET_LP_ADC = 4, // LP ADC
|
||||||
|
DEBUG_PROBE_TARGET_LP_SPI = 5, // LP SPI
|
||||||
|
DEBUG_PROBE_TARGET_LP_TOUCH = 6, // LP Touch
|
||||||
|
DEBUG_PROBE_TARGET_LP_ANA_PERI = 7, // LP Analog Peripherals
|
||||||
|
DEBUG_PROBE_TARGET_LP_AON_CLKRST = 8, // LP AON Clock/Reset
|
||||||
|
DEBUG_PROBE_TARGET_LP_SYS_MISC = 9, // LP System Misc
|
||||||
|
DEBUG_PROBE_TARGET_LP_SYS_PROBE_IN = 10, // LP System Probe In
|
||||||
|
} soc_debug_probe_target_lp_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -285,7 +285,7 @@
|
|||||||
#define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (2)
|
#define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (2)
|
||||||
#define SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER (1)
|
#define SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER (1)
|
||||||
|
|
||||||
#define SOC_DEBUG_PROBE_NUM_UNIT (1U) // Number of debug probe units
|
#define SOC_DEBUG_PROBE_NUM_UNIT (2U) // Unit 0: HP probe, Unit 1: LP probe
|
||||||
#define SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH (16) // Maximum width of the debug probe output in each unit
|
#define SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH (16) // Maximum width of the debug probe output in each unit
|
||||||
|
|
||||||
/*-------------------------- RTCIO CAPS --------------------------------------*/
|
/*-------------------------- RTCIO CAPS --------------------------------------*/
|
||||||
@@ -686,6 +686,8 @@
|
|||||||
|
|
||||||
#define SOC_PM_RETENTION_MODULE_NUM (64)
|
#define SOC_PM_RETENTION_MODULE_NUM (64)
|
||||||
|
|
||||||
|
#define SOC_MAIN_POWER_CONTROL_SUPPORTED (1) /*!<Supports outputting an enable signal to control the power-on and power-off of the main power supply when powered by VBAT.*/
|
||||||
|
|
||||||
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
|
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
|
||||||
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)
|
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,8 @@ examples/lowpower/power_management:
|
|||||||
examples/lowpower/vbat:
|
examples/lowpower/vbat:
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_VBAT_SUPPORTED == 1
|
- if: SOC_VBAT_SUPPORTED == 1
|
||||||
|
disable:
|
||||||
|
- if: IDF_TARGET in ["esp32h2"] and CONFIG_NAME == "mainpower_ctrl"
|
||||||
disable_test:
|
disable_test:
|
||||||
- if: IDF_TARGET in ["esp32h2"]
|
- if: IDF_TARGET in ["esp32h2"]
|
||||||
temporary: true
|
temporary: true
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ This example demonstrates the ESP backup battery power supply solution, which ha
|
|||||||
- Support battery voltage detection, wake up the chip and switch to the main power supply when undervoltage occurs.
|
- Support battery voltage detection, wake up the chip and switch to the main power supply when undervoltage occurs.
|
||||||
- Support battery charging, automatically stop charging when threshold voltage is reached, and charging current can be configured.
|
- Support battery charging, automatically stop charging when threshold voltage is reached, and charging current can be configured.
|
||||||
- Supports selection of chip status when charging the battery, options include keep active, entering lightsleep or entering deepsleep.
|
- Supports selection of chip status when charging the battery, options include keep active, entering lightsleep or entering deepsleep.
|
||||||
|
- Optional main power (ESP_3V3) control via GPIO when in deep sleep on VBAT: turn off main power after switching to VBAT, and turn it on again in advance before wakeup (configurable advance time).
|
||||||
|
|
||||||
## How to use example
|
## How to use example
|
||||||
|
|
||||||
@@ -48,6 +49,44 @@ idf.py menuconfig
|
|||||||
- The chip state while waiting for battery charging the battery can be selected by `Example Configuration → Configure the chip state while waiting for battery charging`.
|
- The chip state while waiting for battery charging the battery can be selected by `Example Configuration → Configure the chip state while waiting for battery charging`.
|
||||||
- The period to check whether the battery has been charged done can be selected by `Battery charging done check period (in seconds)`.
|
- The period to check whether the battery has been charged done can be selected by `Battery charging done check period (in seconds)`.
|
||||||
|
|
||||||
|
#### Main power control when running on VBAT (ESP32-P4)
|
||||||
|
|
||||||
|
When the chip is in deep sleep and powered by VBAT, the main power rail (ESP_3V3) may be turned off to reduce power consumption (for example, when it also supplies other peripherals on the board). ESP32-P4 supports controlling the main power enable via an RTC GPIO so that the rail is disabled after switching to VBAT and re-enabled in advance before wakeup, allowing the supply to stabilize before the chip exits deep sleep and switches back to main supply.
|
||||||
|
|
||||||
|
Application scenario — circuit connections:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────┐ ┌───────────────────────────────────┐
|
||||||
|
│ Button │ VBAT │ ESP32-P4 │
|
||||||
|
│ Battery ├──────>│ VBAT │
|
||||||
|
└──────────────┘ │ │
|
||||||
|
│ ESP_3V3 (RTC IO)│
|
||||||
|
└───────────────────────────────┬───┘
|
||||||
|
^ │ Enable (power ctrl)
|
||||||
|
Vout (3.3V) │ v
|
||||||
|
┌─────┴───────────────────────────────┐
|
||||||
|
│ Main Power Enable Pin │
|
||||||
|
└─────────────────────────────────────┘
|
||||||
|
│ 3.3V
|
||||||
|
v
|
||||||
|
┌───────────────────┐
|
||||||
|
│ Other Circuits │
|
||||||
|
└───────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Button Battery** → ESP32-P4 **VBAT**: backup supply during deep sleep, keeps RTC alive.
|
||||||
|
- **Power Module** Vout → ESP32-P4 **ESP_3V3** and **Other Circuits**: main 3.3 V rail.
|
||||||
|
- ESP32-P4 **GPIO (RTC IO 0~3)** → Power Module **Enable**: the chip disables main power after entering deep sleep on VBAT, and re-enables it in advance before wakeup.
|
||||||
|
|
||||||
|
Configuration (under `Component config → Hardware Settings → Power Supplier → RTC Backup Battery`):
|
||||||
|
|
||||||
|
- Enable the feature: **Control main power (ESP_3V3) enable via GPIO when VBAT powers deep sleep**.
|
||||||
|
- Select the control pin: **GPIO for main power (ESP_3V3) enable** — RTC GPIO 0~3 (or 2~3 only when the RTC clock source is the external 32 kHz crystal, because GPIO0/1 are then reserved).
|
||||||
|
- Set output polarity: **Invert main power control pin output** — enable this if the main power is enabled by a low level (active-low).
|
||||||
|
- Set the wakeup advance time: **Main power enable advance time before wakeup (us)** — the time in microseconds by which the main power enable is asserted before the chip starts the wakeup sequence. This value must be at least the main power supply’s startup/settling time (from enable assertion to stable output); otherwise the chip may brown out or boot unstably after wake.
|
||||||
|
|
||||||
|
This feature requires a hardware design in which the main power enable is driven by the chosen RTC GPIO (for example, via an external FET or the enable pin of a regulator).
|
||||||
|
|
||||||
### Build and Flash
|
### Build and Flash
|
||||||
|
|
||||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CONFIG_ESP_VBAT_CONTROL_MAIN_POWER_IN_DSLP=y
|
||||||
|
CONFIG_ESP_VBAT_MAIN_POWER_CTRL_PIN=3
|
||||||
Reference in New Issue
Block a user