target/cortex_m: reduce duplication in profiling

The Cortex-M implementation of profiling contains a bunch of
conditionals and checks to handle both chips which have PCSR and chips
which do not. However, the net effect of the non-PCSR branches is
actually exactly the same as what target_profiling_default does. Rather
than duplicating this code, just detect the situation where PCSR isn’t
available and delegate to target_profiling_default.

Change-Id: I1be57ac77f983816ab6bf644a3cfca77b67d6f70
Signed-off-by: Christopher Head <chead@zaber.com>
Reviewed-on: http://openocd.zylin.com/5236
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Christopher Head 2019-06-14 15:25:26 -07:00 committed by Antonio Borneo
parent a7502ee8b9
commit d3aa2d3536
3 changed files with 23 additions and 46 deletions

View File

@ -1835,28 +1835,23 @@ int cortex_m_profiling(struct target *target, uint32_t *samples,
struct timeval timeout, now;
struct armv7m_common *armv7m = target_to_armv7m(target);
uint32_t reg_value;
bool use_pcsr = false;
int retval = ERROR_OK;
struct reg *reg;
gettimeofday(&timeout, NULL);
timeval_add_time(&timeout, seconds, 0);
int retval;
retval = target_read_u32(target, DWT_PCSR, &reg_value);
if (retval != ERROR_OK) {
LOG_ERROR("Error while reading PCSR");
return retval;
}
if (reg_value != 0) {
use_pcsr = true;
LOG_INFO("Starting Cortex-M profiling. Sampling DWT_PCSR as fast as we can...");
} else {
LOG_INFO("Starting profiling. Halting and resuming the"
" target as often as we can...");
reg = register_get_by_name(target->reg_cache, "pc", 1);
if (reg_value == 0) {
LOG_INFO("PCSR sampling not supported on this processor.");
return target_profiling_default(target, samples, max_num_samples, num_samples, seconds);
}
gettimeofday(&timeout, NULL);
timeval_add_time(&timeout, seconds, 0);
LOG_INFO("Starting Cortex-M profiling. Sampling DWT_PCSR as fast as we can...");
/* Make sure the target is running */
target_poll(target);
if (target->state == TARGET_HALTED)
@ -1870,40 +1865,21 @@ int cortex_m_profiling(struct target *target, uint32_t *samples,
uint32_t sample_count = 0;
for (;;) {
if (use_pcsr) {
if (armv7m && armv7m->debug_ap) {
uint32_t read_count = max_num_samples - sample_count;
if (read_count > 1024)
read_count = 1024;
if (armv7m && armv7m->debug_ap) {
uint32_t read_count = max_num_samples - sample_count;
if (read_count > 1024)
read_count = 1024;
retval = mem_ap_read_buf_noincr(armv7m->debug_ap,
(void *)&samples[sample_count],
4, read_count, DWT_PCSR);
sample_count += read_count;
} else {
target_read_u32(target, DWT_PCSR, &samples[sample_count++]);
}
retval = mem_ap_read_buf_noincr(armv7m->debug_ap,
(void *)&samples[sample_count],
4, read_count, DWT_PCSR);
sample_count += read_count;
} else {
target_poll(target);
if (target->state == TARGET_HALTED) {
reg_value = buf_get_u32(reg->value, 0, 32);
/* current pc, addr = 0, do not handle breakpoints, not debugging */
retval = target_resume(target, 1, 0, 0, 0);
samples[sample_count++] = reg_value;
target_poll(target);
alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */
} else if (target->state == TARGET_RUNNING) {
/* We want to quickly sample the PC. */
retval = target_halt(target);
} else {
LOG_INFO("Target not halted or running");
retval = ERROR_OK;
break;
}
target_read_u32(target, DWT_PCSR, &samples[sample_count++]);
}
if (retval != ERROR_OK) {
LOG_ERROR("Error while reading %s", use_pcsr ? "PCSR" : "target pc");
LOG_ERROR("Error while reading PCSR");
return retval;
}

View File

@ -72,8 +72,6 @@ static int target_get_gdb_fileio_info_default(struct target *target,
struct gdb_fileio_info *fileio_info);
static int target_gdb_fileio_end_default(struct target *target, int retcode,
int fileio_errno, bool ctrl_c);
static int target_profiling_default(struct target *target, uint32_t *samples,
uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
/* targets */
extern struct target_type arm7tdmi_target;
@ -2137,7 +2135,7 @@ static int target_gdb_fileio_end_default(struct target *target,
return ERROR_OK;
}
static int target_profiling_default(struct target *target, uint32_t *samples,
int target_profiling_default(struct target *target, uint32_t *samples,
uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
{
struct timeval timeout, now;

View File

@ -748,6 +748,9 @@ void target_handle_md_output(struct command_invocation *cmd,
struct target *target, target_addr_t address, unsigned size,
unsigned count, const uint8_t *buffer);
int target_profiling_default(struct target *target, uint32_t *samples, uint32_t
max_num_samples, uint32_t *num_samples, uint32_t seconds);
#define ERROR_TARGET_INVALID (-300)
#define ERROR_TARGET_INIT_FAILED (-301)
#define ERROR_TARGET_TIMEOUT (-302)