feat(esp_hw_support): support LP_Probe in debug probe driver & sig inversion

This commit is contained in:
wuzhenghui
2026-03-18 17:02:03 +08:00
parent 6b1e0e87c6
commit 5c2e3b768e
10 changed files with 239 additions and 80 deletions

View File

@@ -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
*/
@@ -16,6 +16,10 @@
#include "soc/soc_caps.h"
#include "soc/debug_probe_periph.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 "esp_private/debug_probe.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;
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
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 {
@@ -45,9 +50,31 @@ typedef struct debug_probe_platform_t {
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)
{
int unit_id = unit->unit_id;
debug_probe_unit_id_t unit_id = unit->unit_id;
// remove the unit from the platform
_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
debug_probe_ll_enable_unit(unit_id, false);
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(unit);
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)
{
debug_probe_unit_t *unit = NULL;
int unit_id = -1;
ESP_RETURN_ON_FALSE(config && out_handle, ESP_ERR_INVALID_ARG, TAG, "invalid args");
debug_probe_unit_id_t unit_id = config->unit_id;
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);
for (int i = 0; i < SOC_DEBUG_PROBE_NUM_UNIT; i++) {
if (s_platform.units[i] == NULL) {
unit_id = i;
unit = calloc(1, sizeof(debug_probe_unit_t));
s_platform.units[i] = unit;
break;
}
if (s_platform.units[unit_id] != NULL) {
_lock_release(&s_platform.mutex);
ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_FOUND, TAG, "unit slot in use");
}
unit = calloc(1, sizeof(debug_probe_unit_t));
if (unit) {
s_platform.units[unit_id] = unit;
}
_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");
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
esp_err_t ret = ESP_OK;
for (int i = 0; i < SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH; i++) {
if (config->probe_out_gpio_nums[i] >= 0) {
gpio_func_sel(config->probe_out_gpio_nums[i], PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(config->probe_out_gpio_nums[i],
debug_probe_periph_signals.units[unit_id].out_sig[i],
false, false);
int pin = config->probe_out_gpio_nums[i];
if (pin >= 0) {
bool out_inv = !!(config->probe_out_inv_mask & BIT(i));
ret = connect_probe_out_to_pin(unit_id, pin, (unsigned)i, out_inv);
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->probe_out_inv_mask = config->probe_out_inv_mask;
// enable the probe unit
debug_probe_ll_enable_unit(unit_id, true);
*out_handle = unit;
return ESP_OK;
return ret;
}
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)
{
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;
// 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;
int chan_id = -1;
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
_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;
// 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);
*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_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;
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);
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,
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(chan0->unit == unit && chan1->unit == unit, ESP_ERR_INVALID_ARG, TAG, "chan not belong to unit");
int unit_id = unit->unit_id;
ESP_RETURN_ON_FALSE(unit && chan0, ESP_ERR_INVALID_ARG, TAG, "invalid args");
ESP_RETURN_ON_FALSE(chan0->unit == unit, ESP_ERR_INVALID_ARG, TAG, "chan0 not belong to unit");
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_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;
}
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");
int unit_id = unit->unit_id;
*value = debug_probe_ll_read_output(unit_id);
debug_probe_unit_id_t unit_id = unit->unit_id;
uint32_t raw = debug_probe_ll_read_output(unit_id);
*value = raw ^ unit->probe_out_inv_mask;
return ESP_OK;
}

View File

@@ -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
*/
@@ -30,7 +30,9 @@ typedef struct debug_probe_channel_t *debug_probe_channel_handle_t;
* @brief Configuration for a debug probe unit
*/
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;
/**
@@ -60,9 +62,13 @@ esp_err_t debug_probe_del_unit(debug_probe_unit_handle_t unit);
/**
* @brief Configuration for a debug probe channel
* @note Use hp_target for HP unit, lp_target for LP unit
*/
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;
/**
@@ -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.
*
* @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
* @return
* - 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] 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] chan1 Handle of the debug probe channel 1, whose output will be merged to the upper 16 signals of the unit output
* @param[in] split_of_chan1 Part of the channel 1 output to be merged
* @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 (ignored when chan1 is NULL)
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the parameters are invalid

View File

@@ -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
*/
@@ -20,11 +20,15 @@ extern "C" {
#endif
#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_lp_t debug_probe_target_lp_t;
#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_lp_t;
#endif
#ifdef __cplusplus

View File

@@ -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
*/
@@ -15,21 +15,29 @@
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};
printf("install debug probe exhaustively\r\n");
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]));
}
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]));
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};
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++) {
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]")
{
debug_probe_unit_config_t unit_config = {
.probe_out_gpio_nums = {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
}
.unit_id = DEBUG_PROBE_UNIT_HP,
.probe_out_gpio_nums = DEBUG_PROBE_GPIO_NUMS_NONE,
};
debug_probe_unit_handle_t probe_unit = NULL;
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
debug_probe_channel_handle_t probe_chans[2] = {0};
for (int i = 0; i < 2; i++) {
debug_probe_channel_config_t chan_config = {
.target_module = i + 1,
};
debug_probe_channel_config_t chan_config = {0};
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]));
// group15[7:0] contains the debug target module ID

View File

@@ -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
*/
@@ -10,8 +10,8 @@
#include <stdbool.h>
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/debug_probe_targets.h"
#include "soc/hp_system_struct.h"
#include "soc/lp_system_struct.h"
#include "hal/debug_probe_types.h"
/**
@@ -29,39 +29,58 @@ extern "C" {
/**
* @brief Enable the debug probe module
*
* @param unit_id unit identifier, see debug_probe_unit_id_t
* @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
*
* @param unit_id unit identifier, see debug_probe_unit_id_t
* @param channel channel number (only support 0 and 1)
* @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
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
*
* @param unit_id unit identifier, see debug_probe_unit_id_t
* @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) {
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 {
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_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) {
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));
if (unit_id == DEBUG_PROBE_UNIT_HP) {
if (channel == 0) {
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 {
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));
if (channel == 0) {
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
*/
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
*
* @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);
}
@@ -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
*/
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

View File

@@ -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
*/
@@ -10,6 +10,15 @@
extern "C" {
#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
*/

View File

@@ -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
*/
#include "soc/gpio_sig_map.h"
#include "soc/lp_gpio_sig_map.h"
#include "soc/debug_probe_periph.h"
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,
[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,
}
}
}
};

View File

@@ -745,7 +745,7 @@ config SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER
config SOC_DEBUG_PROBE_NUM_UNIT
int
default 1
default 2
config SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH
int

View File

@@ -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
*/
@@ -49,6 +49,23 @@ typedef enum {
DEBUG_PROBE_TARGET_PVT = 30, // PVT
} 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
}
#endif

View File

@@ -285,7 +285,7 @@
#define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (2)
#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
/*-------------------------- RTCIO CAPS --------------------------------------*/