1 /***************************************************************************
2 * Copyright (C) 2007 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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. *
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. *
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 ***************************************************************************/
24 #include "arm7_9_common.h"
29 #include "binarybuffer.h"
36 char* etb_reg_list
[] =
43 "ETB_ram_read_pointer",
44 "ETB_ram_write_pointer",
45 "ETB_trigger_counter",
49 int etb_reg_arch_type
= -1;
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
);
55 int etb_write_reg(reg_t
*reg
, u32 value
);
56 int etb_read_reg(reg_t
*reg
);
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
);
61 char *etmv1_branch_reason_string
[] =
63 "normal pc change", "tracing enabled", "restart after FIFO overflow",
64 "exit from debug state", "peridoic synchronization point",
65 "reserved", "reserved", "reserved"
69 int etb_set_instr(etb_t
*etb
, u32 new_instr
)
71 jtag_device_t
*device
= jtag_get_device(etb
->chain_pos
);
73 if (buf_get_u32(device
->cur_instr
, 0, device
->ir_length
) != new_instr
)
77 field
.device
= etb
->chain_pos
;
78 field
.num_bits
= device
->ir_length
;
79 field
.out_value
= calloc(CEIL(field
.num_bits
, 8), 1);
80 buf_set_u32(field
.out_value
, 0, field
.num_bits
, new_instr
);
81 field
.out_mask
= NULL
;
82 field
.in_value
= NULL
;
83 field
.in_check_value
= NULL
;
84 field
.in_check_mask
= NULL
;
85 field
.in_handler
= NULL
;
86 field
.in_handler_priv
= NULL
;
88 jtag_add_ir_scan(1, &field
, -1, NULL
);
90 free(field
.out_value
);
96 int etb_scann(etb_t
*etb
, u32 new_scan_chain
)
98 if(etb
->cur_scan_chain
!= new_scan_chain
)
102 field
.device
= etb
->chain_pos
;
104 field
.out_value
= calloc(CEIL(field
.num_bits
, 8), 1);
105 buf_set_u32(field
.out_value
, 0, field
.num_bits
, new_scan_chain
);
106 field
.out_mask
= NULL
;
107 field
.in_value
= NULL
;
108 field
.in_check_value
= NULL
;
109 field
.in_check_mask
= NULL
;
110 field
.in_handler
= NULL
;
111 field
.in_handler_priv
= NULL
;
113 /* select INTEST instruction */
114 etb_set_instr(etb
, 0x2);
115 jtag_add_dr_scan(1, &field
, -1, NULL
);
117 etb
->cur_scan_chain
= new_scan_chain
;
119 free(field
.out_value
);
125 reg_cache_t
* etb_build_reg_cache(etb_t
*etb
)
127 reg_cache_t
*reg_cache
= malloc(sizeof(reg_cache_t
));
128 reg_t
*reg_list
= NULL
;
129 etb_reg_t
*arch_info
= NULL
;
133 /* register a register arch-type for etm registers only once */
134 if (etb_reg_arch_type
== -1)
135 etb_reg_arch_type
= register_reg_arch_type(etb_get_reg
, etb_set_reg_w_exec
);
137 /* the actual registers are kept in two arrays */
138 reg_list
= calloc(num_regs
, sizeof(reg_t
));
139 arch_info
= calloc(num_regs
, sizeof(etb_reg_t
));
141 /* fill in values for the reg cache */
142 reg_cache
->name
= "etb registers";
143 reg_cache
->next
= NULL
;
144 reg_cache
->reg_list
= reg_list
;
145 reg_cache
->num_regs
= num_regs
;
147 /* set up registers */
148 for (i
= 0; i
< num_regs
; i
++)
150 reg_list
[i
].name
= etb_reg_list
[i
];
151 reg_list
[i
].size
= 32;
152 reg_list
[i
].dirty
= 0;
153 reg_list
[i
].valid
= 0;
154 reg_list
[i
].bitfield_desc
= NULL
;
155 reg_list
[i
].num_bitfields
= 0;
156 reg_list
[i
].value
= calloc(1, 4);
157 reg_list
[i
].arch_info
= &arch_info
[i
];
158 reg_list
[i
].arch_type
= etb_reg_arch_type
;
159 reg_list
[i
].size
= 32;
160 arch_info
[i
].addr
= i
;
161 arch_info
[i
].etb
= etb
;
167 int etb_get_reg(reg_t
*reg
)
169 if (etb_read_reg(reg
) != ERROR_OK
)
171 ERROR("BUG: error scheduling etm register read");
175 if (jtag_execute_queue() != ERROR_OK
)
177 ERROR("register read failed");
183 int etb_read_reg_w_check(reg_t
*reg
, u8
* check_value
, u8
* check_mask
)
185 etb_reg_t
*etb_reg
= reg
->arch_info
;
186 u8 reg_addr
= etb_reg
->addr
& 0x7f;
187 scan_field_t fields
[3];
189 DEBUG("%i", etb_reg
->addr
);
191 jtag_add_end_state(TAP_RTI
);
192 etb_scann(etb_reg
->etb
, 0x0);
193 etb_set_instr(etb_reg
->etb
, 0xc);
195 fields
[0].device
= etb_reg
->etb
->chain_pos
;
196 fields
[0].num_bits
= 32;
197 fields
[0].out_value
= reg
->value
;
198 fields
[0].out_mask
= NULL
;
199 fields
[0].in_value
= NULL
;
200 fields
[0].in_check_value
= NULL
;
201 fields
[0].in_check_mask
= NULL
;
202 fields
[0].in_handler
= NULL
;
203 fields
[0].in_handler_priv
= NULL
;
205 fields
[1].device
= etb_reg
->etb
->chain_pos
;
206 fields
[1].num_bits
= 7;
207 fields
[1].out_value
= malloc(1);
208 buf_set_u32(fields
[1].out_value
, 0, 7, reg_addr
);
209 fields
[1].out_mask
= NULL
;
210 fields
[1].in_value
= NULL
;
211 fields
[1].in_check_value
= NULL
;
212 fields
[1].in_check_mask
= NULL
;
213 fields
[1].in_handler
= NULL
;
214 fields
[1].in_handler_priv
= NULL
;
216 fields
[2].device
= etb_reg
->etb
->chain_pos
;
217 fields
[2].num_bits
= 1;
218 fields
[2].out_value
= malloc(1);
219 buf_set_u32(fields
[2].out_value
, 0, 1, 0);
220 fields
[2].out_mask
= NULL
;
221 fields
[2].in_value
= NULL
;
222 fields
[2].in_check_value
= NULL
;
223 fields
[2].in_check_mask
= NULL
;
224 fields
[2].in_handler
= NULL
;
225 fields
[2].in_handler_priv
= NULL
;
227 jtag_add_dr_scan(3, fields
, -1, NULL
);
229 /* read the identification register in the second run, to make sure we
230 * don't read the ETB data register twice, skipping every second entry
232 buf_set_u32(fields
[1].out_value
, 0, 7, 0x0);
233 fields
[0].in_value
= reg
->value
;
234 fields
[0].in_check_value
= check_value
;
235 fields
[0].in_check_mask
= check_mask
;
237 jtag_add_dr_scan(3, fields
, -1, NULL
);
239 free(fields
[1].out_value
);
240 free(fields
[2].out_value
);
245 int etb_read_reg(reg_t
*reg
)
247 return etb_read_reg_w_check(reg
, NULL
, NULL
);
250 int etb_set_reg(reg_t
*reg
, u32 value
)
252 if (etb_write_reg(reg
, value
) != ERROR_OK
)
254 ERROR("BUG: error scheduling etm register write");
258 buf_set_u32(reg
->value
, 0, reg
->size
, value
);
265 int etb_set_reg_w_exec(reg_t
*reg
, u8
*buf
)
267 etb_set_reg(reg
, buf_get_u32(buf
, 0, reg
->size
));
269 if (jtag_execute_queue() != ERROR_OK
)
271 ERROR("register write failed");
277 int etb_write_reg(reg_t
*reg
, u32 value
)
279 etb_reg_t
*etb_reg
= reg
->arch_info
;
280 u8 reg_addr
= etb_reg
->addr
& 0x7f;
281 scan_field_t fields
[3];
283 DEBUG("%i: 0x%8.8x", etb_reg
->addr
, value
);
285 jtag_add_end_state(TAP_RTI
);
286 etb_scann(etb_reg
->etb
, 0x0);
287 etb_set_instr(etb_reg
->etb
, 0xc);
289 fields
[0].device
= etb_reg
->etb
->chain_pos
;
290 fields
[0].num_bits
= 32;
291 fields
[0].out_value
= malloc(4);
292 buf_set_u32(fields
[0].out_value
, 0, 32, value
);
293 fields
[0].out_mask
= NULL
;
294 fields
[0].in_value
= NULL
;
295 fields
[0].in_check_value
= NULL
;
296 fields
[0].in_check_mask
= NULL
;
297 fields
[0].in_handler
= NULL
;
298 fields
[0].in_handler_priv
= NULL
;
300 fields
[1].device
= etb_reg
->etb
->chain_pos
;
301 fields
[1].num_bits
= 7;
302 fields
[1].out_value
= malloc(1);
303 buf_set_u32(fields
[1].out_value
, 0, 7, reg_addr
);
304 fields
[1].out_mask
= NULL
;
305 fields
[1].in_value
= NULL
;
306 fields
[1].in_check_value
= NULL
;
307 fields
[1].in_check_mask
= NULL
;
308 fields
[1].in_handler
= NULL
;
309 fields
[1].in_handler_priv
= NULL
;
311 fields
[2].device
= etb_reg
->etb
->chain_pos
;
312 fields
[2].num_bits
= 1;
313 fields
[2].out_value
= malloc(1);
314 buf_set_u32(fields
[2].out_value
, 0, 1, 1);
315 fields
[2].out_mask
= NULL
;
316 fields
[2].in_value
= NULL
;
317 fields
[2].in_check_value
= NULL
;
318 fields
[2].in_check_mask
= NULL
;
319 fields
[2].in_handler
= NULL
;
320 fields
[2].in_handler_priv
= NULL
;
322 jtag_add_dr_scan(3, fields
, -1, NULL
);
324 free(fields
[0].out_value
);
325 free(fields
[1].out_value
);
326 free(fields
[2].out_value
);
331 int etb_store_reg(reg_t
*reg
)
333 return etb_write_reg(reg
, buf_get_u32(reg
->value
, 0, reg
->size
));
336 int etb_register_commands(struct command_context_s
*cmd_ctx
, command_t
*arm7_9_cmd
)
338 register_command(cmd_ctx
, arm7_9_cmd
, "etb", handle_arm7_9_etb_command
, COMMAND_CONFIG
, NULL
);
340 register_command(cmd_ctx
, arm7_9_cmd
, "etb_dump", handle_arm7_9_etb_dump_command
, COMMAND_EXEC
, "dump current ETB content");
345 #define PIPESTAT(x) ((x) & 0x7)
346 #define TRACEPKT(x) (((x) & 0x7fff8) >> 3)
347 #define TRACESYNC(x) (((x) & 0x80000) >> 19)
349 int etmv1_next_packet(int trace_depth
, u32
*trace_data
, int frame
, int *port_half
, int apo
, u8
*packet
)
351 while (frame
< trace_depth
)
355 if (TRACESYNC(trace_data
[frame
]))
360 /* we're looking for a branch address, skip if TRACESYNC isn't set */
361 if ((apo
== 0) && (!TRACESYNC(trace_data
[frame
])))
367 /* TRACEPKT is valid if this isn't a TD nor a TRIGGER cycle */
368 if (((PIPESTAT(trace_data
[frame
]) != 0x7) && (PIPESTAT(trace_data
[frame
]) != 0x6))
369 && !((apo
== 0) && (!TRACESYNC(trace_data
[frame
]))))
373 *packet
= TRACEPKT(trace_data
[frame
]) & 0xff;
378 *packet
= (TRACEPKT(trace_data
[frame
]) & 0xff00) >> 8;
388 /* we reached the end of the trace without finding the packet we're looking for
389 * tracing is finished
394 int handle_arm7_9_etb_dump_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
397 target_t
*target
= get_current_target(cmd_ctx
);
398 armv4_5_common_t
*armv4_5
;
399 arm7_9_common_t
*arm7_9
;
403 int addressbits_valid
= 0;
407 int last_instruction
= -1;
410 char trace_output
[256];
411 int trace_output_len
;
414 if (arm7_9_get_arch_pointers(target
, &armv4_5
, &arm7_9
) != ERROR_OK
)
416 command_print(cmd_ctx
, "current target isn't an ARM7/ARM9 target");
422 command_print(cmd_ctx
, "no ETB configured for current target");
426 if (!(arm7_9
->etb
->RAM_depth
&& arm7_9
->etb
->RAM_width
))
428 /* identify ETB RAM depth and width */
429 etb_read_reg(&arm7_9
->etb
->reg_cache
->reg_list
[ETB_RAM_DEPTH
]);
430 etb_read_reg(&arm7_9
->etb
->reg_cache
->reg_list
[ETB_RAM_WIDTH
]);
431 jtag_execute_queue();
433 arm7_9
->etb
->RAM_depth
= buf_get_u32(arm7_9
->etb
->reg_cache
->reg_list
[ETB_RAM_DEPTH
].value
, 0, 32);
434 arm7_9
->etb
->RAM_width
= buf_get_u32(arm7_9
->etb
->reg_cache
->reg_list
[ETB_RAM_WIDTH
].value
, 0, 32);
437 trace_data
= malloc(sizeof(u32
) * arm7_9
->etb
->RAM_depth
);
439 etb_read_reg(&arm7_9
->etb
->reg_cache
->reg_list
[ETB_STATUS
]);
440 etb_read_reg(&arm7_9
->etb
->reg_cache
->reg_list
[ETB_RAM_WRITE_POINTER
]);
441 jtag_execute_queue();
443 /* check if we overflowed, and adjust first and last frame of the trace accordingly */
444 if (buf_get_u32(arm7_9
->etb
->reg_cache
->reg_list
[ETB_STATUS
].value
, 1, 1))
446 first_frame
= buf_get_u32(arm7_9
->etb
->reg_cache
->reg_list
[ETB_RAM_WRITE_POINTER
].value
, 0, 32);
449 last_frame
= buf_get_u32(arm7_9
->etb
->reg_cache
->reg_list
[ETB_RAM_WRITE_POINTER
].value
, 0, 32) - 1;
451 etb_write_reg(&arm7_9
->etb
->reg_cache
->reg_list
[ETB_RAM_READ_POINTER
], first_frame
);
453 /* read trace data from ETB */
457 etb_read_reg(&arm7_9
->etb
->reg_cache
->reg_list
[ETB_RAM_DATA
]);
458 jtag_execute_queue();
459 trace_data
[j
++] = buf_get_u32(arm7_9
->etb
->reg_cache
->reg_list
[ETB_RAM_DATA
].value
, 0, 32);
461 } while ((i
% arm7_9
->etb
->RAM_depth
) != (first_frame
% arm7_9
->etb
->RAM_depth
));
463 for (i
= 0, j
= 0; i
< arm7_9
->etb
->RAM_depth
; i
++)
467 trace_output_len
= 0;
469 /* catch trigger, actual PIPESTAT is encoded in TRACEPKT[2:0] */
470 if (PIPESTAT(trace_data
[i
]) == 0x6)
473 trace_data
[i
] &= ~0x7;
474 trace_data
[i
] |= TRACEPKT(trace_data
[i
]) & 0x7;
477 if (addressbits_valid
== 32)
479 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
480 "%i: 0x%8.8x %s", i
, address
, (trigger
) ? "(TRIGGER) " : "");
482 else if (addressbits_valid
!= 0)
484 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
485 "%i: 0x...%x %s", i
, address
, (trigger
) ? "(TRIGGER) " : "");
489 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
490 "%i: 0xUNK %s", i
, (trigger
) ? "(TRIGGER) " : "");
493 switch (PIPESTAT(trace_data
[i
]))
496 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
500 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
504 /* Instruction exectued - TRACEPKT might be valid, but belongs to another cycle */
505 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
509 /* WAIT cycle - TRACEPKT is valid, but belongs to another cycle */
510 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
514 /* following a branch two APO cycles are output on PIPESTAT[1:0]
515 * but another BE/BD could overwrite the current branch,
516 * or a trigger could cause the APO to be output on TRACEPKT[1:0]
518 if ((PIPESTAT(trace_data
[i
+ 1]) == 0x4)
519 || (PIPESTAT(trace_data
[i
+ 1]) == 0x5))
521 /* another branch occured, we ignore this one */
522 j
= (j
< i
+ 1) ? i
+ 1 : j
;
525 else if (PIPESTAT(trace_data
[i
+ 1]) == 0x6)
527 apo
= TRACEPKT(trace_data
[i
+ 1]) & 0x3;
531 apo
= PIPESTAT(trace_data
[i
+ 1]) & 0x3;
534 if ((PIPESTAT(trace_data
[i
+ 2]) == 0x4)
535 || (PIPESTAT(trace_data
[i
+ 2]) == 0x5))
537 j
= (j
< i
+ 2) ? i
+ 1 : j
;
541 else if (PIPESTAT(trace_data
[i
+ 2]) == 0x6)
543 apo
|= (TRACEPKT(trace_data
[i
+ 2]) & 0x3) << 2;
547 apo
= (PIPESTAT(trace_data
[i
+ 1]) & 0x3) << 2;
554 if ((j
= etmv1_next_packet(arm7_9
->etb
->RAM_depth
, trace_data
, j
, &port_half
, apo
, &packet
)) != -1)
556 address
&= ~(0x7f << (k
* 7));
557 address
|= (packet
& 0x7f) << (k
* 7);
564 } while ((k
< 5) && (packet
& 0x80));
566 if (addressbits_valid
< ((k
* 7 > 32) ? 32 : k
* 7))
567 addressbits_valid
= (k
* 7 > 32) ? 32 : k
* 7;
571 branch_reason
= (packet
& 0x7) >> 4;
572 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
573 "BE 0x%x (/%i) (%s)", address
, addressbits_valid
, etmv1_branch_reason_string
[branch_reason
]);
577 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
578 "BE 0x%x (/%i)", address
, addressbits_valid
);
583 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
587 /* We catch the trigger event before we get here */
588 ERROR("TR pipestat should have been caught earlier");
589 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
593 /* TRACE disabled - TRACEPKT = invalid */
594 trace_output_len
+= snprintf(trace_output
+ trace_output_len
, 256 - trace_output_len
,
599 /* PIPESTAT other than WT (b011) and TD (b111) mean we executed an instruction */
600 if ((PIPESTAT(trace_data
[i
]) & 0x3) != 0x3)
602 last_instruction
= i
;
606 /* The group of packets for a particular instruction cannot start on or before any
607 * previous functional PIPESTAT (IE, IN, ID, BE, or BD)
609 if (j
< last_instruction
)
611 j
= last_instruction
+ 1;
614 /* restore trigger PIPESTAT to ensure TRACEPKT is ignored */
617 trace_data
[i
] &= ~0x7;
618 trace_data
[i
] |= 0x6;
621 command_print(cmd_ctx
, "%s (raw: 0x%8.8x)", trace_output
, trace_data
[i
]);
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)