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 switch (armv7m
->trace_config
.internal_channel
) {
44 case TRACE_INTERNAL_CHANNEL_FILE
:
45 if (armv7m
->trace_config
.trace_file
!= NULL
) {
46 if (fwrite(buf
, 1, size
, armv7m
->trace_config
.trace_file
) == size
)
47 fflush(armv7m
->trace_config
.trace_file
);
49 LOG_ERROR("Error writing to the trace destination file");
54 case TRACE_INTERNAL_CHANNEL_TCP
:
55 if (armv7m
->trace_config
.trace_service
!= NULL
) {
56 /* broadcast to all service connections */
57 struct connection
*connection
= armv7m
->trace_config
.trace_service
->connections
;
60 if (connection_write(connection
, buf
, size
) != (int) size
)
63 connection
= connection
->next
;
66 if (retval
!= ERROR_OK
) {
67 LOG_ERROR("Error streaming the trace to TCP/IP port");
72 case TRACE_INTERNAL_CHANNEL_TCL_ONLY
:
74 * the trace data is sent to TCL by calling the target_call_trace_callbacks
78 LOG_ERROR("unsupported trace internal channel");
85 int armv7m_trace_tpiu_config(struct target
*target
)
87 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
88 struct armv7m_trace_config
*trace_config
= &armv7m
->trace_config
;
92 target_unregister_timer_callback(armv7m_poll_trace
, target
);
94 retval
= adapter_config_trace(trace_config
->config_type
== TRACE_CONFIG_TYPE_INTERNAL
,
95 trace_config
->pin_protocol
, trace_config
->port_size
,
96 &trace_config
->trace_freq
, trace_config
->traceclkin_freq
, &prescaler
);
98 if (retval
!= ERROR_OK
)
101 if (trace_config
->config_type
== TRACE_CONFIG_TYPE_EXTERNAL
) {
102 prescaler
= trace_config
->traceclkin_freq
/ trace_config
->trace_freq
;
104 if (trace_config
->traceclkin_freq
% trace_config
->trace_freq
) {
107 int trace_freq
= trace_config
->traceclkin_freq
/ prescaler
;
108 LOG_INFO("Can not obtain %u trace port frequency from %u "
109 "TRACECLKIN frequency, using %u instead",
110 trace_config
->trace_freq
, trace_config
->traceclkin_freq
,
113 trace_config
->trace_freq
= trace_freq
;
117 if (!trace_config
->trace_freq
) {
118 LOG_ERROR("Trace port frequency is 0, can't enable TPIU");
122 retval
= target_write_u32(target
, TPIU_CSPSR
, 1 << trace_config
->port_size
);
123 if (retval
!= ERROR_OK
)
126 retval
= target_write_u32(target
, TPIU_ACPR
, prescaler
- 1);
127 if (retval
!= ERROR_OK
)
130 retval
= target_write_u32(target
, TPIU_SPPR
, trace_config
->pin_protocol
);
131 if (retval
!= ERROR_OK
)
135 retval
= target_read_u32(target
, TPIU_FFCR
, &ffcr
);
136 if (retval
!= ERROR_OK
)
138 if (trace_config
->formatter
)
142 retval
= target_write_u32(target
, TPIU_FFCR
, ffcr
);
143 if (retval
!= ERROR_OK
)
146 if (trace_config
->config_type
== TRACE_CONFIG_TYPE_INTERNAL
)
147 target_register_timer_callback(armv7m_poll_trace
, 1,
148 TARGET_TIMER_TYPE_PERIODIC
, target
);
150 target_call_event_callbacks(target
, TARGET_EVENT_TRACE_CONFIG
);
155 int armv7m_trace_itm_config(struct target
*target
)
157 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
158 struct armv7m_trace_config
*trace_config
= &armv7m
->trace_config
;
161 retval
= target_write_u32(target
, ITM_LAR
, ITM_LAR_KEY
);
162 if (retval
!= ERROR_OK
)
165 /* Enable ITM, TXENA, set TraceBusID and other parameters */
166 retval
= target_write_u32(target
, ITM_TCR
, (1 << 0) | (1 << 3) |
167 (trace_config
->itm_diff_timestamps
<< 1) |
168 (trace_config
->itm_synchro_packets
<< 2) |
169 (trace_config
->itm_async_timestamps
<< 4) |
170 (trace_config
->itm_ts_prescale
<< 8) |
171 (trace_config
->trace_bus_id
<< 16));
172 if (retval
!= ERROR_OK
)
175 for (unsigned int i
= 0; i
< 8; i
++) {
176 retval
= target_write_u32(target
, ITM_TER0
+ i
* 4,
177 trace_config
->itm_ter
[i
]);
178 if (retval
!= ERROR_OK
)
185 static void close_trace_channel(struct armv7m_common
*armv7m
)
187 switch (armv7m
->trace_config
.internal_channel
) {
188 case TRACE_INTERNAL_CHANNEL_FILE
:
189 if (armv7m
->trace_config
.trace_file
)
190 fclose(armv7m
->trace_config
.trace_file
);
191 armv7m
->trace_config
.trace_file
= NULL
;
193 case TRACE_INTERNAL_CHANNEL_TCP
:
194 if (armv7m
->trace_config
.trace_service
)
195 remove_service(armv7m
->trace_config
.trace_service
->name
, armv7m
->trace_config
.trace_service
->port
);
196 armv7m
->trace_config
.trace_service
= NULL
;
198 case TRACE_INTERNAL_CHANNEL_TCL_ONLY
:
200 * the trace polling is disabled in the beginning of armv7m_trace_tpiu_config
204 LOG_ERROR("unsupported trace internal channel");
208 static int trace_new_connection(struct connection
*connection
)
214 static int trace_input(struct connection
*connection
)
216 /* create a dummy buffer to check if the connection is still active */
217 const int buf_len
= 100;
218 unsigned char buf
[buf_len
];
219 int bytes_read
= connection_read(connection
, buf
, buf_len
);
222 return ERROR_SERVER_REMOTE_CLOSED
;
223 else if (bytes_read
== -1) {
224 LOG_ERROR("error during read: %s", strerror(errno
));
225 return ERROR_SERVER_REMOTE_CLOSED
;
231 static int trace_connection_closed(struct connection
*connection
)
233 /* nothing to do, no connection->priv to free */
237 COMMAND_HANDLER(handle_tpiu_config_command
)
239 struct target
*target
= get_current_target(CMD_CTX
);
240 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
242 unsigned int cmd_idx
= 0;
244 if (CMD_ARGC
== cmd_idx
)
245 return ERROR_COMMAND_SYNTAX_ERROR
;
246 if (!strcmp(CMD_ARGV
[cmd_idx
], "disable")) {
247 if (CMD_ARGC
== cmd_idx
+ 1) {
248 close_trace_channel(armv7m
);
250 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_DISABLED
;
251 if (CMD_CTX
->mode
== COMMAND_EXEC
)
252 return armv7m_trace_tpiu_config(target
);
256 } else if (!strcmp(CMD_ARGV
[cmd_idx
], "external") ||
257 !strcmp(CMD_ARGV
[cmd_idx
], "internal")) {
258 close_trace_channel(armv7m
);
260 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_EXTERNAL
;
261 if (!strcmp(CMD_ARGV
[cmd_idx
], "internal")) {
263 if (CMD_ARGC
== cmd_idx
)
264 return ERROR_COMMAND_SYNTAX_ERROR
;
266 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_INTERNAL
;
267 armv7m
->trace_config
.internal_channel
= TRACE_INTERNAL_CHANNEL_TCL_ONLY
;
269 if (strcmp(CMD_ARGV
[cmd_idx
], "-") != 0) {
270 if (CMD_ARGV
[cmd_idx
][0] == ':') {
271 armv7m
->trace_config
.internal_channel
= TRACE_INTERNAL_CHANNEL_TCP
;
273 int ret
= add_service("armv7m_trace", &(CMD_ARGV
[cmd_idx
][1]),
274 CONNECTION_LIMIT_UNLIMITED
, trace_new_connection
, trace_input
,
275 trace_connection_closed
, NULL
, &armv7m
->trace_config
.trace_service
);
276 if (ret
!= ERROR_OK
) {
277 LOG_ERROR("Can't configure trace TCP port");
281 armv7m
->trace_config
.internal_channel
= TRACE_INTERNAL_CHANNEL_FILE
;
282 armv7m
->trace_config
.trace_file
= fopen(CMD_ARGV
[cmd_idx
], "ab");
283 if (!armv7m
->trace_config
.trace_file
) {
284 LOG_ERROR("Can't open trace destination file");
291 if (CMD_ARGC
== cmd_idx
)
292 return ERROR_COMMAND_SYNTAX_ERROR
;
294 if (!strcmp(CMD_ARGV
[cmd_idx
], "sync")) {
295 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_SYNC
;
298 if (CMD_ARGC
== cmd_idx
)
299 return ERROR_COMMAND_SYNTAX_ERROR
;
301 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.port_size
);
303 if (!strcmp(CMD_ARGV
[cmd_idx
], "manchester"))
304 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_ASYNC_MANCHESTER
;
305 else if (!strcmp(CMD_ARGV
[cmd_idx
], "uart"))
306 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_ASYNC_UART
;
308 return ERROR_COMMAND_SYNTAX_ERROR
;
311 if (CMD_ARGC
== cmd_idx
)
312 return ERROR_COMMAND_SYNTAX_ERROR
;
314 COMMAND_PARSE_ON_OFF(CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.formatter
);
318 if (CMD_ARGC
== cmd_idx
)
319 return ERROR_COMMAND_SYNTAX_ERROR
;
321 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.traceclkin_freq
);
324 if (CMD_ARGC
!= cmd_idx
) {
325 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.trace_freq
);
328 if (armv7m
->trace_config
.config_type
!= TRACE_CONFIG_TYPE_INTERNAL
) {
329 LOG_ERROR("Trace port frequency can't be omitted in external capture mode");
330 return ERROR_COMMAND_SYNTAX_ERROR
;
332 armv7m
->trace_config
.trace_freq
= 0;
335 if (CMD_ARGC
== cmd_idx
) {
336 if (CMD_CTX
->mode
== COMMAND_EXEC
)
337 return armv7m_trace_tpiu_config(target
);
343 return ERROR_COMMAND_SYNTAX_ERROR
;
346 COMMAND_HANDLER(handle_itm_port_command
)
348 struct target
*target
= get_current_target(CMD_CTX
);
349 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
350 unsigned int reg_idx
;
355 return ERROR_COMMAND_SYNTAX_ERROR
;
357 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0], port
);
358 COMMAND_PARSE_ON_OFF(CMD_ARGV
[1], enable
);
362 armv7m
->trace_config
.itm_ter
[reg_idx
] |= (1 << port
);
364 armv7m
->trace_config
.itm_ter
[reg_idx
] &= ~(1 << port
);
366 if (CMD_CTX
->mode
== COMMAND_EXEC
)
367 return armv7m_trace_itm_config(target
);
372 COMMAND_HANDLER(handle_itm_ports_command
)
374 struct target
*target
= get_current_target(CMD_CTX
);
375 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
379 return ERROR_COMMAND_SYNTAX_ERROR
;
381 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], enable
);
382 memset(armv7m
->trace_config
.itm_ter
, enable
? 0xff : 0,
383 sizeof(armv7m
->trace_config
.itm_ter
));
385 if (CMD_CTX
->mode
== COMMAND_EXEC
)
386 return armv7m_trace_itm_config(target
);
391 static const struct command_registration tpiu_command_handlers
[] = {
394 .handler
= handle_tpiu_config_command
,
396 .help
= "Configure TPIU features",
397 .usage
= "(disable | "
398 "((external | internal (<filename> | <:port> | -)) "
399 "(sync <port width> | ((manchester | uart) <formatter enable>)) "
400 "<TRACECLKIN freq> [<trace freq>]))",
402 COMMAND_REGISTRATION_DONE
405 static const struct command_registration itm_command_handlers
[] = {
408 .handler
= handle_itm_port_command
,
410 .help
= "Enable or disable ITM stimulus port",
411 .usage
= "<port> (0|1|on|off)",
415 .handler
= handle_itm_ports_command
,
417 .help
= "Enable or disable all ITM stimulus ports",
418 .usage
= "(0|1|on|off)",
420 COMMAND_REGISTRATION_DONE
423 const struct command_registration armv7m_trace_command_handlers
[] = {
427 .help
= "tpiu command group",
429 .chain
= tpiu_command_handlers
,
434 .help
= "itm command group",
436 .chain
= itm_command_handlers
,
438 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)