OpenOCD
armv7m_trace.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2015 Paul Fertser <fercerpav@gmail.com> *
5  ***************************************************************************/
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include <target/target.h>
12 #include <target/armv7m.h>
13 #include <target/cortex_m.h>
14 #include <target/armv7m_trace.h>
15 #include <jtag/interface.h>
16 #include <helper/time_support.h>
17 
19 {
20  struct armv7m_common *armv7m = target_to_armv7m(target);
21  struct armv7m_trace_config *trace_config = &armv7m->trace_config;
22  int retval;
23 
25  if (retval != ERROR_OK)
26  return retval;
27 
28  /* pg315 of CoreSight Components
29  * It is recommended that the ITMEn bit is cleared and waits for the
30  * ITMBusy bit to be cleared, before changing any fields in the
31  * Control Register, otherwise the behavior can be unpredictable.
32  */
33  uint32_t itm_tcr;
34  retval = target_read_u32(target, ITM_TCR, &itm_tcr);
35  if (retval != ERROR_OK)
36  return retval;
37  retval = target_write_u32(target,
38  ITM_TCR,
39  itm_tcr & ~ITM_TCR_ITMENA_BIT
40  );
41  if (retval != ERROR_OK)
42  return retval;
43 
44  int64_t then = timeval_ms() + 1000;
45  do {
46  retval = target_read_u32(target, ITM_TCR, &itm_tcr);
47  if (retval != ERROR_OK)
48  return retval;
49  if (timeval_ms() > then) {
50  LOG_ERROR("timeout waiting for ITM_TCR_BUSY_BIT");
51  return ERROR_FAIL;
52  }
53  } while (itm_tcr & ITM_TCR_BUSY_BIT);
54 
55  /* Enable ITM, TXENA, set TraceBusID and other parameters */
56  retval = target_write_u32(target, ITM_TCR, (1 << 0) | (1 << 3) |
57  (trace_config->itm_diff_timestamps << 1) |
58  (trace_config->itm_synchro_packets << 2) |
59  (trace_config->itm_async_timestamps << 4) |
60  (trace_config->itm_ts_prescale << 8) |
61  (trace_config->trace_bus_id << 16));
62  if (retval != ERROR_OK)
63  return retval;
64 
65  for (unsigned int i = 0; i < 8; i++) {
66  retval = target_write_u32(target, ITM_TER0 + i * 4,
67  trace_config->itm_ter[i]);
68  if (retval != ERROR_OK)
69  return retval;
70  }
71 
72  return ERROR_OK;
73 }
74 
75 COMMAND_HANDLER(handle_itm_port_command)
76 {
78  struct armv7m_common *armv7m = target_to_armv7m(target);
79  unsigned int reg_idx;
80  uint8_t port;
81  bool enable;
82 
83  if (CMD_ARGC != 2)
85 
86  COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], port);
87  COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable);
88  reg_idx = port / 32;
89  port = port % 32;
90  if (enable)
91  armv7m->trace_config.itm_ter[reg_idx] |= (1 << port);
92  else
93  armv7m->trace_config.itm_ter[reg_idx] &= ~(1 << port);
94 
95  /*
96  * In config mode ITM is not accessible yet.
97  * Keep the value and it will be programmed at target init.
98  */
99  if (CMD_CTX->mode == COMMAND_CONFIG)
100  return ERROR_OK;
101 
103 }
104 
105 COMMAND_HANDLER(handle_itm_ports_command)
106 {
108  struct armv7m_common *armv7m = target_to_armv7m(target);
109  bool enable;
110 
111  if (CMD_ARGC != 1)
113 
114  COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
115  memset(armv7m->trace_config.itm_ter, enable ? 0xff : 0,
116  sizeof(armv7m->trace_config.itm_ter));
117 
118  /*
119  * In config mode ITM is not accessible yet.
120  * Keep the value and it will be programmed at target init.
121  */
122  if (CMD_CTX->mode == COMMAND_CONFIG)
123  return ERROR_OK;
124 
126 }
127 
128 static const struct command_registration itm_command_handlers[] = {
129  {
130  .name = "port",
131  .handler = handle_itm_port_command,
132  .mode = COMMAND_ANY,
133  .help = "Enable or disable ITM stimulus port",
134  .usage = "<port> (0|1|on|off)",
135  },
136  {
137  .name = "ports",
138  .handler = handle_itm_ports_command,
139  .mode = COMMAND_ANY,
140  .help = "Enable or disable all ITM stimulus ports",
141  .usage = "(0|1|on|off)",
142  },
144 };
145 
147  {
148  .name = "itm",
149  .mode = COMMAND_ANY,
150  .help = "itm command group",
151  .usage = "",
152  .chain = itm_command_handlers,
153  },
155 };
static struct armv7m_common * target_to_armv7m(struct target *target)
Definition: armv7m.h:262
COMMAND_HANDLER(handle_itm_port_command)
Definition: armv7m_trace.c:75
const struct command_registration armv7m_trace_command_handlers[]
Definition: armv7m_trace.c:146
static const struct command_registration itm_command_handlers[]
Definition: armv7m_trace.c:128
int armv7m_trace_itm_config(struct target *target)
Configure hardware accordingly to the current ITM target settings.
Definition: armv7m_trace.c:18
Holds the interface to ITM and DWT configuration functions.
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define COMMAND_PARSE_ON_OFF(in, out)
parses an on/off command argument
Definition: command.h:530
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:402
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define COMMAND_PARSE_NUMBER(type, in, out)
parses the string in into out as a type, or prints a command error and passes the error code to the c...
Definition: command.h:442
#define CMD_CTX
Use this macro to access the context of the command being handled, rather than accessing the variable...
Definition: command.h:146
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:253
@ COMMAND_CONFIG
Definition: command.h:41
@ COMMAND_ANY
Definition: command.h:42
#define ITM_TCR_ITMENA_BIT
Definition: cortex_m.h:27
#define ITM_LAR_KEY
Definition: cortex_m.h:30
#define ITM_TCR
Definition: cortex_m.h:26
#define ITM_TER0
Definition: cortex_m.h:24
#define ITM_TCR_BUSY_BIT
Definition: cortex_m.h:28
#define ITM_LAR
Definition: cortex_m.h:29
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define ERROR_OK
Definition: log.h:164
struct armv7m_trace_config trace_config
Definition: armv7m.h:238
uint32_t itm_ter[8]
Bitmask of currently enabled ITM stimuli.
Definition: armv7m_trace.h:27
unsigned int trace_bus_id
Identifier for multi-source trace stream formatting.
Definition: armv7m_trace.h:29
bool itm_diff_timestamps
Enable differential timestamps.
Definition: armv7m_trace.h:33
bool itm_async_timestamps
Enable async timestamps model.
Definition: armv7m_trace.h:35
bool itm_synchro_packets
Enable synchronisation packet transmission (for sync port only)
Definition: armv7m_trace.h:37
enum itm_ts_prescaler itm_ts_prescale
Prescaler for the timestamp counter.
Definition: armv7m_trace.h:31
const char * name
Definition: command.h:235
Definition: target.h:116
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
Definition: target.c:2641
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
Definition: target.c:2550
struct target * get_current_target(struct command_context *cmd_ctx)
Definition: target.c:458
int64_t timeval_ms(void)