diff --git a/components/esp_hw_support/debug_probe/debug_probe.c b/components/esp_hw_support/debug_probe/debug_probe.c index f1824e42cf0..761ef4f11c8 100644 --- a/components/esp_hw_support/debug_probe/debug_probe.c +++ b/components/esp_hw_support/debug_probe/debug_probe.c @@ -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; } diff --git a/components/esp_hw_support/debug_probe/include/esp_private/debug_probe.h b/components/esp_hw_support/debug_probe/include/esp_private/debug_probe.h index 0afb1c8ffe5..50396c32189 100644 --- a/components/esp_hw_support/debug_probe/include/esp_private/debug_probe.h +++ b/components/esp_hw_support/debug_probe/include/esp_private/debug_probe.h @@ -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 diff --git a/components/esp_hw_support/debug_probe/include/esp_private/debug_probe_types.h b/components/esp_hw_support/debug_probe/include/esp_private/debug_probe_types.h index ac54ca66ec5..49d700a3fe5 100644 --- a/components/esp_hw_support/debug_probe/include/esp_private/debug_probe_types.h +++ b/components/esp_hw_support/debug_probe/include/esp_private/debug_probe_types.h @@ -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 diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_debug_probe.c b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_debug_probe.c index e9af7da1e99..0aa09aeb085 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_debug_probe.c +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_debug_probe.c @@ -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 diff --git a/components/hal/esp32p4/include/hal/debug_probe_ll.h b/components/hal/esp32p4/include/hal/debug_probe_ll.h index dd9f539230d..2f0bab979ba 100644 --- a/components/hal/esp32p4/include/hal/debug_probe_ll.h +++ b/components/hal/esp32p4/include/hal/debug_probe_ll.h @@ -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 #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 diff --git a/components/hal/include/hal/debug_probe_types.h b/components/hal/include/hal/debug_probe_types.h index 654a5de015b..0eddc341153 100644 --- a/components/hal/include/hal/debug_probe_types.h +++ b/components/hal/include/hal/debug_probe_types.h @@ -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 */ diff --git a/components/soc/esp32p4/debug_probe_periph.c b/components/soc/esp32p4/debug_probe_periph.c index 99d048daa1c..bec4a2d1be9 100644 --- a/components/soc/esp32p4/debug_probe_periph.c +++ b/components/soc/esp32p4/debug_probe_periph.c @@ -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, + } } } }; diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 7001db6a976..b3bf006934c 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32p4/include/soc/debug_probe_targets.h b/components/soc/esp32p4/include/soc/debug_probe_targets.h index c826919d102..25736f33b1a 100644 --- a/components/soc/esp32p4/include/soc/debug_probe_targets.h +++ b/components/soc/esp32p4/include/soc/debug_probe_targets.h @@ -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 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index d9d1c20681f..35b2b08a5a7 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -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 --------------------------------------*/