OpenOCD
target_request.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2007 by Dominic Rath *
5  * Dominic.Rath@gmx.de *
6  * *
7  * Copyright (C) 2007,2008 Øyvind Harboe *
8  * oyvind.harboe@zylin.com *
9  * *
10  * Copyright (C) 2008 by Spencer Oliver *
11  * spen@spen-soft.co.uk *
12  ***************************************************************************/
13 
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17 
18 #include <helper/log.h>
19 #include <helper/binarybuffer.h>
20 
21 #include "target.h"
22 #include "target_request.h"
23 #include "target_type.h"
24 #include "trace.h"
25 
26 static bool got_message;
27 
29 {
30  bool t = got_message;
31  got_message = false;
32  return t;
33 }
34 
35 static int charmsg_mode;
36 
37 static int target_asciimsg(struct target *target, uint32_t length)
38 {
39  char *msg = malloc(DIV_ROUND_UP(length + 1, 4) * 4);
40  struct debug_msg_receiver *c = target->dbgmsg;
41 
42  target->type->target_request_data(target, DIV_ROUND_UP(length, 4), (uint8_t *)msg);
43  msg[length] = 0;
44 
45  LOG_DEBUG("%s", msg);
46 
47  while (c) {
49  c = c->next;
50  }
51 
52  return ERROR_OK;
53 }
54 
55 static int target_charmsg(struct target *target, uint8_t msg)
56 {
57  LOG_USER_N("%c", msg);
58 
59  return ERROR_OK;
60 }
61 
62 static int target_hexmsg(struct target *target, int size, uint32_t length)
63 {
64  uint8_t *data = malloc(DIV_ROUND_UP(length * size, 4) * 4);
65  char line[128];
66  int line_len;
67  struct debug_msg_receiver *c = target->dbgmsg;
68  uint32_t i;
69 
70  LOG_DEBUG("size: %i, length: %i", (int)size, (int)length);
71 
72  target->type->target_request_data(target, DIV_ROUND_UP(length * size, 4), (uint8_t *)data);
73 
74  line_len = 0;
75  for (i = 0; i < length; i++) {
76  switch (size) {
77  case 4:
78  line_len += snprintf(line + line_len, 128 - line_len, "%8.8" PRIx32 " ", le_to_h_u32(data + (4*i)));
79  break;
80  case 2:
81  line_len += snprintf(line + line_len, 128 - line_len, "%4.4x ", le_to_h_u16(data + (2*i)));
82  break;
83  case 1:
84  line_len += snprintf(line + line_len, 128 - line_len, "%2.2x ", data[i]);
85  break;
86  }
87 
88  if ((i%8 == 7) || (i == length - 1)) {
89  LOG_DEBUG("%s", line);
90 
91  while (c) {
92  command_output_text(c->cmd_ctx, line);
93  c = c->next;
94  }
95  c = target->dbgmsg;
96  line_len = 0;
97  }
98  }
99 
100  free(data);
101 
102  return ERROR_OK;
103 }
104 
105 /* handle requests from the target received by a target specific
106  * side-band channel (e.g. ARM7/9 DCC)
107  */
108 int target_request(struct target *target, uint32_t request)
109 {
110  target_req_cmd_t target_req_cmd = request & 0xff;
111 
112  assert(target->type->target_request_data);
113 
114  /* Record that we got a target message for back-off algorithm */
115  got_message = true;
116 
117  if (charmsg_mode) {
119  return ERROR_OK;
120  }
121 
122  switch (target_req_cmd) {
123  case TARGET_REQ_TRACEMSG:
124  trace_point(target, (request & 0xffffff00) >> 8);
125  break;
126  case TARGET_REQ_DEBUGMSG:
127  if (((request & 0xff00) >> 8) == 0)
128  target_asciimsg(target, (request & 0xffff0000) >> 16);
129  else
130  target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16);
131  break;
133  target_charmsg(target, (request & 0x00ff0000) >> 16);
134  break;
135 /* case TARGET_REQ_SEMIHOSTING:
136  * break;
137  */
138  default:
139  LOG_ERROR("unknown target request: %2.2x", target_req_cmd);
140  break;
141  }
142 
143  return ERROR_OK;
144 }
145 
147 {
148  struct debug_msg_receiver **p = &target->dbgmsg;
149 
150  if (!target)
152 
153  /* see if there's already a list */
154  if (*p) {
155  /* find end of linked list */
156  while ((*p)->next)
157  p = &((*p)->next);
158  p = &((*p)->next);
159  }
160 
161  /* add new debug message receiver */
162  (*p) = malloc(sizeof(struct debug_msg_receiver));
163  (*p)->cmd_ctx = cmd_ctx;
164  (*p)->next = NULL;
165 
166  /* enable callback */
167  target->dbg_msg_enabled = true;
168 
169  return ERROR_OK;
170 }
171 
173  struct target *target)
174 {
175  int do_all_targets = 0;
176 
177  /* if no target has been specified search all of them */
178  if (!target) {
179  /* if no targets haven been specified */
180  if (!all_targets)
181  return NULL;
182 
184  do_all_targets = 1;
185  }
186 
187  /* so we target != null */
188  struct debug_msg_receiver **p = &target->dbgmsg;
189  do {
190  while (*p) {
191  if ((*p)->cmd_ctx == cmd_ctx)
192  return *p;
193  p = &((*p)->next);
194  }
195 
196  target = target->next;
197  } while (target && do_all_targets);
198 
199  return NULL;
200 }
201 
203 {
204  struct debug_msg_receiver **p;
205  struct debug_msg_receiver *c;
206  int do_all_targets = 0;
207 
208  /* if no target has been specified search all of them */
209  if (!target) {
210  /* if no targets haven been specified */
211  if (!all_targets)
212  return ERROR_OK;
213 
215  do_all_targets = 1;
216  }
217 
218  do {
219  p = &target->dbgmsg;
220  c = *p;
221  while (c) {
222  struct debug_msg_receiver *next = c->next;
223  if (c->cmd_ctx == cmd_ctx) {
224  *p = next;
225  free(c);
226  if (!*p) {
227  /* disable callback */
228  target->dbg_msg_enabled = false;
229  }
230  return ERROR_OK;
231  } else
232  p = &(c->next);
233  c = next;
234  }
235 
236  target = target->next;
237  } while (target && do_all_targets);
238 
239  return ERROR_OK;
240 }
241 
242 COMMAND_HANDLER(handle_target_request_debugmsgs_command)
243 {
245 
246  int receiving = 0;
247 
249  LOG_ERROR("Target %s does not support target requests", target_name(target));
250  return ERROR_OK;
251  }
252 
253  /* see if receiver is already registered */
255  receiving = 1;
256 
257  if (CMD_ARGC > 0) {
258  if (!strcmp(CMD_ARGV[0], "enable") || !strcmp(CMD_ARGV[0], "charmsg")) {
259  /* don't register if this command context is already receiving */
260  if (!receiving) {
261  receiving = 1;
263  }
264  charmsg_mode = !strcmp(CMD_ARGV[0], "charmsg");
265  } else if (!strcmp(CMD_ARGV[0], "disable")) {
266  /* no need to delete a receiver if none is registered */
267  if (receiving) {
268  receiving = 0;
270  }
271  } else
273  }
274 
275  command_print(CMD, "receiving debug messages from current target %s",
276  (receiving) ? (charmsg_mode ? "charmsg" : "enabled") : "disabled");
277  return ERROR_OK;
278 }
279 
281  {
282  .name = "debugmsgs",
283  .handler = handle_target_request_debugmsgs_command,
284  .mode = COMMAND_EXEC,
285  .help = "display and/or modify reception of debug messages from target",
286  .usage = "['enable'|'charmsg'|'disable']",
287  },
289 };
290 static const struct command_registration target_req_command_handlers[] = {
291  {
292  .name = "target_request",
293  .mode = COMMAND_ANY,
294  .help = "target request command group",
295  .usage = "",
297  },
299 };
300 
302 {
304 }
Support functions to access arbitrary bits in a byte array.
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:443
void command_output_text(struct command_context *context, const char *data)
Definition: command.c:414
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
Definition: command.h:141
#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 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 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
static int register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, const struct command_registration *cmds)
Register one or more commands in the specified context, as children of parent (or top-level commends,...
Definition: command.h:274
@ COMMAND_ANY
Definition: command.h:42
@ COMMAND_EXEC
Definition: command.h:40
uint8_t length
Definition: esp_usb_jtag.c:1
#define LOG_USER_N(expr ...)
Definition: log.h:138
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
const char * name
Definition: command.h:235
struct debug_msg_receiver * next
struct command_context * cmd_ctx
int(* target_request_data)(struct target *target, uint32_t size, uint8_t *buffer)
Definition: target_type.h:40
Definition: target.h:116
bool dbg_msg_enabled
Definition: target.h:163
struct debug_msg_receiver * dbgmsg
Definition: target.h:162
struct target_type * type
Definition: target.h:117
struct target * next
Definition: target.h:166
struct target * all_targets
Definition: target.c:107
struct target * get_current_target(struct command_context *cmd_ctx)
Definition: target.c:458
static const char * target_name(const struct target *target)
Returns the instance-specific name of the specified target.
Definition: target.h:233
static int charmsg_mode
static const struct command_registration target_req_command_handlers[]
int target_request_register_commands(struct command_context *cmd_ctx)
static int target_hexmsg(struct target *target, int size, uint32_t length)
bool target_got_message(void)
Read and clear the flag as to whether we got a message.
int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
static int target_charmsg(struct target *target, uint8_t msg)
static int add_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
static int target_asciimsg(struct target *target, uint32_t length)
static bool got_message
static const struct command_registration target_req_exec_command_handlers[]
int target_request(struct target *target, uint32_t request)
static struct debug_msg_receiver * find_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
COMMAND_HANDLER(handle_target_request_debugmsgs_command)
enum target_req_cmd target_req_cmd_t
target_req_cmd
@ TARGET_REQ_DEBUGCHAR
@ TARGET_REQ_DEBUGMSG
@ TARGET_REQ_TRACEMSG
int trace_point(struct target *target, uint32_t number)
Definition: trace.c:16
static uint16_t le_to_h_u16(const uint8_t *buf)
Definition: types.h:122
#define DIV_ROUND_UP(m, n)
Rounds m up to the nearest multiple of n using division.
Definition: types.h:79
static uint32_t le_to_h_u32(const uint8_t *buf)
Definition: types.h:112
#define NULL
Definition: usb.h:16