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
->trace_freq
) {
72 LOG_ERROR("Trace port frequency is 0, can't enable TPIU");
76 retval
= target_write_u32(target
, TPIU_CSPSR
, 1 << trace_config
->port_size
);
77 if (retval
!= ERROR_OK
)
80 retval
= target_write_u32(target
, TPIU_ACPR
, prescaler
- 1);
81 if (retval
!= ERROR_OK
)
84 retval
= target_write_u32(target
, TPIU_SPPR
, trace_config
->pin_protocol
);
85 if (retval
!= ERROR_OK
)
89 retval
= target_read_u32(target
, TPIU_FFCR
, &ffcr
);
90 if (retval
!= ERROR_OK
)
92 if (trace_config
->formatter
)
96 retval
= target_write_u32(target
, TPIU_FFCR
, ffcr
);
97 if (retval
!= ERROR_OK
)
100 if (trace_config
->config_type
== TRACE_CONFIG_TYPE_INTERNAL
)
101 target_register_timer_callback(armv7m_poll_trace
, 1,
102 TARGET_TIMER_TYPE_PERIODIC
, target
);
104 target_call_event_callbacks(target
, TARGET_EVENT_TRACE_CONFIG
);
109 int armv7m_trace_itm_config(struct target
*target
)
111 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
112 struct armv7m_trace_config
*trace_config
= &armv7m
->trace_config
;
115 retval
= target_write_u32(target
, ITM_LAR
, ITM_LAR_KEY
);
116 if (retval
!= ERROR_OK
)
119 /* Enable ITM, TXENA, set TraceBusID and other parameters */
120 retval
= target_write_u32(target
, ITM_TCR
, (1 << 0) | (1 << 3) |
121 (trace_config
->itm_diff_timestamps
<< 1) |
122 (trace_config
->itm_synchro_packets
<< 2) |
123 (trace_config
->itm_async_timestamps
<< 4) |
124 (trace_config
->itm_ts_prescale
<< 8) |
125 (trace_config
->trace_bus_id
<< 16));
126 if (retval
!= ERROR_OK
)
129 for (unsigned int i
= 0; i
< 8; i
++) {
130 retval
= target_write_u32(target
, ITM_TER0
+ i
* 4,
131 trace_config
->itm_ter
[i
]);
132 if (retval
!= ERROR_OK
)
139 static void close_trace_file(struct armv7m_common
*armv7m
)
141 if (armv7m
->trace_config
.trace_file
)
142 fclose(armv7m
->trace_config
.trace_file
);
143 armv7m
->trace_config
.trace_file
= NULL
;
146 COMMAND_HANDLER(handle_tpiu_config_command
)
148 struct target
*target
= get_current_target(CMD_CTX
);
149 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
151 unsigned int cmd_idx
= 0;
153 if (CMD_ARGC
== cmd_idx
)
154 return ERROR_COMMAND_SYNTAX_ERROR
;
155 if (!strcmp(CMD_ARGV
[cmd_idx
], "disable")) {
156 if (CMD_ARGC
== cmd_idx
+ 1) {
157 close_trace_file(armv7m
);
159 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_DISABLED
;
160 if (CMD_CTX
->mode
== COMMAND_EXEC
)
161 return armv7m_trace_tpiu_config(target
);
165 } else if (!strcmp(CMD_ARGV
[cmd_idx
], "external") ||
166 !strcmp(CMD_ARGV
[cmd_idx
], "internal")) {
167 close_trace_file(armv7m
);
169 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_EXTERNAL
;
170 if (!strcmp(CMD_ARGV
[cmd_idx
], "internal")) {
172 if (CMD_ARGC
== cmd_idx
)
173 return ERROR_COMMAND_SYNTAX_ERROR
;
175 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_INTERNAL
;
177 if (strcmp(CMD_ARGV
[cmd_idx
], "-") != 0) {
178 armv7m
->trace_config
.trace_file
= fopen(CMD_ARGV
[cmd_idx
], "ab");
179 if (!armv7m
->trace_config
.trace_file
) {
180 LOG_ERROR("Can't open trace destination file");
186 if (CMD_ARGC
== cmd_idx
)
187 return ERROR_COMMAND_SYNTAX_ERROR
;
189 if (!strcmp(CMD_ARGV
[cmd_idx
], "sync")) {
190 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_SYNC
;
193 if (CMD_ARGC
== cmd_idx
)
194 return ERROR_COMMAND_SYNTAX_ERROR
;
196 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.port_size
);
198 if (!strcmp(CMD_ARGV
[cmd_idx
], "manchester"))
199 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_ASYNC_MANCHESTER
;
200 else if (!strcmp(CMD_ARGV
[cmd_idx
], "uart"))
201 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_ASYNC_UART
;
203 return ERROR_COMMAND_SYNTAX_ERROR
;
206 if (CMD_ARGC
== cmd_idx
)
207 return ERROR_COMMAND_SYNTAX_ERROR
;
209 COMMAND_PARSE_ON_OFF(CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.formatter
);
213 if (CMD_ARGC
== cmd_idx
)
214 return ERROR_COMMAND_SYNTAX_ERROR
;
216 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.traceclkin_freq
);
219 if (CMD_ARGC
!= cmd_idx
) {
220 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.trace_freq
);
223 if (armv7m
->trace_config
.config_type
!= TRACE_CONFIG_TYPE_INTERNAL
) {
224 LOG_ERROR("Trace port frequency can't be omitted in external capture mode");
225 return ERROR_COMMAND_SYNTAX_ERROR
;
227 armv7m
->trace_config
.trace_freq
= 0;
230 if (CMD_ARGC
== cmd_idx
) {
231 if (CMD_CTX
->mode
== COMMAND_EXEC
)
232 return armv7m_trace_tpiu_config(target
);
238 return ERROR_COMMAND_SYNTAX_ERROR
;
241 COMMAND_HANDLER(handle_itm_port_command
)
243 struct target
*target
= get_current_target(CMD_CTX
);
244 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
245 unsigned int reg_idx
;
250 return ERROR_COMMAND_SYNTAX_ERROR
;
252 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0], port
);
253 COMMAND_PARSE_ON_OFF(CMD_ARGV
[1], enable
);
257 armv7m
->trace_config
.itm_ter
[reg_idx
] |= (1 << port
);
259 armv7m
->trace_config
.itm_ter
[reg_idx
] &= ~(1 << port
);
261 if (CMD_CTX
->mode
== COMMAND_EXEC
)
262 return armv7m_trace_itm_config(target
);
267 COMMAND_HANDLER(handle_itm_ports_command
)
269 struct target
*target
= get_current_target(CMD_CTX
);
270 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
274 return ERROR_COMMAND_SYNTAX_ERROR
;
276 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], enable
);
277 memset(armv7m
->trace_config
.itm_ter
, enable
? 0xff : 0,
278 sizeof(armv7m
->trace_config
.itm_ter
));
280 if (CMD_CTX
->mode
== COMMAND_EXEC
)
281 return armv7m_trace_itm_config(target
);
286 static const struct command_registration tpiu_command_handlers
[] = {
289 .handler
= handle_tpiu_config_command
,
291 .help
= "Configure TPIU features",
292 .usage
= "(disable | "
293 "((external | internal <filename>) "
294 "(sync <port width> | ((manchester | uart) <formatter enable>)) "
295 "<TRACECLKIN freq> [<trace freq>]))",
297 COMMAND_REGISTRATION_DONE
300 static const struct command_registration itm_command_handlers
[] = {
303 .handler
= handle_itm_port_command
,
305 .help
= "Enable or disable ITM stimulus port",
306 .usage
= "<port> (0|1|on|off)",
310 .handler
= handle_itm_ports_command
,
312 .help
= "Enable or disable all ITM stimulus ports",
313 .usage
= "(0|1|on|off)",
315 COMMAND_REGISTRATION_DONE
318 const struct command_registration armv7m_trace_command_handlers
[] = {
322 .help
= "tpiu command group",
324 .chain
= tpiu_command_handlers
,
329 .help
= "itm command group",
331 .chain
= itm_command_handlers
,
333 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)