feat(debug_probe): added debug probe hal driver

This commit is contained in:
morris 2024-07-11 13:38:58 +08:00
parent d3d920eacb
commit c30d89953c
14 changed files with 789 additions and 1 deletions

View File

@ -84,6 +84,10 @@ if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "ldo/esp_ldo_regulator.c")
endif()
if(CONFIG_SOC_DEBUG_PROBE_SUPPORTED)
list(APPEND srcs "debug_probe/debug_probe.c")
endif()
if(CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED)
list(APPEND srcs "dma/esp_async_memcpy.c")
if(CONFIG_SOC_GDMA_SUPPORTED)
@ -177,8 +181,11 @@ else()
list(APPEND priv_requires "esp_system")
endif()
set(public_include_dirs "include" "include/soc" "include/soc/${target}"
"dma/include" "ldo/include" "debug_probe/include")
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS include include/soc include/soc/${target} dma/include ldo/include
INCLUDE_DIRS ${public_include_dirs}
PRIV_INCLUDE_DIRS port/include include/esp_private
REQUIRES ${requires}
PRIV_REQUIRES "${priv_requires}"

View File

@ -0,0 +1,221 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <string.h>
#include <stdatomic.h>
#include <sys/lock.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_heap_caps.h"
#include "soc/soc_caps.h"
#include "soc/debug_probe_periph.h"
#include "hal/debug_probe_ll.h"
#include "esp_private/debug_probe.h"
#include "esp_rom_gpio.h"
#include "driver/gpio.h"
static const char *TAG = "dbg_probe";
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_channel_t *channels[DEBUG_PROBE_LL_CHANNELS_PER_UNIT]; // channels installed in this unit
};
struct debug_probe_channel_t {
debug_probe_unit_t *unit; // the unit this channel belongs to
int chan_id; // channel id
};
typedef struct debug_probe_platform_t {
_lock_t mutex; // platform level mutex lock
debug_probe_unit_t *units[SOC_DEBUG_PROBE_NUM_UNIT]; // debug probe units
} debug_probe_platform_t;
static debug_probe_platform_t s_platform; // singleton platform
static esp_err_t debug_probe_unit_destroy(debug_probe_unit_t *unit)
{
int unit_id = unit->unit_id;
// remove the unit from the platform
_lock_acquire(&s_platform.mutex);
s_platform.units[unit_id] = NULL;
_lock_release(&s_platform.mutex);
// disable the probe output
debug_probe_ll_enable_unit(unit_id, false);
// free the memory
free(unit);
return ESP_OK;
}
esp_err_t debug_probe_new_unit(const debug_probe_unit_config_t *config, debug_probe_unit_handle_t *out_handle)
{
esp_err_t ret = ESP_OK;
debug_probe_unit_t *unit = NULL;
int unit_id = -1;
ESP_RETURN_ON_FALSE(config && out_handle, ESP_ERR_INVALID_ARG, TAG, "invalid args");
// search for a free unit slot
_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;
}
}
_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;
// configure the GPIOs
gpio_config_t monitor_io_conf = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 0,
};
for (int i = 0; i < SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH; i++) {
// skip unused IOs
if (config->probe_out_gpio_nums[i] < 0) {
continue;
}
monitor_io_conf.pin_bit_mask |= (1ULL << config->probe_out_gpio_nums[i]);
}
if (monitor_io_conf.pin_bit_mask) {
ESP_GOTO_ON_ERROR(gpio_config(&monitor_io_conf), err, TAG, "gpio_config failed");
}
// connect the probe output signals to the GPIOs
for (int i = 0; i < SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH; i++) {
if (config->probe_out_gpio_nums[i] < 0) {
continue;
}
esp_rom_gpio_connect_out_signal(config->probe_out_gpio_nums[i],
debug_probe_periph_signals.units[unit_id].out_sig[i],
false, false);
}
// enable the probe unit
debug_probe_ll_enable_unit(unit_id, true);
*out_handle = unit;
return ESP_OK;
err:
if (unit) {
debug_probe_unit_destroy(unit);
}
return ret;
}
esp_err_t debug_probe_del_unit(debug_probe_unit_handle_t unit)
{
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid args");
// if there's any channel still being used, return error
int channel_in_use = -1;
_lock_acquire(&s_platform.mutex);
for (int i = 0; i < DEBUG_PROBE_LL_CHANNELS_PER_UNIT; i++) {
if (unit->channels[i]) {
channel_in_use = i;
break;
}
}
_lock_release(&s_platform.mutex);
ESP_RETURN_ON_FALSE(channel_in_use < 0, ESP_ERR_INVALID_STATE, TAG, "channel %d still in use", channel_in_use);
return debug_probe_unit_destroy(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;
int chan_id = chan->chan_id;
// remove the channel from the unit
_lock_acquire(&s_platform.mutex);
unit->channels[chan_id] = NULL;
_lock_release(&s_platform.mutex);
// disable the probe channel
debug_probe_ll_enable_channel(unit_id, chan_id, false);
// free the memory
free(chan);
return ESP_OK;
}
esp_err_t debug_probe_new_channel(debug_probe_unit_handle_t unit, const debug_probe_channel_config_t *config, debug_probe_channel_handle_t *out_handle)
{
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;
// search for a free channel slot
_lock_acquire(&s_platform.mutex);
for (int i = 0; i < DEBUG_PROBE_LL_CHANNELS_PER_UNIT; i++) {
if (unit->channels[i] == NULL) {
chan_id = i;
chan = calloc(1, sizeof(debug_probe_channel_t));
unit->channels[i] = chan;
break;
}
}
_lock_release(&s_platform.mutex);
ESP_RETURN_ON_FALSE(chan_id >= 0, ESP_ERR_NOT_FOUND, TAG, "no free chan slot");
ESP_RETURN_ON_FALSE(chan, ESP_ERR_NO_MEM, TAG, "no mem for chan");
chan->chan_id = chan_id;
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);
debug_probe_ll_enable_channel(unit_id, chan_id, true);
*out_handle = chan;
return ESP_OK;
}
esp_err_t debug_probe_del_channel(debug_probe_channel_handle_t chan)
{
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid args");
return debug_probe_channel_destroy(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;
debug_probe_ll_channel_add_signal_group(unit->unit_id, chan->chan_id, byte_idx, sig_group);
return ESP_OK;
}
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;
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);
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);
return ESP_OK;
}

View File

@ -0,0 +1,157 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdio.h>
#include "esp_err.h"
#include "soc/gpio_num.h"
#include "debug_probe_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Handle type of a debug probe unit
*/
typedef struct debug_probe_unit_t *debug_probe_unit_handle_t;
/**
* @brief Handle type of a debug probe channel
*/
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_config_t;
/**
* @brief Create a new debug probe unit
*
* @param[in] config Configuration for the debug probe unit
* @param[out] out_handle Handle of the created debug probe unit
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the configuration is invalid
* - ESP_ERR_NOT_FOUND if there is no free unit slot
* - ESP_ERR_NO_MEM if memory allocation failed
* - ESP_FAIL if an internal error occurred
*/
esp_err_t debug_probe_new_unit(const debug_probe_unit_config_t *config, debug_probe_unit_handle_t *out_handle);
/**
* @brief Delete a debug probe unit
*
* @param[in] unit Handle of the debug probe unit
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the handle is invalid
* - ESP_FAIL if an internal error occurred
*/
esp_err_t debug_probe_del_unit(debug_probe_unit_handle_t unit);
/**
* @brief Configuration for a debug probe channel
*/
typedef struct {
debug_probe_target_t target_module; ///< Target module of the debug probe channel
} debug_probe_channel_config_t;
/**
* @brief Create a new debug probe channel in a unit
*
* @param[in] unit Handle of the debug probe unit
* @param[in] config Configuration for the debug probe channel
* @param[out] out_handle Handle of the created debug probe channel
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the handle or configuration is invalid
* - ESP_ERR_NOT_FOUND if there is no free channel slot
* - ESP_ERR_NO_MEM if memory allocation failed
* - ESP_FAIL if an internal error occurred
*/
esp_err_t debug_probe_new_channel(debug_probe_unit_handle_t unit, const debug_probe_channel_config_t *config, debug_probe_channel_handle_t *out_handle);
/**
* @brief Delete a debug probe channel
*
* @param[in] chan Handle of the debug probe channel
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the handle is invalid
* - ESP_FAIL if an internal error occurred
*/
esp_err_t debug_probe_del_channel(debug_probe_channel_handle_t chan);
/**
* @brief Add signals to a debug probe channel
*
* @note The n-th byte of channel output comes from the n-th byte in the sig_group.
* @note The signals to be added must aligned to the byte boundary.
* byte_idx = 0: signal 0-7 in the group
* byte_idx = 1: signal 8-15 in the group
* ...
* @note If you add the signals from different groups but with the same byte_idx, only the last added signal will be effective.
* @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] sig_group Signal group of the signal, ranges from 0 to 15
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the parameters are invalid
* - ESP_FAIL if an internal error occurred
*/
esp_err_t debug_probe_chan_add_signal_by_byte(debug_probe_channel_handle_t chan, uint8_t byte_idx, uint8_t sig_group);
/**
* @brief Merge the part of the channel output to the debug probe unit output
*
* +----upper16---+
* chan_0 ---+ |
* +----lower16---+
* |
* +-------unit_output[31:0]
* |
* +----upper16---+
* chan_1 ---+ |
* +----lower16---+
*
* @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
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the parameters are invalid
* - ESP_FAIL if an internal error occurred
*/
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);
/**
* @brief Read the value of the debug probe unit
*
* @note Only the lower 16 signals of the probe unit can be routed to the GPIO pads.
*
* @param[in] unit Handle of the debug probe unit
* @param[out] value Current value of the debug probe unit output
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if the handle or value is invalid
* - ESP_FAIL if an internal error occurred
*/
esp_err_t debug_probe_unit_read(debug_probe_unit_handle_t unit, uint32_t *value);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,32 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdio.h>
#include "esp_err.h"
#include "soc/soc_caps.h"
#include "hal/debug_probe_types.h"
#if SOC_DEBUG_PROBE_SUPPORTED
#include "soc/debug_probe_targets.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_DEBUG_PROBE_SUPPORTED
#define DEBUG_PROBE_MAX_OUTPUT_WIDTH SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH
typedef soc_debug_probe_target_t debug_probe_target_t;
#else
#define DEBUG_PROBE_MAX_OUTPUT_WIDTH 16
typedef int debug_probe_target_t;
#endif
#ifdef __cplusplus
}
#endif

View File

@ -16,6 +16,10 @@ if(CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX OR CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX
list(APPEND srcs "test_esp_clock_output.c")
endif()
if(CONFIG_SOC_DEBUG_PROBE_SUPPORTED)
list(APPEND srcs "test_debug_probe.c")
endif()
if(CONFIG_SOC_ETM_SUPPORTED)
list(APPEND srcs "test_etm_core.c")
endif()

View File

@ -0,0 +1,86 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#include "soc/soc_caps.h"
#include "hal/debug_probe_ll.h"
#include "esp_private/debug_probe.h"
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++) {
TEST_ESP_OK(debug_probe_new_unit(&unit_config, &probe_units[i]));
}
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++) {
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_ERR(ESP_ERR_NOT_FOUND, debug_probe_new_channel(probe_units[i], &chan_config, &probe_chans[i][0]));
}
for (int i = 0; i < SOC_DEBUG_PROBE_NUM_UNIT; i++) {
for (int j = 0; j < DEBUG_PROBE_LL_CHANNELS_PER_UNIT; j++) {
TEST_ESP_OK(debug_probe_del_channel(probe_chans[i][j]));
}
TEST_ESP_OK(debug_probe_del_unit(probe_units[i]));
}
}
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,
}
};
debug_probe_unit_handle_t probe_unit = NULL;
TEST_ESP_OK(debug_probe_new_unit(&unit_config, &probe_unit));
// 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,
};
TEST_ESP_OK(debug_probe_new_channel(probe_unit, &chan_config, &probe_chans[i]));
// group15[7:0] contains the debug target module ID
TEST_ESP_OK(debug_probe_chan_add_signal_by_byte(probe_chans[i], 0, 15));
TEST_ESP_OK(debug_probe_chan_add_signal_by_byte(probe_chans[i], 1, 15));
TEST_ESP_OK(debug_probe_chan_add_signal_by_byte(probe_chans[i], 2, 15));
TEST_ESP_OK(debug_probe_chan_add_signal_by_byte(probe_chans[i], 3, 15));
}
TEST_ESP_OK(debug_probe_unit_merge16(probe_unit,
probe_chans[0], DEBUG_PROBE_SPLIT_LOWER16,
probe_chans[1], DEBUG_PROBE_SPLIT_LOWER16));
uint32_t probe_result = 0;
TEST_ESP_OK(debug_probe_unit_read(probe_unit, &probe_result));
printf("probe result: 0x%"PRIx32"\r\n", probe_result);
TEST_ASSERT_EQUAL_HEX32(0x20001, probe_result);
// free resources
for (int i = 0; i < 2; i++) {
TEST_ESP_OK(debug_probe_del_channel(probe_chans[i]));
}
TEST_ESP_OK(debug_probe_del_unit(probe_unit));
}

View File

@ -0,0 +1,122 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/debug_probe_targets.h"
#include "soc/hp_system_struct.h"
#include "hal/debug_probe_types.h"
/**
* @brief Define how many channels are there in one debug probe unit
*/
#define DEBUG_PROBE_LL_CHANNELS_PER_UNIT 2
#ifdef __cplusplus
extern "C" {
#endif
// translate the HAL types into register values
#define DEBUG_PROBE_LL_PART_TO_REG_VAL(part) ((uint8_t[]) {0, 1}[(part)])
/**
* @brief Enable the debug probe module
*
* @param en true: enable, false: disable
*/
static inline void debug_probe_ll_enable_unit(int unit_id, bool en)
{
HP_SYSTEM.probea_ctrl.reg_probe_global_en = en;
}
/**
* @brief Enable a specific channel in the debug probe unit
*
* @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)
{
// channel 0 is always enabled
if (channel == 1) {
HP_SYSTEM.probeb_ctrl.reg_probe_b_en = en;
}
}
/**
* @brief Set the target module for a probe channel
*
* @param channel channel number (only support 0 and 1)
* @param target_module target module, see soc_debug_probe_target_t
*/
static inline void debug_probe_ll_channel_set_target_module(int unit_id, uint8_t channel, soc_debug_probe_target_t target_module)
{
if (channel == 0) {
HP_SYSTEM.probea_ctrl.reg_probe_a_top_sel = target_module;
} else {
HP_SYSTEM.probeb_ctrl.reg_probe_b_top_sel = target_module;
}
}
/**
* @brief Add signals from a specific group to the probe channel
*
* @note One sig_group contains 4 bytes of signals. The sig_byte_idx is used to select the byte in the sig_group.
*
* @param channel channel number (only support 0 and 1)
* @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)
{
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));
}
}
/**
* @brief Set the lower 16 bits of the probe output
*
* @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)
{
HP_SYSTEM.probea_ctrl.reg_probe_l_sel = channel * 2 + DEBUG_PROBE_LL_PART_TO_REG_VAL(part);
}
/**
* @brief Set the upper 16 bits of the probe output
*
* @param part where does the probe_top_out[31:16] come from
*/
static inline void debug_probe_ll_set_upper16_output(int unit_id, int channel, debug_probe_split_u16_t part)
{
HP_SYSTEM.probea_ctrl.reg_probe_h_sel = channel * 2 + DEBUG_PROBE_LL_PART_TO_REG_VAL(part);
}
/**
* @brief Read the value that currently being probed
*
* @note ESP32P4 can only route the LSB probe_top_out[15:0] to the GPIO pad. But the register still saves 32 signal bits.
*
* @return the value that currently being probed
*/
static inline uint32_t debug_probe_ll_read_output(int unit_id)
{
return HP_SYSTEM.probe_out.reg_probe_top_out;
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief The 32bit debug probe output can be split into two 16bit parts
*/
typedef enum {
DEBUG_PROBE_SPLIT_LOWER16, ///< The lower 16 signals of the debug probe output
DEBUG_PROBE_SPLIT_UPPER16, ///< The upper 16 signals of the debug probe output
} debug_probe_split_u16_t;
#ifdef __cplusplus
}
#endif

View File

@ -33,6 +33,10 @@ if(CONFIG_SOC_DEDICATED_GPIO_SUPPORTED)
list(APPEND srcs "${target_folder}/dedic_gpio_periph.c")
endif()
if(CONFIG_SOC_DEBUG_PROBE_SUPPORTED)
list(APPEND srcs "${target_folder}/debug_probe_periph.c")
endif()
if(CONFIG_SOC_EMAC_SUPPORTED)
list(APPEND srcs "${target_folder}/emac_periph.c")
endif()

View File

@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/gpio_sig_map.h"
#include "soc/debug_probe_periph.h"
const debug_probe_signal_conn_t debug_probe_periph_signals = {
.units = {
[0] = {
.out_sig = {
[0] = HP_PROBE_TOP_OUT0_IDX,
[1] = HP_PROBE_TOP_OUT1_IDX,
[2] = HP_PROBE_TOP_OUT2_IDX,
[3] = HP_PROBE_TOP_OUT3_IDX,
[4] = HP_PROBE_TOP_OUT4_IDX,
[5] = HP_PROBE_TOP_OUT5_IDX,
[6] = HP_PROBE_TOP_OUT6_IDX,
[7] = HP_PROBE_TOP_OUT7_IDX,
[8] = HP_PROBE_TOP_OUT8_IDX,
[9] = HP_PROBE_TOP_OUT9_IDX,
[10] = HP_PROBE_TOP_OUT10_IDX,
[11] = HP_PROBE_TOP_OUT11_IDX,
[12] = HP_PROBE_TOP_OUT12_IDX,
[13] = HP_PROBE_TOP_OUT13_IDX,
[14] = HP_PROBE_TOP_OUT14_IDX,
[15] = HP_PROBE_TOP_OUT15_IDX,
}
}
}
};

View File

@ -267,6 +267,10 @@ config SOC_ASSIST_DEBUG_SUPPORTED
bool
default y
config SOC_DEBUG_PROBE_SUPPORTED
bool
default y
config SOC_WDT_SUPPORTED
bool
default y
@ -639,6 +643,14 @@ config SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER
bool
default y
config SOC_DEBUG_PROBE_NUM_UNIT
int
default 1
config SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH
int
default 16
config SOC_GPIO_SUPPORT_FORCE_HOLD
bool
default y

View File

@ -0,0 +1,54 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Target module that we want to attach the probe to
*
* @note The target module ID can be obtained from the prob_grp15[7:0]
*/
typedef enum {
DEBUG_PROBE_TARGET_MIPI_CSI_HOST = 0, // MIPI CSI Host
DEBUG_PROBE_TARGET_AXI_GDMA = 1, // AXI GDMA
DEBUG_PROBE_TARGET_I3C = 2, // I3C
DEBUG_PROBE_TARGET_HP_TCM = 3, // HP TCM Memory
DEBUG_PROBE_TARGET_USB_OTG_FS = 4, // USB OTG FS (1.1)
DEBUG_PROBE_TARGET_MIPI_CSI_BRG = 5, // MIPI CSI Bridge
DEBUG_PROBE_TARGET_MSPI_PSRAM = 6, // MSPI PSRAM
DEBUG_PROBE_TARGET_MIPI_DSI_BRG = 7, // MIPI DSI Bridge
DEBUG_PROBE_TARGET_DW_GDMA = 8, // DW GDMA
DEBUG_PROBE_TARGET_AXI_ICM = 9, // AXI ICM matrix
DEBUG_PROBE_TARGET_L2_MEM = 10, // L2 Memory
DEBUG_PROBE_TARGET_BIT_SCRAMBLER = 11, // Bit Scrambler
DEBUG_PROBE_TARGET_MSPI_FLASH = 12, // MSPI Flash
DEBUG_PROBE_TARGET_L1_CACHE = 13, // L1 Cache
DEBUG_PROBE_TARGET_HP_CORE = 14, // HP Core
DEBUG_PROBE_TARGET_L2_CACHE = 15, // L2 Cache
DEBUG_PROBE_TARGET_LP_PROBE_IN = 16, // LP System Probe In
DEBUG_PROBE_TARGET_USJ = 17, // USB Serial JTAG
DEBUG_PROBE_TARGET_EMAC = 18, // EMAC
DEBUG_PROBE_TARGET_JPEG = 19, // JPEG
DEBUG_PROBE_TARGET_PPA = 20, // PPA
DEBUG_PROBE_TARGET_DMA2D = 21, // DMA2D
DEBUG_PROBE_TARGET_LEDC = 22, // LEDC
DEBUG_PROBE_TARGET_SDMMC = 23, // SDMMC
DEBUG_PROBE_TARGET_ISP = 24, // ISP
DEBUG_PROBE_TARGET_USB_OTG_HS = 25, // USB OTG HS (2.0)
DEBUG_PROBE_TARGET_H264 = 26, // H264
DEBUG_PROBE_TARGET_MCPWM0 = 27, // MCPWM0
DEBUG_PROBE_TARGET_MCPWM1 = 28, // MCPWM1
DEBUG_PROBE_TARGET_REGDMA = 29, // REGDMA
DEBUG_PROBE_TARGET_PVT = 30, // PVT
} soc_debug_probe_target_t;
#ifdef __cplusplus
}
#endif

View File

@ -85,6 +85,7 @@
#define SOC_SDMMC_HOST_SUPPORTED 1
#define SOC_CLK_TREE_SUPPORTED 1
#define SOC_ASSIST_DEBUG_SUPPORTED 1
#define SOC_DEBUG_PROBE_SUPPORTED 1
#define SOC_WDT_SUPPORTED 1
#define SOC_SPI_FLASH_SUPPORTED 1
#define SOC_TOUCH_SENSOR_SUPPORTED 1
@ -95,6 +96,7 @@
#define SOC_DEEP_SLEEP_SUPPORTED 1
#define SOC_PM_SUPPORTED 1
/*-------------------------- XTAL CAPS ---------------------------------------*/
#define SOC_XTAL_SUPPORT_40M 1
@ -252,6 +254,9 @@
#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_MAX_OUTPUT_WIDTH (16) // Maximum width of the debug probe output in each unit
// Support to force hold all IOs
#define SOC_GPIO_SUPPORT_FORCE_HOLD (1)
// Support to hold a single digital I/O when the digital domain is powered off

View File

@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_DEBUG_PROBE_SUPPORTED
typedef struct {
struct {
const int out_sig[SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH];
} units[SOC_DEBUG_PROBE_NUM_UNIT];
} debug_probe_signal_conn_t;
extern const debug_probe_signal_conn_t debug_probe_periph_signals;
#endif // SOC_DEBUG_PROBE_SUPPORTED
#ifdef __cplusplus
}
#endif