target/espressif: add profiling function for ESP32-S3

Use the TRAX interface DEBUGPC if available.
Otherwise use default stop-and-go profiling.

ESP32-S3, before this patch:
	Internal: 8 samples/second
	FT2232H: 12 samples/second

After this patch:
	Internal: 18ksamples/second
	FT2232H: 100ksamples/second

Change-Id: I681f0bccf4263c1e24f38be511e3b3aec8bf4d60
Signed-off-by: Richard Allen <rsaxvc@rsaxvc.net>
Reviewed-on: https://review.openocd.org/c/openocd/+/8431
Reviewed-by: Erhan Kurubas <erhan.kurubas@espressif.com>
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: Ian Thompson <ianst@cadence.com>
Reviewed-by: Yurii Shutkin <yurii.shutkin@gmail.com>
This commit is contained in:
Richard Allen 2024-07-31 20:53:52 -05:00 committed by Antonio Borneo
parent e5276bb945
commit 930ec2f439
4 changed files with 78 additions and 0 deletions

View File

@ -421,4 +421,5 @@ struct target_type esp32s3_target = {
.deinit_target = esp_xtensa_target_deinit,
.commands = esp32s3_command_handlers,
.profiling = esp_xtensa_profiling,
};

View File

@ -179,3 +179,75 @@ int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *break
return xtensa_breakpoint_remove(target, breakpoint);
/* flash breakpoints will be handled in another patch */
}
int esp_xtensa_profiling(struct target *target, uint32_t *samples,
uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
{
struct timeval timeout, now;
struct xtensa *xtensa = target_to_xtensa(target);
int retval = ERROR_OK;
int res;
/* Vary samples per pass to avoid sampling a periodic function periodically */
#define MIN_PASS 200
#define MAX_PASS 1000
gettimeofday(&timeout, NULL);
timeval_add_time(&timeout, seconds, 0);
uint8_t buf[sizeof(uint32_t) * MAX_PASS];
/* Capture one sample to verify the register is present and working */
xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf);
res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK) {
LOG_TARGET_INFO(target, "Failed to read DEBUGPC, fallback to stop-and-go");
return target_profiling_default(target, samples, max_num_samples, num_samples, seconds);
} else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0) {
LOG_TARGET_INFO(target, "NULL DEBUGPC, fallback to stop-and-go");
return target_profiling_default(target, samples, max_num_samples, num_samples, seconds);
}
LOG_TARGET_INFO(target, "Starting XTENSA DEBUGPC profiling. Sampling as fast as we can...");
/* Make sure the target is running */
target_poll(target);
if (target->state == TARGET_HALTED)
retval = target_resume(target, 1, 0, 0, 0);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "Error while resuming target");
return retval;
}
uint32_t sample_count = 0;
for (;;) {
uint32_t remaining = max_num_samples - sample_count;
uint32_t this_pass = rand() % (MAX_PASS - MIN_PASS) + MIN_PASS;
this_pass = this_pass > remaining ? remaining : this_pass;
for (uint32_t i = 0; i < this_pass; ++i)
xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf + i * sizeof(uint32_t));
res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK) {
LOG_TARGET_ERROR(target, "Failed to read DEBUGPC!");
return res;
}
for (uint32_t i = 0; i < this_pass; ++i) {
uint32_t sample32 = buf_get_u32(buf + i * sizeof(uint32_t), 0, 32);
samples[sample_count++] = sample32;
}
gettimeofday(&now, NULL);
if (sample_count >= max_num_samples || timeval_compare(&now, &timeout) > 0) {
LOG_TARGET_INFO(target, "Profiling completed. %" PRIu32 " samples.", sample_count);
break;
}
}
*num_samples = sample_count;
return retval;
#undef MIN_PASS
#undef MAX_PASS
}

View File

@ -37,6 +37,9 @@ void esp_xtensa_queue_tdi_idle(struct target *target);
int esp_xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint);
int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint);
int esp_xtensa_poll(struct target *target);
int esp_xtensa_profiling(struct target *target, uint32_t *samples,
uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
int esp_xtensa_on_halt(struct target *target);
#endif /* OPENOCD_TARGET_ESP_XTENSA_H */

View File

@ -75,6 +75,7 @@ enum xtensa_dm_reg {
XDMREG_DELAYCNT,
XDMREG_MEMADDRSTART,
XDMREG_MEMADDREND,
XDMREG_DEBUGPC,/*Unsupported, undocumented, may not be present*/
XDMREG_EXTTIMELO,
XDMREG_EXTTIMEHI,
XDMREG_TRAXRSVD48,
@ -184,6 +185,7 @@ struct xtensa_dm_reg_offsets {
{ .nar = 0x07, .apb = 0x001c }, /* XDMREG_DELAYCNT */ \
{ .nar = 0x08, .apb = 0x0020 }, /* XDMREG_MEMADDRSTART */ \
{ .nar = 0x09, .apb = 0x0024 }, /* XDMREG_MEMADDREND */ \
{ .nar = 0x0f, .apb = 0x003c }, /* XDMREG_DEBUGPC */ \
{ .nar = 0x10, .apb = 0x0040 }, /* XDMREG_EXTTIMELO */ \
{ .nar = 0x11, .apb = 0x0044 }, /* XDMREG_EXTTIMEHI */ \
{ .nar = 0x12, .apb = 0x0048 }, /* XDMREG_TRAXRSVD48 */ \