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,
120 TARGET_TIMER_TYPE_PERIODIC
, target
);
122 target_call_event_callbacks(target
, TARGET_EVENT_TRACE_CONFIG
);
127 int armv7m_trace_itm_config(struct target
*target
)
129 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
130 struct armv7m_trace_config
*trace_config
= &armv7m
->trace_config
;
133 retval
= target_write_u32(target
, ITM_LAR
, ITM_LAR_KEY
);
134 if (retval
!= ERROR_OK
)
137 /* Enable ITM, TXENA, set TraceBusID and other parameters */
138 retval
= target_write_u32(target
, ITM_TCR
, (1 << 0) | (1 << 3) |
139 (trace_config
->itm_diff_timestamps
<< 1) |
140 (trace_config
->itm_synchro_packets
<< 2) |
141 (trace_config
->itm_async_timestamps
<< 4) |
142 (trace_config
->itm_ts_prescale
<< 8) |
143 (trace_config
->trace_bus_id
<< 16));
144 if (retval
!= ERROR_OK
)
147 for (unsigned int i
= 0; i
< 8; i
++) {
148 retval
= target_write_u32(target
, ITM_TER0
+ i
* 4,
149 trace_config
->itm_ter
[i
]);
150 if (retval
!= ERROR_OK
)
157 static void close_trace_file(struct armv7m_common
*armv7m
)
159 if (armv7m
->trace_config
.trace_file
)
160 fclose(armv7m
->trace_config
.trace_file
);
161 armv7m
->trace_config
.trace_file
= NULL
;
164 COMMAND_HANDLER(handle_tpiu_config_command
)
166 struct target
*target
= get_current_target(CMD_CTX
);
167 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
169 unsigned int cmd_idx
= 0;
171 if (CMD_ARGC
== cmd_idx
)
172 return ERROR_COMMAND_SYNTAX_ERROR
;
173 if (!strcmp(CMD_ARGV
[cmd_idx
], "disable")) {
174 if (CMD_ARGC
== cmd_idx
+ 1) {
175 close_trace_file(armv7m
);
177 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_DISABLED
;
178 if (CMD_CTX
->mode
== COMMAND_EXEC
)
179 return armv7m_trace_tpiu_config(target
);
183 } else if (!strcmp(CMD_ARGV
[cmd_idx
], "external") ||
184 !strcmp(CMD_ARGV
[cmd_idx
], "internal")) {
185 close_trace_file(armv7m
);
187 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_EXTERNAL
;
188 if (!strcmp(CMD_ARGV
[cmd_idx
], "internal")) {
190 if (CMD_ARGC
== cmd_idx
)
191 return ERROR_COMMAND_SYNTAX_ERROR
;
193 armv7m
->trace_config
.config_type
= TRACE_CONFIG_TYPE_INTERNAL
;
195 if (strcmp(CMD_ARGV
[cmd_idx
], "-") != 0) {
196 armv7m
->trace_config
.trace_file
= fopen(CMD_ARGV
[cmd_idx
], "ab");
197 if (!armv7m
->trace_config
.trace_file
) {
198 LOG_ERROR("Can't open trace destination file");
204 if (CMD_ARGC
== cmd_idx
)
205 return ERROR_COMMAND_SYNTAX_ERROR
;
207 if (!strcmp(CMD_ARGV
[cmd_idx
], "sync")) {
208 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_SYNC
;
211 if (CMD_ARGC
== cmd_idx
)
212 return ERROR_COMMAND_SYNTAX_ERROR
;
214 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.port_size
);
216 if (!strcmp(CMD_ARGV
[cmd_idx
], "manchester"))
217 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_ASYNC_MANCHESTER
;
218 else if (!strcmp(CMD_ARGV
[cmd_idx
], "uart"))
219 armv7m
->trace_config
.pin_protocol
= TPIU_PIN_PROTOCOL_ASYNC_UART
;
221 return ERROR_COMMAND_SYNTAX_ERROR
;
224 if (CMD_ARGC
== cmd_idx
)
225 return ERROR_COMMAND_SYNTAX_ERROR
;
227 COMMAND_PARSE_ON_OFF(CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.formatter
);
231 if (CMD_ARGC
== cmd_idx
)
232 return ERROR_COMMAND_SYNTAX_ERROR
;
234 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.traceclkin_freq
);
237 if (CMD_ARGC
!= cmd_idx
) {
238 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[cmd_idx
], armv7m
->trace_config
.trace_freq
);
241 if (armv7m
->trace_config
.config_type
!= TRACE_CONFIG_TYPE_INTERNAL
) {
242 LOG_ERROR("Trace port frequency can't be omitted in external capture mode");
243 return ERROR_COMMAND_SYNTAX_ERROR
;
245 armv7m
->trace_config
.trace_freq
= 0;
248 if (CMD_ARGC
== cmd_idx
) {
249 if (CMD_CTX
->mode
== COMMAND_EXEC
)
250 return armv7m_trace_tpiu_config(target
);
256 return ERROR_COMMAND_SYNTAX_ERROR
;
259 COMMAND_HANDLER(handle_itm_port_command
)
261 struct target
*target
= get_current_target(CMD_CTX
);
262 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
263 unsigned int reg_idx
;
268 return ERROR_COMMAND_SYNTAX_ERROR
;
270 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[0], port
);
271 COMMAND_PARSE_ON_OFF(CMD_ARGV
[1], enable
);
275 armv7m
->trace_config
.itm_ter
[reg_idx
] |= (1 << port
);
277 armv7m
->trace_config
.itm_ter
[reg_idx
] &= ~(1 << port
);
279 if (CMD_CTX
->mode
== COMMAND_EXEC
)
280 return armv7m_trace_itm_config(target
);
285 COMMAND_HANDLER(handle_itm_ports_command
)
287 struct target
*target
= get_current_target(CMD_CTX
);
288 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
292 return ERROR_COMMAND_SYNTAX_ERROR
;
294 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], enable
);
295 memset(armv7m
->trace_config
.itm_ter
, enable
? 0xff : 0,
296 sizeof(armv7m
->trace_config
.itm_ter
));
298 if (CMD_CTX
->mode
== COMMAND_EXEC
)
299 return armv7m_trace_itm_config(target
);
304 static const struct command_registration tpiu_command_handlers
[] = {
307 .handler
= handle_tpiu_config_command
,
309 .help
= "Configure TPIU features",
310 .usage
= "(disable | "
311 "((external | internal <filename>) "
312 "(sync <port width> | ((manchester | uart) <formatter enable>)) "
313 "<TRACECLKIN freq> [<trace freq>]))",
315 COMMAND_REGISTRATION_DONE
318 static const struct command_registration itm_command_handlers
[] = {
321 .handler
= handle_itm_port_command
,
323 .help
= "Enable or disable ITM stimulus port",
324 .usage
= "<port> (0|1|on|off)",
328 .handler
= handle_itm_ports_command
,
330 .help
= "Enable or disable all ITM stimulus ports",
331 .usage
= "(0|1|on|off)",
333 COMMAND_REGISTRATION_DONE
336 const struct command_registration armv7m_trace_command_handlers
[] = {
340 .help
= "tpiu command group",
342 .chain
= tpiu_command_handlers
,
347 .help
= "itm command group",
349 .chain
= itm_command_handlers
,
351 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)