OpenOCD
commands.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2005 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) 2009 SoftPLC Corporation *
11  * http://softplc.com *
12  * dick@softplc.com *
13  * *
14  * Copyright (C) 2009 Zachary T Welch *
15  * zw@superlucidity.net *
16  ***************************************************************************/
17 
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 
22 #include <jtag/jtag.h>
23 #include <transport/transport.h>
24 #include "commands.h"
25 
28  void *address;
29  size_t used;
30 };
31 
32 #define CMD_QUEUE_PAGE_SIZE (1024 * 1024)
35 
38 
40 {
41  if (!transport_is_jtag()) {
42  /*
43  * FIXME: This should not happen!
44  * There could be old code that queues jtag commands with non jtag interfaces so, for
45  * the moment simply highlight it by log an error.
46  * We should fix it quitting with assert(0) because it is an internal error, or returning
47  * an error after call to jtag_command_queue_reset() to free the jtag queue and avoid
48  * memory leaks.
49  * The fix can be applied immediately after next release (v0.11.0 ?)
50  */
51  LOG_ERROR("JTAG API jtag_queue_command() called on non JTAG interface");
52  }
53 
54  /* this command goes on the end, so ensure the queue terminates */
55  cmd->next = NULL;
56 
57  struct jtag_command **last_cmd = next_command_pointer;
58  assert(last_cmd);
59  assert(!*last_cmd);
60  *last_cmd = cmd;
61 
62  /* store location where the next command pointer will be stored */
63  next_command_pointer = &cmd->next;
64 }
65 
66 void *cmd_queue_alloc(size_t size)
67 {
68  struct cmd_queue_page **p_page = &cmd_queue_pages;
69  int offset;
70  uint8_t *t;
71 
72  /*
73  * WARNING:
74  * We align/round the *SIZE* per below
75  * so that all pointers returned by
76  * this function are reasonably well
77  * aligned.
78  *
79  * If we did not, then an "odd-length" request would cause the
80  * *next* allocation to be at an *odd* address, and because
81  * this function has the same type of api as malloc() - we
82  * must also return pointers that have the same type of
83  * alignment.
84  *
85  * What I do not/have is a reasonable portable means
86  * to align by...
87  *
88  * The solution here, is based on these suggestions.
89  * http://gcc.gnu.org/ml/gcc-help/2008-12/msg00041.html
90  *
91  */
92  union worse_case_align {
93  int i;
94  long l;
95  float f;
96  void *v;
97  };
98 #define ALIGN_SIZE (sizeof(union worse_case_align))
99 
100  /* The alignment process. */
101  size = (size + ALIGN_SIZE - 1) & (~(ALIGN_SIZE - 1));
102  /* Done... */
103 
104  if (*p_page) {
105  p_page = &cmd_queue_pages_tail;
106  if (CMD_QUEUE_PAGE_SIZE < (*p_page)->used + size)
107  p_page = &((*p_page)->next);
108  }
109 
110  if (!*p_page) {
111  *p_page = malloc(sizeof(struct cmd_queue_page));
112  (*p_page)->used = 0;
113  size_t alloc_size = (size < CMD_QUEUE_PAGE_SIZE) ?
115  (*p_page)->address = malloc(alloc_size);
116  (*p_page)->next = NULL;
117  cmd_queue_pages_tail = *p_page;
118  }
119 
120  offset = (*p_page)->used;
121  (*p_page)->used += size;
122 
123  t = (*p_page)->address;
124  return t + offset;
125 }
126 
127 static void cmd_queue_free(void)
128 {
129  struct cmd_queue_page *page = cmd_queue_pages;
130 
131  while (page) {
132  struct cmd_queue_page *last = page;
133  free(page->address);
134  page = page->next;
135  free(last);
136  }
137 
140 }
141 
143 {
144  cmd_queue_free();
145 
148 }
149 
151 {
152  return jtag_command_queue;
153 }
154 
160 void jtag_scan_field_clone(struct scan_field *dst, const struct scan_field *src)
161 {
162  dst->num_bits = src->num_bits;
164  dst->in_value = src->in_value;
165 }
166 
167 enum scan_type jtag_scan_type(const struct scan_command *cmd)
168 {
169  int type = 0;
170 
171  for (unsigned int i = 0; i < cmd->num_fields; i++) {
172  if (cmd->fields[i].in_value)
173  type |= SCAN_IN;
174  if (cmd->fields[i].out_value)
175  type |= SCAN_OUT;
176  }
177 
178  return type;
179 }
180 
181 unsigned int jtag_scan_size(const struct scan_command *cmd)
182 {
183  unsigned int bit_count = 0;
184 
185  /* count bits in scan command */
186  for (unsigned int i = 0; i < cmd->num_fields; i++)
187  bit_count += cmd->fields[i].num_bits;
188 
189  return bit_count;
190 }
191 
192 int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer)
193 {
194  unsigned int bit_count = jtag_scan_size(cmd);
195  *buffer = calloc(1, DIV_ROUND_UP(bit_count, 8));
196 
197  bit_count = 0;
198 
199  LOG_DEBUG_IO("%s num_fields: %u",
200  cmd->ir_scan ? "IRSCAN" : "DRSCAN",
201  cmd->num_fields);
202 
203  for (unsigned int i = 0; i < cmd->num_fields; i++) {
204  if (cmd->fields[i].out_value) {
206  char *char_buf = buf_to_hex_str(cmd->fields[i].out_value,
207  (cmd->fields[i].num_bits > DEBUG_JTAG_IOZ)
209  : cmd->fields[i].num_bits);
210 
211  LOG_DEBUG("fields[%u].out_value[%u]: 0x%s", i,
212  cmd->fields[i].num_bits, char_buf);
213  free(char_buf);
214  }
215  buf_set_buf(cmd->fields[i].out_value, 0, *buffer,
216  bit_count, cmd->fields[i].num_bits);
217  } else {
218  LOG_DEBUG_IO("fields[%u].out_value[%u]: NULL",
219  i, cmd->fields[i].num_bits);
220  }
221 
222  bit_count += cmd->fields[i].num_bits;
223  }
224 
225  /*LOG_DEBUG_IO("bit_count totalling: %i", bit_count); */
226 
227  return bit_count;
228 }
229 
230 int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd)
231 {
232  int bit_count = 0;
233  int retval;
234 
235  /* we return ERROR_OK, unless a check fails, or a handler reports a problem */
236  retval = ERROR_OK;
237 
238  for (unsigned int i = 0; i < cmd->num_fields; i++) {
239  /* if neither in_value nor in_handler
240  * are specified we don't have to examine this field
241  */
242  if (cmd->fields[i].in_value) {
243  const unsigned int num_bits = cmd->fields[i].num_bits;
244  uint8_t *captured = buf_set_buf(buffer, bit_count,
245  malloc(DIV_ROUND_UP(num_bits, 8)), 0, num_bits);
246 
248  char *char_buf = buf_to_hex_str(captured,
249  (num_bits > DEBUG_JTAG_IOZ)
251  : num_bits);
252 
253  LOG_DEBUG("fields[%u].in_value[%u]: 0x%s",
254  i, num_bits, char_buf);
255  free(char_buf);
256  }
257 
258  if (cmd->fields[i].in_value)
259  buf_cpy(captured, cmd->fields[i].in_value, num_bits);
260 
261  free(captured);
262  }
263  bit_count += cmd->fields[i].num_bits;
264  }
265 
266  return retval;
267 }
char * buf_to_hex_str(const void *_buf, unsigned int buf_len)
Definition: binarybuffer.c:178
void * buf_set_buf(const void *_src, unsigned int src_start, void *_dst, unsigned int dst_start, unsigned int len)
Definition: binarybuffer.c:120
void * buf_cpy(const void *from, void *_to, unsigned int size)
Copies size bits out of from and into to.
Definition: binarybuffer.c:43
static struct jtag_command * jtag_command_queue
Definition: commands.c:36
struct jtag_command * jtag_command_queue_get(void)
Definition: commands.c:150
unsigned int jtag_scan_size(const struct scan_command *cmd)
Definition: commands.c:181
int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer)
Definition: commands.c:192
void jtag_queue_command(struct jtag_command *cmd)
Definition: commands.c:39
void jtag_scan_field_clone(struct scan_field *dst, const struct scan_field *src)
Copy a struct scan_field for insertion into the queue.
Definition: commands.c:160
#define ALIGN_SIZE
enum scan_type jtag_scan_type(const struct scan_command *cmd)
Definition: commands.c:167
#define CMD_QUEUE_PAGE_SIZE
Definition: commands.c:32
static struct cmd_queue_page * cmd_queue_pages
Definition: commands.c:33
static struct jtag_command ** next_command_pointer
Definition: commands.c:37
int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd)
Definition: commands.c:230
static struct cmd_queue_page * cmd_queue_pages_tail
Definition: commands.c:34
void jtag_command_queue_reset(void)
Definition: commands.c:142
void * cmd_queue_alloc(size_t size)
Definition: commands.c:66
static void cmd_queue_free(void)
Definition: commands.c:127
scan_type
The inferred type of a scan_command structure, indicating whether the command has the host scan in fr...
Definition: commands.h:22
@ SCAN_IN
From device to host,.
Definition: commands.h:24
@ SCAN_OUT
From host to device,.
Definition: commands.h:26
uint8_t type
Definition: esp_usb_jtag.c:0
bool transport_is_jtag(void)
Returns true if the current debug session is using JTAG as its transport.
Definition: jtag/core.c:1827
The JTAG interface can be implemented with a software or hardware fifo.
#define DEBUG_JTAG_IOZ
Definition: jtag.h:20
#define LOG_DEBUG_IO(expr ...)
Definition: log.h:101
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_LEVEL_IS(FOO)
Definition: log.h:99
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
@ LOG_LVL_DEBUG_IO
Definition: log.h:48
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
size_t used
Definition: commands.c:29
struct cmd_queue_page * next
Definition: commands.c:27
void * address
Definition: commands.c:28
The scan_command provide a means of encapsulating a set of scan_field structures that should be scann...
Definition: commands.h:35
This structure defines a single scan field in the scan.
Definition: jtag.h:87
uint8_t * in_value
A pointer to a 32-bit memory location for data scanned out.
Definition: jtag.h:93
const uint8_t * out_value
A pointer to value to be scanned into the device.
Definition: jtag.h:91
unsigned int num_bits
The number of bits this field specifies.
Definition: jtag.h:89
#define DIV_ROUND_UP(m, n)
Rounds m up to the nearest multiple of n using division.
Definition: types.h:79
#define NULL
Definition: usb.h:16
uint8_t cmd
Definition: vdebug.c:1
uint8_t offset[4]
Definition: vdebug.c:9