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:
parent
e5276bb945
commit
930ec2f439
|
@ -421,4 +421,5 @@ struct target_type esp32s3_target = {
|
|||
.deinit_target = esp_xtensa_target_deinit,
|
||||
|
||||
.commands = esp32s3_command_handlers,
|
||||
.profiling = esp_xtensa_profiling,
|
||||
};
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */ \
|
||||
|
|
Loading…
Reference in New Issue