aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Schubert <2@0x2c.org>2017-09-01 20:34:09 +0200
committerPaul Fertser <fercerpav@gmail.com>2018-01-13 09:29:59 +0000
commit64b0d5aac0c5214db01f938550e8b126891d5a08 (patch)
tree313bd288f65722f1456c4a910ba0f8664b731ce0
parent2b44b52478708c3bef58033dfd4f7bb7db74d843 (diff)
downloadriscv-openocd-64b0d5aac0c5214db01f938550e8b126891d5a08.zip
riscv-openocd-64b0d5aac0c5214db01f938550e8b126891d5a08.tar.gz
riscv-openocd-64b0d5aac0c5214db01f938550e8b126891d5a08.tar.bz2
cortex_m: add profiling function
Use DWT_PCSR if present (reads nonzero); otherwise do halt-and-sample pc. Signed-off-by: Simon Schubert <2@0x2c.org> Change-Id: Id2dc4665e5008cc497a2e6e6493522d038d5af42 Reviewed-on: http://openocd.zylin.com/4211 Tested-by: jenkins Reviewed-by: Karl Palsson <karlp@tweak.net.au> Reviewed-by: Christopher Head <chead@zaber.com> Reviewed-by: Paul Fertser <fercerpav@gmail.com>
-rw-r--r--src/target/cortex_m.c89
-rw-r--r--src/target/cortex_m.h1
2 files changed, 90 insertions, 0 deletions
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index 2f8c2a2..988323b 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -1707,6 +1707,93 @@ void cortex_m_deinit_target(struct target *target)
free(cortex_m);
}
+static int cortex_m_profiling(struct target *target, uint32_t *samples,
+ uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
+{
+ 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);
+
+ 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);
+ }
+
+ /* 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_ERROR("Error while resuming target");
+ return retval;
+ }
+
+ uint32_t sample_count = 0;
+
+ for (;;) {
+ if (use_pcsr) {
+ 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_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;
+ }
+ }
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Error while reading %s", use_pcsr ? "PCSR" : "target pc");
+ return retval;
+ }
+
+
+ gettimeofday(&now, NULL);
+ if (sample_count >= max_num_samples ||
+ (now.tv_sec >= timeout.tv_sec && now.tv_usec >= timeout.tv_usec)) {
+ LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count);
+ break;
+ }
+ }
+
+ *num_samples = sample_count;
+ return retval;
+}
+
+
/* REVISIT cache valid/dirty bits are unmaintained. We could set "valid"
* on r/w if the core is not running, and clear on resume or reset ... or
* at least, in a post_restore_context() method.
@@ -2451,4 +2538,6 @@ struct target_type cortexm_target = {
.init_target = cortex_m_init_target,
.examine = cortex_m_examine,
.deinit_target = cortex_m_deinit_target,
+
+ .profiling = cortex_m_profiling,
};
diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h
index 3d9714b..dbf9ac8 100644
--- a/src/target/cortex_m.h
+++ b/src/target/cortex_m.h
@@ -48,6 +48,7 @@
#define DWT_CTRL 0xE0001000
#define DWT_CYCCNT 0xE0001004
+#define DWT_PCSR 0xE000101C
#define DWT_COMP0 0xE0001020
#define DWT_MASK0 0xE0001024
#define DWT_FUNCTION0 0xE0001028