- added support for error handlers to JTAG scan commands (jtag_[plain_][ir|dr]_scan)
[openocd.git] / src / target / etb.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "arm7_9_common.h"
25 #include "etb.h"
26
27 #include "log.h"
28 #include "types.h"
29 #include "binarybuffer.h"
30 #include "target.h"
31 #include "register.h"
32 #include "jtag.h"
33
34 #include <stdlib.h>
35
36 char* etb_reg_list[] =
37 {
38 "ETB_identification",
39 "ETB_ram_depth",
40 "ETB_ram_width",
41 "ETB_status",
42 "ETB_ram_data",
43 "ETB_ram_read_pointer",
44 "ETB_ram_write_pointer",
45 "ETB_trigger_counter",
46 "ETB_control",
47 };
48
49 int etb_reg_arch_type = -1;
50
51 int etb_get_reg(reg_t *reg);
52 int etb_set_reg(reg_t *reg, u32 value);
53 int etb_set_reg_w_exec(reg_t *reg, u8 *buf);
54
55 int etb_write_reg(reg_t *reg, u32 value);
56 int etb_read_reg(reg_t *reg);
57
58 int handle_arm7_9_etb_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
59 int handle_arm7_9_etb_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
60
61 int etb_set_instr(etb_t *etb, u32 new_instr)
62 {
63 jtag_device_t *device = jtag_get_device(etb->chain_pos);
64
65 if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
66 {
67 scan_field_t field;
68
69 field.device = etb->chain_pos;
70 field.num_bits = device->ir_length;
71 field.out_value = calloc(CEIL(field.num_bits, 8), 1);
72 buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
73 field.out_mask = NULL;
74 field.in_value = NULL;
75 field.in_check_value = NULL;
76 field.in_check_mask = NULL;
77 field.in_handler = NULL;
78 field.in_handler_priv = NULL;
79
80 jtag_add_ir_scan(1, &field, -1, NULL);
81
82 free(field.out_value);
83 }
84
85 return ERROR_OK;
86 }
87
88 int etb_scann(etb_t *etb, u32 new_scan_chain)
89 {
90 if(etb->cur_scan_chain != new_scan_chain)
91 {
92 scan_field_t field;
93
94 field.device = etb->chain_pos;
95 field.num_bits = 5;
96 field.out_value = calloc(CEIL(field.num_bits, 8), 1);
97 buf_set_u32(field.out_value, 0, field.num_bits, new_scan_chain);
98 field.out_mask = NULL;
99 field.in_value = NULL;
100 field.in_check_value = NULL;
101 field.in_check_mask = NULL;
102 field.in_handler = NULL;
103 field.in_handler_priv = NULL;
104
105 /* select INTEST instruction */
106 etb_set_instr(etb, 0x2);
107 jtag_add_dr_scan(1, &field, -1, NULL);
108
109 etb->cur_scan_chain = new_scan_chain;
110
111 free(field.out_value);
112 }
113
114 return ERROR_OK;
115 }
116
117 reg_cache_t* etb_build_reg_cache(etb_t *etb)
118 {
119 reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
120 reg_t *reg_list = NULL;
121 etb_reg_t *arch_info = NULL;
122 int num_regs = 9;
123 int i;
124
125 /* register a register arch-type for etm registers only once */
126 if (etb_reg_arch_type == -1)
127 etb_reg_arch_type = register_reg_arch_type(etb_get_reg, etb_set_reg_w_exec);
128
129 /* the actual registers are kept in two arrays */
130 reg_list = calloc(num_regs, sizeof(reg_t));
131 arch_info = calloc(num_regs, sizeof(etb_reg_t));
132
133 /* fill in values for the reg cache */
134 reg_cache->name = "etb registers";
135 reg_cache->next = NULL;
136 reg_cache->reg_list = reg_list;
137 reg_cache->num_regs = num_regs;
138
139 /* set up registers */
140 for (i = 0; i < num_regs; i++)
141 {
142 reg_list[i].name = etb_reg_list[i];
143 reg_list[i].size = 32;
144 reg_list[i].dirty = 0;
145 reg_list[i].valid = 0;
146 reg_list[i].bitfield_desc = NULL;
147 reg_list[i].num_bitfields = 0;
148 reg_list[i].value = calloc(1, 4);
149 reg_list[i].arch_info = &arch_info[i];
150 reg_list[i].arch_type = etb_reg_arch_type;
151 reg_list[i].size = 32;
152 arch_info[i].addr = i;
153 arch_info[i].etb = etb;
154 }
155
156 return reg_cache;
157 }
158
159 int etb_get_reg(reg_t *reg)
160 {
161 if (etb_read_reg(reg) != ERROR_OK)
162 {
163 ERROR("BUG: error scheduling etm register read");
164 exit(-1);
165 }
166
167 if (jtag_execute_queue() != ERROR_OK)
168 {
169 ERROR("register read failed");
170 }
171
172 return ERROR_OK;
173 }
174
175 int etb_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
176 {
177 etb_reg_t *etb_reg = reg->arch_info;
178 u8 reg_addr = etb_reg->addr & 0x7f;
179 scan_field_t fields[3];
180
181 DEBUG("%i", etb_reg->addr);
182
183 jtag_add_end_state(TAP_RTI);
184 etb_scann(etb_reg->etb, 0x0);
185 etb_set_instr(etb_reg->etb, 0xc);
186
187 fields[0].device = etb_reg->etb->chain_pos;
188 fields[0].num_bits = 32;
189 fields[0].out_value = reg->value;
190 fields[0].out_mask = NULL;
191 fields[0].in_value = NULL;
192 fields[0].in_check_value = NULL;
193 fields[0].in_check_mask = NULL;
194 fields[0].in_handler = NULL;
195 fields[0].in_handler_priv = NULL;
196
197 fields[1].device = etb_reg->etb->chain_pos;
198 fields[1].num_bits = 7;
199 fields[1].out_value = malloc(1);
200 buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
201 fields[1].out_mask = NULL;
202 fields[1].in_value = NULL;
203 fields[1].in_check_value = NULL;
204 fields[1].in_check_mask = NULL;
205 fields[1].in_handler = NULL;
206 fields[1].in_handler_priv = NULL;
207
208 fields[2].device = etb_reg->etb->chain_pos;
209 fields[2].num_bits = 1;
210 fields[2].out_value = malloc(1);
211 buf_set_u32(fields[2].out_value, 0, 1, 0);
212 fields[2].out_mask = NULL;
213 fields[2].in_value = NULL;
214 fields[2].in_check_value = NULL;
215 fields[2].in_check_mask = NULL;
216 fields[2].in_handler = NULL;
217 fields[2].in_handler_priv = NULL;
218
219 jtag_add_dr_scan(3, fields, -1, NULL);
220
221 /* read the identification register in the second run, to make sure we
222 * don't read the ETB data register twice, skipping every second entry
223 */
224 buf_set_u32(fields[1].out_value, 0, 7, 0x0);
225 fields[0].in_value = reg->value;
226 fields[0].in_check_value = check_value;
227 fields[0].in_check_mask = check_mask;
228
229 jtag_add_dr_scan(3, fields, -1, NULL);
230
231 free(fields[1].out_value);
232 free(fields[2].out_value);
233
234 return ERROR_OK;
235 }
236
237 int etb_read_reg(reg_t *reg)
238 {
239 return etb_read_reg_w_check(reg, NULL, NULL);
240 }
241
242 int etb_set_reg(reg_t *reg, u32 value)
243 {
244 if (etb_write_reg(reg, value) != ERROR_OK)
245 {
246 ERROR("BUG: error scheduling etm register write");
247 exit(-1);
248 }
249
250 buf_set_u32(reg->value, 0, reg->size, value);
251 reg->valid = 1;
252 reg->dirty = 0;
253
254 return ERROR_OK;
255 }
256
257 int etb_set_reg_w_exec(reg_t *reg, u8 *buf)
258 {
259 etb_set_reg(reg, buf_get_u32(buf, 0, reg->size));
260
261 if (jtag_execute_queue() != ERROR_OK)
262 {
263 ERROR("register write failed");
264 exit(-1);
265 }
266 return ERROR_OK;
267 }
268
269 int etb_write_reg(reg_t *reg, u32 value)
270 {
271 etb_reg_t *etb_reg = reg->arch_info;
272 u8 reg_addr = etb_reg->addr & 0x7f;
273 scan_field_t fields[3];
274
275 DEBUG("%i: 0x%8.8x", etb_reg->addr, value);
276
277 jtag_add_end_state(TAP_RTI);
278 etb_scann(etb_reg->etb, 0x0);
279 etb_set_instr(etb_reg->etb, 0xc);
280
281 fields[0].device = etb_reg->etb->chain_pos;
282 fields[0].num_bits = 32;
283 fields[0].out_value = malloc(4);
284 buf_set_u32(fields[0].out_value, 0, 32, value);
285 fields[0].out_mask = NULL;
286 fields[0].in_value = NULL;
287 fields[0].in_check_value = NULL;
288 fields[0].in_check_mask = NULL;
289 fields[0].in_handler = NULL;
290 fields[0].in_handler_priv = NULL;
291
292 fields[1].device = etb_reg->etb->chain_pos;
293 fields[1].num_bits = 7;
294 fields[1].out_value = malloc(1);
295 buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
296 fields[1].out_mask = NULL;
297 fields[1].in_value = NULL;
298 fields[1].in_check_value = NULL;
299 fields[1].in_check_mask = NULL;
300 fields[1].in_handler = NULL;
301 fields[1].in_handler_priv = NULL;
302
303 fields[2].device = etb_reg->etb->chain_pos;
304 fields[2].num_bits = 1;
305 fields[2].out_value = malloc(1);
306 buf_set_u32(fields[2].out_value, 0, 1, 1);
307 fields[2].out_mask = NULL;
308 fields[2].in_value = NULL;
309 fields[2].in_check_value = NULL;
310 fields[2].in_check_mask = NULL;
311 fields[2].in_handler = NULL;
312 fields[2].in_handler_priv = NULL;
313
314 jtag_add_dr_scan(3, fields, -1, NULL);
315
316 free(fields[0].out_value);
317 free(fields[1].out_value);
318 free(fields[2].out_value);
319
320 return ERROR_OK;
321 }
322
323 int etb_store_reg(reg_t *reg)
324 {
325 return etb_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
326 }
327
328 int etb_register_commands(struct command_context_s *cmd_ctx, command_t *arm7_9_cmd)
329 {
330 register_command(cmd_ctx, arm7_9_cmd, "etb", handle_arm7_9_etb_command, COMMAND_CONFIG, NULL);
331
332 register_command(cmd_ctx, arm7_9_cmd, "etb_dump", handle_arm7_9_etb_dump_command, COMMAND_EXEC, "dump current ETB content");
333
334 return ERROR_OK;
335 }
336
337 int handle_arm7_9_etb_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
338 {
339 int retval;
340 target_t *target = get_current_target(cmd_ctx);
341 armv4_5_common_t *armv4_5;
342 arm7_9_common_t *arm7_9;
343 int i;
344
345 if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
346 {
347 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
348 return ERROR_OK;
349 }
350
351 if (!arm7_9->etb)
352 {
353 command_print(cmd_ctx, "no ETB configured for current target");
354 return ERROR_OK;
355 }
356
357 if (!(arm7_9->etb->RAM_depth && arm7_9->etb->RAM_width))
358 {
359 /* identify ETB RAM depth and width */
360 etb_read_reg(&arm7_9->etb->reg_cache->reg_list[ETB_RAM_DEPTH]);
361 etb_read_reg(&arm7_9->etb->reg_cache->reg_list[ETB_RAM_WIDTH]);
362 jtag_execute_queue();
363
364 arm7_9->etb->RAM_depth = buf_get_u32(arm7_9->etb->reg_cache->reg_list[ETB_RAM_DEPTH].value, 0, 32);
365 arm7_9->etb->RAM_width = buf_get_u32(arm7_9->etb->reg_cache->reg_list[ETB_RAM_WIDTH].value, 0, 32);
366 }
367
368 /* always start reading from the beginning of the buffer */
369 etb_write_reg(&arm7_9->etb->reg_cache->reg_list[ETB_RAM_READ_POINTER], 0x0);
370 for (i = 0; i < arm7_9->etb->RAM_depth; i++)
371 {
372 u32 trace_data;
373 etb_read_reg(&arm7_9->etb->reg_cache->reg_list[ETB_RAM_DATA]);
374 jtag_execute_queue();
375 trace_data = buf_get_u32(arm7_9->etb->reg_cache->reg_list[ETB_RAM_DATA].value, 0, 32);
376 command_print(cmd_ctx, "%8.8i: %i %2.2x %2.2x %2.2x (0x%8.8x)",
377 i, (trace_data >> 19) & 1, (trace_data >> 11) & 0xff, (trace_data >> 3) & 0xff, trace_data & 0x7, trace_data);
378 }
379
380 return ERROR_OK;
381 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)