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
);
65 retval
= adapter_config_trace(trace_config
->config_type
== TRACE_CONFIG_TYPE_INTERNAL
,
66 trace_config
->pin_protocol
,
67 trace_config
->port_size
,
68 &trace_config
->trace_freq
);
69 if (retval
!= ERROR_OK
)
72 if (!trace_config
->trace_freq
) {
73 LOG_ERROR("Trace port frequency is 0, can't enable TPIU");
77 prescaler
= trace_config
->traceclkin_freq
/ trace_config
->trace_freq
;
79 if (trace_config
->traceclkin_freq
% trace_config
->trace_freq
) {
81 int trace_freq
= trace_config
->traceclkin_freq
/ prescaler
;
82 LOG_INFO("Can not obtain %u trace port frequency from %u TRACECLKIN frequency, using %u instead",
83 trace_config
->trace_freq
, trace_config
->traceclkin_freq
,
85 trace_config
->trace_freq
= trace_freq
;
86 retval
= adapter_config_trace(trace_config
->config_type
== TRACE_CONFIG_TYPE_INTERNAL
,
87 trace_config
->pin_protocol
,
88 trace_config
->port_size
,
89 &trace_config
->trace_freq
);
90 if (retval
!= ERROR_OK
)
94 retval
= target_write_u32(target
, TPIU_CSPSR
, 1 << trace_config
->port_size
);
95 if (retval
!= ERROR_OK
)
98 retval
= target_write_u32(target
, TPIU_ACPR
, prescaler
- 1);
99 if (retval
!= ERROR_OK
)
102 retval
= target_write_u32(target
, TPIU_SPPR
, trace_config
->pin_protocol
);
103 if (retval
!= ERROR_OK
)
107 retval
= target_read_u32(target
, TPIU_FFCR
, &ffcr
);
108 if (retval
!= ERROR_OK
)
110 if (trace_config
->formatter
)
114 retval
= target_write_u32(target
, TPIU_FFCR
, ffcr
);
115 if (retval
!= ERROR_OK
)
118 if (trace_config
->config_type
== TRACE_CONFIG_TYPE_INTERNAL
)
119 target_register_timer_callback(armv7m_poll_trace
, 1, 1, target
);
121 target_call_event_callbacks(target
, TARGET_EVENT_TRACE_CONFIG
);
126 int armv7m_trace_itm_config(struct target
*target
)
128 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
129 struct armv7m_trace_config
*trace_config
= &armv7m
->trace_config
;
132 retval
= target_write_u32(target
, ITM_LAR
, ITM_LAR_KEY
);
133 if (retval
!= ERROR_OK
)
136 /* Enable ITM, TXENA, set TraceBusID and other parameters */
137 retval
= target_write_u32(target
, ITM_TCR
, (1 << 0) | (1 << 3) |
138 (trace_config
->itm_diff_timestamps
<< 1) |
139 (trace_config
->itm_synchro_packets
<< 2) |
140 (trace_config
->itm_async_timestamps
<< 4) |
141 (trace_config
->itm_ts_prescale
<< 8) |
142 (trace_config
->trace_bus_id
<< 16));
143 if (retval
!= ERROR_OK
)
146 for (unsigned int i
= 0; i
< 8; i
++) {
147 retval
= target_write_u32(target
, ITM_TER0
+ i
* 4,
148 trace_config
->itm_ter
[i
]);
149 if (retval
!= ERROR_OK
)
156 static void close_trace_file(struct armv7m_common
*armv7m
)
158 if (armv7m
->trace_config
.trace_file
)
159 fclose(armv7m
->trace_config
.trace_file
);
160 armv7m
->trace_config
.trace_file
= NULL
;
163 COMMAND_HANDLER(handle_tpiu_config_command
)
165 struct target
*target
= get_current_target(CMD_CTX
);
166 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
168 unsigned int cmd_idx
= 0;
170 if (CMD_ARGC
== cmd_idx
)
171 return ERROR_COMMAND_SYNTAX_ERROR
;
172 if (!strcmp(CMD_ARGV
[cmd_idx
], "disable")) {
173 if (CMD_ARGC
== cmd_idx
+ 1) {
174 close_trace_file(armv7m
);
176 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_DISABLED
;
177 if (CMD_CTX
->mode
== COMMAND_EXEC
)
178 return armv7m_trace_tpiu_config(target
);
182 } else if (!strcmp(CMD_ARGV
[cmd_idx
], "external") ||
183 !strcmp(CMD_ARGV
[cmd_idx
], "internal")) {
184 close_trace_file(armv7m
);
186 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_EXTERNAL
;
187 if (!strcmp(CMD_ARGV
[cmd_idx
], "internal")) {
189 if (CMD_ARGC
== cmd_idx
)
190 return ERROR_COMMAND_SYNTAX_ERROR
;
192 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_INTERNAL
;
194 if (strcmp(CMD_ARGV
[cmd_idx
], "-") != 0) {
195 armv7m
->trace_config
.trace_file
= fopen(CMD_ARGV
[cmd_idx
], "ab");
196 if (!armv7m
->trace_config
.trace_file
) {
197 LOG_ERROR("Can't open trace destination file");
203 if (CMD_ARGC
== cmd_idx
)
204 return ERROR_COMMAND_SYNTAX_ERROR
;
206 if (!strcmp(CMD_ARGV
[cmd_idx
], "sync")) {
207 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_SYNC
;
210 if (CMD_ARGC
== cmd_idx
)
211 return ERROR_COMMAND_SYNTAX_ERROR
;
213 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.port_size
);
215 if (!strcmp(CMD_ARGV
[cmd_idx
], "manchester"))
216 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_ASYNC_MANCHESTER
;
217 else if (!strcmp(CMD_ARGV
[cmd_idx
], "uart"))
218 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_ASYNC_UART
;
220 return ERROR_COMMAND_SYNTAX_ERROR
;
223 if (CMD_ARGC
== cmd_idx
)
224 return ERROR_COMMAND_SYNTAX_ERROR
;
226 COMMAND_PARSE_ON_OFF(CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.formatter
);
230 if (CMD_ARGC
== cmd_idx
)
231 return ERROR_COMMAND_SYNTAX_ERROR
;
233 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.traceclkin_freq
);
236 if (CMD_ARGC
!= cmd_idx
) {
237 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.trace_freq
);
240 if (armv7m
->trace_config
.config_type
!= TRACE_CONFIG_TYPE_INTERNAL
) {
241 LOG_ERROR("Trace port frequency can't be omitted in external capture mode");
242 return ERROR_COMMAND_SYNTAX_ERROR
;
244 armv7m
->trace_config
.trace_freq
= 0;
247 if (CMD_ARGC
== cmd_idx
) {
248 if (CMD_CTX
->mode
== COMMAND_EXEC
)
249 return armv7m_trace_tpiu_config(target
);
255 return ERROR_COMMAND_SYNTAX_ERROR
;
258 COMMAND_HANDLER(handle_itm_port_command
)
260 struct target
*target
= get_current_target(CMD_CTX
);
261 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
262 unsigned int reg_idx
;
267 return ERROR_COMMAND_SYNTAX_ERROR
;
269 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0], port
);
270 COMMAND_PARSE_ON_OFF(CMD_ARGV
[1], enable
);
274 armv7m
->trace_config
.itm_ter
[reg_idx
] |= (1 << port
);
276 armv7m
->trace_config
.itm_ter
[reg_idx
] &= ~(1 << port
);
278 if (CMD_CTX
->mode
== COMMAND_EXEC
)
279 return armv7m_trace_itm_config(target
);
284 COMMAND_HANDLER(handle_itm_ports_command
)
286 struct target
*target
= get_current_target(CMD_CTX
);
287 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
291 return ERROR_COMMAND_SYNTAX_ERROR
;
293 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], enable
);
294 memset(armv7m
->trace_config
.itm_ter
, enable
? 0xff : 0,
295 sizeof(armv7m
->trace_config
.itm_ter
));
297 if (CMD_CTX
->mode
== COMMAND_EXEC
)
298 return armv7m_trace_itm_config(target
);
303 static const struct command_registration tpiu_command_handlers
[] = {
306 .handler
= handle_tpiu_config_command
,
308 .help
= "Configure TPIU features",
309 .usage
= "(disable | "
310 "((external | internal <filename>) "
311 "(sync <port width> | ((manchester | uart) <formatter enable>)) "
312 "<TRACECLKIN freq> [<trace freq>]))",
314 COMMAND_REGISTRATION_DONE
317 static const struct command_registration itm_command_handlers
[] = {
320 .handler
= handle_itm_port_command
,
322 .help
= "Enable or disable ITM stimulus port",
323 .usage
= "<port> (0|1|on|off)",
327 .handler
= handle_itm_ports_command
,
329 .help
= "Enable or disable all ITM stimulus ports",
330 .usage
= "(0|1|on|off)",
332 COMMAND_REGISTRATION_DONE
335 const struct command_registration armv7m_trace_command_handlers
[] = {
339 .help
= "tpiu command group",
341 .chain
= tpiu_command_handlers
,
346 .help
= "itm command group",
348 .chain
= itm_command_handlers
,
350 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)