From 344bed2f7eab5f4ff05fd944b1c476fc8a2103ba Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 22 Oct 2009 12:01:27 -0700 Subject: [PATCH] ETM: rename registers, doc tweaks The register names are perversely not documented as zero-indexed, so rename them to match that convention. Also switch to lowercase suffixes and infix numbering, matching ETB and EmbeddedICE usage. Update docs to be a bit more accurate, especially regarding what the "trigger" event can cause; and to split the issues into a few more paragraphs, for clarity. Make "configure" helptext point out that "oocd_trace" is prototype hardware, not anything "real". Signed-off-by: David Brownell --- configure.in | 3 +- doc/openocd.texi | 19 ++++++++- src/target/etm.c | 101 +++++++++++++++++++++++++---------------------- 3 files changed, 73 insertions(+), 50 deletions(-) diff --git a/configure.in b/configure.in index 1d3f0ec6..99f97da4 100644 --- a/configure.in +++ b/configure.in @@ -377,7 +377,8 @@ AC_ARG_ENABLE(usbprog, [build_usbprog=$enableval], [build_usbprog=no]) AC_ARG_ENABLE(oocd_trace, - AS_HELP_STRING([--enable-oocd_trace], [Enable building support for the OpenOCD+trace ETM capture device]), + AS_HELP_STRING([--enable-oocd_trace], + [Enable building support for some prototype OpenOCD+trace ETM capture hardware]), [build_oocd_trace=$enableval], [build_oocd_trace=no]) AC_ARG_ENABLE(jlink, diff --git a/doc/openocd.texi b/doc/openocd.texi index e04b83c8..c9e48bfa 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5114,14 +5114,23 @@ ETM support in OpenOCD doesn't seem to be widely used yet. @quotation Issues ETM support may be buggy, and at least some @command{etm config} parameters should be detected by asking the ETM for them. + +ETM trigger events could also implement a kind of complex +hardware breakpoint, much more powerful than the simple +watchpoint hardware exported by EmbeddedICE modules. +@emph{Such breakpoints can be triggered even when using the +dummy trace port driver}. + It seems like a GDB hookup should be possible, -as well as triggering trace on specific events +as well as tracing only during specific states (perhaps @emph{handling IRQ 23} or @emph{calls foo()}). + There should be GUI tools to manipulate saved trace data and help analyse it in conjunction with the source code. It's unclear how much of a common interface is shared with the current XScale trace support, or should be shared with eventual Nexus-style trace module support. + At this writing (September 2009) only ARM7 and ARM9 support for ETM modules is available. The code should be able to work with some newer cores; but not all of them support @@ -5135,7 +5144,10 @@ ETM setup is coupled with the trace port driver configuration. Declares the ETM associated with @var{target}, and associates it with a given trace port @var{driver}. @xref{Trace Port Drivers}. -Several of the parameters must reflect the trace port configuration. +Several of the parameters must reflect the trace port capabilities, +which are a function of silicon capabilties (exposed later +using @command{etm info}) and of what hardware is connected to +that port (such as an external pod, or ETB). The @var{width} must be either 4, 8, or 16. The @var{mode} must be @option{normal}, @option{multiplexted}, or @option{demultiplexted}. @@ -5151,6 +5163,9 @@ what CPU activities are traced. @deffn Command {etm info} Displays information about the current target's ETM. +This includes resource counts from the @code{ETM_CONFIG} register, +as well as silicon capabilities (except on rather old modules). +from the @code{ETM_SYS_CONFIG} register. @end deffn @deffn Command {etm status} diff --git a/src/target/etm.c b/src/target/etm.c index 34e2ca8a..51065817 100644 --- a/src/target/etm.c +++ b/src/target/etm.c @@ -76,47 +76,46 @@ struct etm_reg_info { /* basic registers that are always there given the right ETM version */ static const struct etm_reg_info etm_core[] = { /* NOTE: we "know" ETM_CONFIG is listed first */ - { ETM_CONFIG, 32, RO, 0x10, "ETM_CONFIG", }, + { ETM_CONFIG, 32, RO, 0x10, "ETM_config", }, /* ETM Trace Registers */ - { ETM_CTRL, 32, RW, 0x10, "ETM_CTRL", }, - { ETM_TRIG_EVENT, 17, WO, 0x10, "ETM_TRIG_EVENT", }, - { ETM_ASIC_CTRL, 8, WO, 0x10, "ETM_ASIC_CTRL", }, - { ETM_STATUS, 3, RO, 0x11, "ETM_STATUS", }, - { ETM_SYS_CONFIG, 9, RO, 0x12, "ETM_SYS_CONFIG", }, + { ETM_CTRL, 32, RW, 0x10, "ETM_ctrl", }, + { ETM_TRIG_EVENT, 17, WO, 0x10, "ETM_trig_event", }, + { ETM_ASIC_CTRL, 8, WO, 0x10, "ETM_asic_ctrl", }, + { ETM_STATUS, 3, RO, 0x11, "ETM_status", }, + { ETM_SYS_CONFIG, 9, RO, 0x12, "ETM_sys_config", }, /* TraceEnable configuration */ - { ETM_TRACE_RESOURCE_CTRL, 32, WO, 0x12, "ETM_TRACE_RESOURCE_CTRL", }, - { ETM_TRACE_EN_CTRL2, 16, WO, 0x12, "ETM_TRACE_EN_CTRL2", }, - { ETM_TRACE_EN_EVENT, 17, WO, 0x10, "ETM_TRACE_EN_EVENT", }, - { ETM_TRACE_EN_CTRL1, 26, WO, 0x10, "ETM_TRACE_EN_CTRL1", }, + { ETM_TRACE_RESOURCE_CTRL, 32, WO, 0x12, "ETM_trace_resource_ctrl", }, + { ETM_TRACE_EN_CTRL2, 16, WO, 0x12, "ETM_trace_en_ctrl2", }, + { ETM_TRACE_EN_EVENT, 17, WO, 0x10, "ETM_trace_en_event", }, + { ETM_TRACE_EN_CTRL1, 26, WO, 0x10, "ETM_trace_en_ctrl1", }, /* ViewData configuration (data trace) */ - { ETM_VIEWDATA_EVENT, 17, WO, 0x10, "ETM_VIEWDATA_EVENT", }, - { ETM_VIEWDATA_CTRL1, 32, WO, 0x10, "ETM_VIEWDATA_CTRL1", }, - { ETM_VIEWDATA_CTRL2, 32, WO, 0x10, "ETM_VIEWDATA_CTRL2", }, - { ETM_VIEWDATA_CTRL3, 17, WO, 0x10, "ETM_VIEWDATA_CTRL3", }, + { ETM_VIEWDATA_EVENT, 17, WO, 0x10, "ETM_viewdata_event", }, + { ETM_VIEWDATA_CTRL1, 32, WO, 0x10, "ETM_viewdata_ctrl1", }, + { ETM_VIEWDATA_CTRL2, 32, WO, 0x10, "ETM_viewdata_ctrl2", }, + { ETM_VIEWDATA_CTRL3, 17, WO, 0x10, "ETM_viewdata_ctrl3", }, /* REVISIT exclude VIEWDATA_CTRL2 when it's not there */ - { 0x78, 12, WO, 0x20, "ETM_SYNC_FREQ", }, - { 0x79, 32, RO, 0x20, "ETM_ID", }, + { 0x78, 12, WO, 0x20, "ETM_sync_freq", }, + { 0x79, 32, RO, 0x20, "ETM_id", }, }; static const struct etm_reg_info etm_fifofull[] = { /* FIFOFULL configuration */ - { ETM_FIFOFULL_REGION, 25, WO, 0x10, "ETM_FIFOFULL_REGION", }, - { ETM_FIFOFULL_LEVEL, 8, WO, 0x10, "ETM_FIFOFULL_LEVEL", }, + { ETM_FIFOFULL_REGION, 25, WO, 0x10, "ETM_fifofull_region", }, + { ETM_FIFOFULL_LEVEL, 8, WO, 0x10, "ETM_fifofull_level", }, }; static const struct etm_reg_info etm_addr_comp[] = { /* Address comparator register pairs */ #define ADDR_COMPARATOR(i) \ - { ETM_ADDR_COMPARATOR_VALUE + (i), 32, WO, 0x10, \ - "ETM_ADDR_COMPARATOR_VALUE" #i, }, \ - { ETM_ADDR_ACCESS_TYPE + (i), 7, WO, 0x10, \ - "ETM_ADDR_ACCESS_TYPE" #i, } - ADDR_COMPARATOR(0), + { ETM_ADDR_COMPARATOR_VALUE + (i) - 1, 32, WO, 0x10, \ + "ETM_addr_" #i "_comparator_value", }, \ + { ETM_ADDR_ACCESS_TYPE + (i) - 1, 7, WO, 0x10, \ + "ETM_addr_" #i "_access_type", } ADDR_COMPARATOR(1), ADDR_COMPARATOR(2), ADDR_COMPARATOR(3), @@ -124,8 +123,8 @@ static const struct etm_reg_info etm_addr_comp[] = { ADDR_COMPARATOR(5), ADDR_COMPARATOR(6), ADDR_COMPARATOR(7), - ADDR_COMPARATOR(8), + ADDR_COMPARATOR(9), ADDR_COMPARATOR(10), ADDR_COMPARATOR(11), @@ -133,17 +132,17 @@ static const struct etm_reg_info etm_addr_comp[] = { ADDR_COMPARATOR(13), ADDR_COMPARATOR(14), ADDR_COMPARATOR(15), + ADDR_COMPARATOR(16), #undef ADDR_COMPARATOR }; static const struct etm_reg_info etm_data_comp[] = { /* Data Value Comparators (NOTE: odd addresses are reserved) */ #define DATA_COMPARATOR(i) \ - { ETM_DATA_COMPARATOR_VALUE + 2*(i), 32, WO, 0x10, \ - "ETM_DATA_COMPARATOR_VALUE" #i, }, \ - { ETM_DATA_COMPARATOR_MASK + 2*(i), 32, WO, 0x10, \ - "ETM_DATA_COMPARATOR_MASK" #i, } - DATA_COMPARATOR(0), + { ETM_DATA_COMPARATOR_VALUE + 2*(i) - 1, 32, WO, 0x10, \ + "ETM_data_" #i "_comparator_value", }, \ + { ETM_DATA_COMPARATOR_MASK + 2*(i) - 1, 32, WO, 0x10, \ + "ETM_data_" #i "_comparator_mask", } DATA_COMPARATOR(1), DATA_COMPARATOR(2), DATA_COMPARATOR(3), @@ -151,30 +150,31 @@ static const struct etm_reg_info etm_data_comp[] = { DATA_COMPARATOR(5), DATA_COMPARATOR(6), DATA_COMPARATOR(7), + DATA_COMPARATOR(8), #undef DATA_COMPARATOR }; static const struct etm_reg_info etm_counters[] = { #define ETM_COUNTER(i) \ - { ETM_COUNTER_RELOAD_VALUE + (i), 16, WO, 0x10, \ - "ETM_COUNTER_RELOAD_VALUE" #i, }, \ - { ETM_COUNTER_ENABLE + (i), 18, WO, 0x10, \ - "ETM_COUNTER_ENABLE" #i, }, \ - { ETM_COUNTER_RELOAD_EVENT + (i), 17, WO, 0x10, \ - "ETM_COUNTER_RELOAD_EVENT" #i, }, \ - { ETM_COUNTER_VALUE + (i), 16, RO, 0x10, \ - "ETM_COUNTER_VALUE" #i, } - ETM_COUNTER(0), + { ETM_COUNTER_RELOAD_VALUE + (i) - 1, 16, WO, 0x10, \ + "ETM_counter_" #i "_reload_value", }, \ + { ETM_COUNTER_ENABLE + (i) - 1, 18, WO, 0x10, \ + "ETM_counter_" #i "_enable", }, \ + { ETM_COUNTER_RELOAD_EVENT + (i) - 1, 17, WO, 0x10, \ + "ETM_counter_" #i "_reload_event", }, \ + { ETM_COUNTER_VALUE + (i) - 1, 16, RO, 0x10, \ + "ETM_counter_" #i "_value", } ETM_COUNTER(1), ETM_COUNTER(2), ETM_COUNTER(3), + ETM_COUNTER(4), #undef ETM_COUNTER }; static const struct etm_reg_info etm_sequencer[] = { #define ETM_SEQ(i) \ { ETM_SEQUENCER_EVENT + (i), 17, WO, 0x10, \ - "ETM_SEQUENCER_EVENT" #i, } + "ETM_sequencer_event" #i, } ETM_SEQ(0), /* 1->2 */ ETM_SEQ(1), /* 2->1 */ ETM_SEQ(2), /* 2->3 */ @@ -183,18 +183,18 @@ static const struct etm_reg_info etm_sequencer[] = { ETM_SEQ(5), /* 1->3 */ #undef ETM_SEQ /* 0x66 reserved */ - { ETM_SEQUENCER_STATE, 2, RO, 0x10, "ETM_SEQUENCER_STATE", }, + { ETM_SEQUENCER_STATE, 2, RO, 0x10, "ETM_sequencer_state", }, }; static const struct etm_reg_info etm_outputs[] = { #define ETM_OUTPUT(i) \ - { ETM_EXTERNAL_OUTPUT + (i), 17, WO, 0x10, \ - "ETM_EXTERNAL_OUTPUT" #i, } + { ETM_EXTERNAL_OUTPUT + (i) - 1, 17, WO, 0x10, \ + "ETM_external_output" #i, } - ETM_OUTPUT(0), ETM_OUTPUT(1), ETM_OUTPUT(2), ETM_OUTPUT(3), + ETM_OUTPUT(4), #undef ETM_OUTPUT }; @@ -202,10 +202,10 @@ static const struct etm_reg_info etm_outputs[] = { /* registers from 0x6c..0x7f were added after ETMv1.3 */ /* Context ID Comparators */ - { 0x6c, 32, RO, 0x20, "ETM_CONTEXTID_COMPARATOR_VALUE1", } - { 0x6d, 32, RO, 0x20, "ETM_CONTEXTID_COMPARATOR_VALUE1", } - { 0x6e, 32, RO, 0x20, "ETM_CONTEXTID_COMPARATOR_VALUE1", } - { 0x6f, 32, RO, 0x20, "ETM_CONTEXTID_COMPARATOR_MASK", } + { 0x6c, 32, RO, 0x20, "ETM_contextid_comparator_value1", } + { 0x6d, 32, RO, 0x20, "ETM_contextid_comparator_value2", } + { 0x6e, 32, RO, 0x20, "ETM_contextid_comparator_value3", } + { 0x6f, 32, RO, 0x20, "ETM_contextid_comparator_mask", } #endif static int etm_reg_arch_type = -1; @@ -1180,6 +1180,7 @@ static int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char if (argc == 4) { + /* what parts of data access are traced? */ if (strcmp(args[0], "none") == 0) { tracemode = ETMV1_TRACE_NONE; @@ -1248,6 +1249,12 @@ static int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char command_print(cmd_ctx, "invalid option '%s'", args[2]); return ERROR_OK; } + + /* IGNORED: + * - CPRT tracing (coprocessor register transfers) + * - debug request (causes debug entry on trigger) + * - stall on FIFOFULL (preventing tracedata lossage) + */ } else if (argc != 0) { -- 2.39.5