1 /***************************************************************************
2 * Copyright (C) 2015 Paul Fertser <fercerpav@gmail.com> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
16 ***************************************************************************/
22 #include <target/target.h>
23 #include <target/armv7m.h>
24 #include <target/cortex_m.h>
25 #include <target/armv7m_trace.h>
26 #include <jtag/interface.h>
28 #define TRACE_BUF_SIZE 4096
30 static int armv7m_poll_trace(void *target
)
32 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
33 uint8_t buf
[TRACE_BUF_SIZE
];
34 size_t size
= sizeof(buf
);
37 retval
= adapter_poll_trace(buf
, &size
);
38 if (retval
!= ERROR_OK
|| !size
)
41 target_call_trace_callbacks(target
, size
, buf
);
43 if (armv7m
->trace_config
.trace_file
!= NULL
) {
44 if (fwrite(buf
, 1, size
, armv7m
->trace_config
.trace_file
) == size
)
45 fflush(armv7m
->trace_config
.trace_file
);
47 LOG_ERROR("Error writing to the trace destination file");
55 int armv7m_trace_tpiu_config(struct target
*target
)
57 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
58 struct armv7m_trace_config
*trace_config
= &armv7m
->trace_config
;
62 target_unregister_timer_callback(armv7m_poll_trace
, target
);
64 retval
= adapter_config_trace(trace_config
->config_type
== TRACE_CONFIG_TYPE_INTERNAL
,
65 trace_config
->pin_protocol
, trace_config
->port_size
,
66 &trace_config
->trace_freq
, trace_config
->traceclkin_freq
, &prescaler
);
68 if (retval
!= ERROR_OK
)
71 if (trace_config
->config_type
== TRACE_CONFIG_TYPE_EXTERNAL
) {
72 prescaler
= trace_config
->traceclkin_freq
/ trace_config
->trace_freq
;
74 if (trace_config
->traceclkin_freq
% trace_config
->trace_freq
) {
77 int trace_freq
= trace_config
->traceclkin_freq
/ prescaler
;
78 LOG_INFO("Can not obtain %u trace port frequency from %u "
79 "TRACECLKIN frequency, using %u instead",
80 trace_config
->trace_freq
, trace_config
->traceclkin_freq
,
83 trace_config
->trace_freq
= trace_freq
;
87 if (!trace_config
->trace_freq
) {
88 LOG_ERROR("Trace port frequency is 0, can't enable TPIU");
92 retval
= target_write_u32(target
, TPIU_CSPSR
, 1 << trace_config
->port_size
);
93 if (retval
!= ERROR_OK
)
96 retval
= target_write_u32(target
, TPIU_ACPR
, prescaler
- 1);
97 if (retval
!= ERROR_OK
)
100 retval
= target_write_u32(target
, TPIU_SPPR
, trace_config
->pin_protocol
);
101 if (retval
!= ERROR_OK
)
105 retval
= target_read_u32(target
, TPIU_FFCR
, &ffcr
);
106 if (retval
!= ERROR_OK
)
108 if (trace_config
->formatter
)
112 retval
= target_write_u32(target
, TPIU_FFCR
, ffcr
);
113 if (retval
!= ERROR_OK
)
116 if (trace_config
->config_type
== TRACE_CONFIG_TYPE_INTERNAL
)
117 target_register_timer_callback(armv7m_poll_trace
, 1,
118 TARGET_TIMER_TYPE_PERIODIC
, target
);
120 target_call_event_callbacks(target
, TARGET_EVENT_TRACE_CONFIG
);
125 int armv7m_trace_itm_config(struct target
*target
)
127 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
128 struct armv7m_trace_config
*trace_config
= &armv7m
->trace_config
;
131 retval
= target_write_u32(target
, ITM_LAR
, ITM_LAR_KEY
);
132 if (retval
!= ERROR_OK
)
135 /* Enable ITM, TXENA, set TraceBusID and other parameters */
136 retval
= target_write_u32(target
, ITM_TCR
, (1 << 0) | (1 << 3) |
137 (trace_config
->itm_diff_timestamps
<< 1) |
138 (trace_config
->itm_synchro_packets
<< 2) |
139 (trace_config
->itm_async_timestamps
<< 4) |
140 (trace_config
->itm_ts_prescale
<< 8) |
141 (trace_config
->trace_bus_id
<< 16));
142 if (retval
!= ERROR_OK
)
145 for (unsigned int i
= 0; i
< 8; i
++) {
146 retval
= target_write_u32(target
, ITM_TER0
+ i
* 4,
147 trace_config
->itm_ter
[i
]);
148 if (retval
!= ERROR_OK
)
155 static void close_trace_file(struct armv7m_common
*armv7m
)
157 if (armv7m
->trace_config
.trace_file
)
158 fclose(armv7m
->trace_config
.trace_file
);
159 armv7m
->trace_config
.trace_file
= NULL
;
162 COMMAND_HANDLER(handle_tpiu_config_command
)
164 struct target
*target
= get_current_target(CMD_CTX
);
165 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
167 unsigned int cmd_idx
= 0;
169 if (CMD_ARGC
== cmd_idx
)
170 return ERROR_COMMAND_SYNTAX_ERROR
;
171 if (!strcmp(CMD_ARGV
[cmd_idx
], "disable")) {
172 if (CMD_ARGC
== cmd_idx
+ 1) {
173 close_trace_file(armv7m
);
175 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_DISABLED
;
176 if (CMD_CTX
->mode
== COMMAND_EXEC
)
177 return armv7m_trace_tpiu_config(target
);
181 } else if (!strcmp(CMD_ARGV
[cmd_idx
], "external") ||
182 !strcmp(CMD_ARGV
[cmd_idx
], "internal")) {
183 close_trace_file(armv7m
);
185 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_EXTERNAL
;
186 if (!strcmp(CMD_ARGV
[cmd_idx
], "internal")) {
188 if (CMD_ARGC
== cmd_idx
)
189 return ERROR_COMMAND_SYNTAX_ERROR
;
191 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_INTERNAL
;
193 if (strcmp(CMD_ARGV
[cmd_idx
], "-") != 0) {
194 armv7m
->trace_config
.trace_file
= fopen(CMD_ARGV
[cmd_idx
], "ab");
195 if (!armv7m
->trace_config
.trace_file
) {
196 LOG_ERROR("Can't open trace destination file");
202 if (CMD_ARGC
== cmd_idx
)
203 return ERROR_COMMAND_SYNTAX_ERROR
;
205 if (!strcmp(CMD_ARGV
[cmd_idx
], "sync")) {
206 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_SYNC
;
209 if (CMD_ARGC
== cmd_idx
)
210 return ERROR_COMMAND_SYNTAX_ERROR
;
212 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.port_size
);
214 if (!strcmp(CMD_ARGV
[cmd_idx
], "manchester"))
215 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_ASYNC_MANCHESTER
;
216 else if (!strcmp(CMD_ARGV
[cmd_idx
], "uart"))
217 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_ASYNC_UART
;
219 return ERROR_COMMAND_SYNTAX_ERROR
;
222 if (CMD_ARGC
== cmd_idx
)
223 return ERROR_COMMAND_SYNTAX_ERROR
;
225 COMMAND_PARSE_ON_OFF(CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.formatter
);
229 if (CMD_ARGC
== cmd_idx
)
230 return ERROR_COMMAND_SYNTAX_ERROR
;
232 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.traceclkin_freq
);
235 if (CMD_ARGC
!= cmd_idx
) {
236 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.trace_freq
);
239 if (armv7m
->trace_config
.config_type
!= TRACE_CONFIG_TYPE_INTERNAL
) {
240 LOG_ERROR("Trace port frequency can't be omitted in external capture mode");
241 return ERROR_COMMAND_SYNTAX_ERROR
;
243 armv7m
->trace_config
.trace_freq
= 0;
246 if (CMD_ARGC
== cmd_idx
) {
247 if (CMD_CTX
->mode
== COMMAND_EXEC
)
248 return armv7m_trace_tpiu_config(target
);
254 return ERROR_COMMAND_SYNTAX_ERROR
;
257 COMMAND_HANDLER(handle_itm_port_command
)
259 struct target
*target
= get_current_target(CMD_CTX
);
260 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
261 unsigned int reg_idx
;
266 return ERROR_COMMAND_SYNTAX_ERROR
;
268 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0], port
);
269 COMMAND_PARSE_ON_OFF(CMD_ARGV
[1], enable
);
273 armv7m
->trace_config
.itm_ter
[reg_idx
] |= (1 << port
);
275 armv7m
->trace_config
.itm_ter
[reg_idx
] &= ~(1 << port
);
277 if (CMD_CTX
->mode
== COMMAND_EXEC
)
278 return armv7m_trace_itm_config(target
);
283 COMMAND_HANDLER(handle_itm_ports_command
)
285 struct target
*target
= get_current_target(CMD_CTX
);
286 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
290 return ERROR_COMMAND_SYNTAX_ERROR
;
292 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], enable
);
293 memset(armv7m
->trace_config
.itm_ter
, enable
? 0xff : 0,
294 sizeof(armv7m
->trace_config
.itm_ter
));
296 if (CMD_CTX
->mode
== COMMAND_EXEC
)
297 return armv7m_trace_itm_config(target
);
302 static const struct command_registration tpiu_command_handlers
[] = {
305 .handler
= handle_tpiu_config_command
,
307 .help
= "Configure TPIU features",
308 .usage
= "(disable | "
309 "((external | internal <filename>) "
310 "(sync <port width> | ((manchester | uart) <formatter enable>)) "
311 "<TRACECLKIN freq> [<trace freq>]))",
313 COMMAND_REGISTRATION_DONE
316 static const struct command_registration itm_command_handlers
[] = {
319 .handler
= handle_itm_port_command
,
321 .help
= "Enable or disable ITM stimulus port",
322 .usage
= "<port> (0|1|on|off)",
326 .handler
= handle_itm_ports_command
,
328 .help
= "Enable or disable all ITM stimulus ports",
329 .usage
= "(0|1|on|off)",
331 COMMAND_REGISTRATION_DONE
334 const struct command_registration armv7m_trace_command_handlers
[] = {
338 .help
= "tpiu command group",
340 .chain
= tpiu_command_handlers
,
345 .help
= "itm command group",
347 .chain
= itm_command_handlers
,
349 COMMAND_REGISTRATION_DONE
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)