mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(debug_probe): added debug probe hal driver
This commit is contained in:
parent
d3d920eacb
commit
c30d89953c
@ -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}"
|
||||
|
221
components/esp_hw_support/debug_probe/debug_probe.c
Normal file
221
components/esp_hw_support/debug_probe/debug_probe.c
Normal 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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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()
|
||||
|
@ -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));
|
||||
}
|
122
components/hal/esp32p4/include/hal/debug_probe_ll.h
Normal file
122
components/hal/esp32p4/include/hal/debug_probe_ll.h
Normal 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
|
23
components/hal/include/hal/debug_probe_types.h
Normal file
23
components/hal/include/hal/debug_probe_types.h
Normal 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
|
@ -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()
|
||||
|
33
components/soc/esp32p4/debug_probe_periph.c
Normal file
33
components/soc/esp32p4/debug_probe_periph.c
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
@ -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
|
||||
|
54
components/soc/esp32p4/include/soc/debug_probe_targets.h
Normal file
54
components/soc/esp32p4/include/soc/debug_probe_targets.h
Normal 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
|
@ -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
|
||||
|
28
components/soc/include/soc/debug_probe_periph.h
Normal file
28
components/soc/include/soc/debug_probe_periph.h
Normal 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
|
Loading…
Reference in New Issue
Block a user