1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Xtensa application tracing module for OpenOCD *
5 * Copyright (C) 2017 Espressif Systems Ltd. *
6 ***************************************************************************/
10 https://github.com/espressif/esp-idf/blob/master/components/app_trace/port/xtensa/port.c#L8
17 #include <helper/align.h>
18 #include <target/xtensa/xtensa.h>
19 #include <target/xtensa/xtensa_debug_module.h>
20 #include "esp_xtensa_apptrace.h"
22 /* TRAX is disabled, so we use its registers for our own purposes
23 * | 31..XXXXXX..24 | 23 .(host_connect). 23 | 22 .(host_data). 22| 21..(block_id)..15 | 14..(block_len)..0 |
25 #define XTENSA_APPTRACE_CTRL_REG XDMREG_DELAYCNT
26 #define XTENSA_APPTRACE_BLOCK_ID_MSK 0x7FUL
27 #define XTENSA_APPTRACE_BLOCK_ID_MAX XTENSA_APPTRACE_BLOCK_ID_MSK
28 /* if non-zero then apptrace code entered the critical section and the value is an address of the
29 * critical section's exit point */
30 #define XTENSA_APPTRACE_STAT_REG XDMREG_TRIGGERPC
32 #define XTENSA_APPTRACE_BLOCK_LEN_MSK 0x7FFFUL
33 #define XTENSA_APPTRACE_BLOCK_LEN(_l_) ((_l_) & XTENSA_APPTRACE_BLOCK_LEN_MSK)
34 #define XTENSA_APPTRACE_BLOCK_LEN_GET(_v_) ((_v_) & XTENSA_APPTRACE_BLOCK_LEN_MSK)
35 #define XTENSA_APPTRACE_BLOCK_ID(_id_) (((_id_) & XTENSA_APPTRACE_BLOCK_ID_MSK) << 15)
36 #define XTENSA_APPTRACE_BLOCK_ID_GET(_v_) (((_v_) >> 15) & XTENSA_APPTRACE_BLOCK_ID_MSK)
37 #define XTENSA_APPTRACE_HOST_DATA BIT(22)
38 #define XTENSA_APPTRACE_HOST_CONNECT BIT(23)
40 static int esp_xtensa_apptrace_leave_crit_section_start(struct target
*target
);
41 static int esp_xtensa_apptrace_leave_crit_section_stop(struct target
*target
);
42 static int esp_xtensa_apptrace_buffs_write(struct target
*target
,
45 const uint8_t *bufs
[],
50 struct esp32_apptrace_hw esp_xtensa_apptrace_hw
= {
51 .max_block_id
= XTENSA_APPTRACE_BLOCK_ID_MAX
,
52 .max_block_size_get
= esp_xtensa_apptrace_block_max_size_get
,
53 .status_reg_read
= esp_xtensa_apptrace_status_reg_read
,
54 .ctrl_reg_write
= esp_xtensa_apptrace_ctrl_reg_write
,
55 .ctrl_reg_read
= esp_xtensa_apptrace_ctrl_reg_read
,
56 .data_len_read
= esp_xtensa_apptrace_data_len_read
,
57 .data_read
= esp_xtensa_apptrace_data_read
,
58 .usr_block_max_size_get
= esp_xtensa_apptrace_usr_block_max_size_get
,
59 .buffs_write
= esp_xtensa_apptrace_buffs_write
,
60 .leave_trace_crit_section_start
= esp_xtensa_apptrace_leave_crit_section_start
,
61 .leave_trace_crit_section_stop
= esp_xtensa_apptrace_leave_crit_section_stop
,
64 uint32_t esp_xtensa_apptrace_block_max_size_get(struct target
*target
)
66 struct xtensa
*xtensa
= target_to_xtensa(target
);
67 struct xtensa_trace_status trace_status
;
68 struct xtensa_trace_config trace_config
;
69 uint32_t max_trace_block_sz
;
71 int res
= xtensa_dm_trace_status_read(&xtensa
->dbg_mod
, &trace_status
);
72 if (res
!= ERROR_OK
) {
73 LOG_ERROR("Failed to read TRAX status (%d)!", res
);
77 max_trace_block_sz
= BIT(((trace_status
.stat
>> 8) & 0x1f) - 2) * 4;
78 res
= xtensa_dm_trace_config_read(&xtensa
->dbg_mod
, &trace_config
);
79 if (res
!= ERROR_OK
) {
80 LOG_ERROR("Failed to read TRAX config (%d)!", res
);
83 LOG_DEBUG("ctrl=0x%" PRIx32
" memadrstart=0x%" PRIx32
" memadrend=0x%" PRIx32
" traxadr=0x%" PRIx32
,
85 trace_config
.memaddr_start
,
86 trace_config
.memaddr_end
,
89 return max_trace_block_sz
;
92 uint32_t esp_xtensa_apptrace_usr_block_max_size_get(struct target
*target
)
94 return esp_xtensa_apptrace_block_max_size_get(target
) - sizeof(struct esp_apptrace_host2target_hdr
);
97 int esp_xtensa_apptrace_data_len_read(struct target
*target
,
101 return esp_xtensa_apptrace_ctrl_reg_read(target
, block_id
, len
, NULL
);
104 int esp_xtensa_apptrace_usr_block_write(struct target
*target
,
109 return esp_apptrace_usr_block_write(&esp_xtensa_apptrace_hw
, target
, block_id
, data
, size
);
112 static int esp_xtensa_apptrace_data_reverse_read(struct xtensa
*xtensa
,
118 uint32_t rd_sz
= ALIGN_UP(size
, 4);
120 res
= xtensa_queue_dbg_reg_write(xtensa
, XDMREG_TRAXADDR
, (xtensa
->core_config
->trace
.mem_sz
- rd_sz
) / 4);
123 if (!IS_ALIGNED(size
, 4)) {
124 res
= xtensa_queue_dbg_reg_read(xtensa
, XDMREG_TRAXDATA
, unal_bytes
);
128 for (unsigned int i
= size
/ 4; i
!= 0; i
--) {
129 res
= xtensa_queue_dbg_reg_read(xtensa
, XDMREG_TRAXDATA
, &buffer
[(i
- 1) * 4]);
136 static int esp_xtensa_apptrace_data_normal_read(struct xtensa
*xtensa
,
141 int res
= xtensa_queue_dbg_reg_write(xtensa
, XDMREG_TRAXADDR
, 0);
144 for (unsigned int i
= 0; i
< size
/ 4; i
++) {
145 res
= xtensa_queue_dbg_reg_read(xtensa
, XDMREG_TRAXDATA
, &buffer
[i
* 4]);
149 if (!IS_ALIGNED(size
, 4)) {
150 res
= xtensa_queue_dbg_reg_read(xtensa
, XDMREG_TRAXDATA
, unal_bytes
);
157 int esp_xtensa_apptrace_data_read(struct target
*target
,
163 struct xtensa
*xtensa
= target_to_xtensa(target
);
165 uint32_t tmp
= XTENSA_APPTRACE_HOST_CONNECT
| XTENSA_APPTRACE_BLOCK_ID(block_id
) |
166 XTENSA_APPTRACE_BLOCK_LEN(0);
167 uint8_t unal_bytes
[4];
169 LOG_DEBUG("Read data on target (%s)", target_name(target
));
170 if (xtensa
->core_config
->trace
.reversed_mem_access
)
171 res
= esp_xtensa_apptrace_data_reverse_read(xtensa
, size
, buffer
, unal_bytes
);
173 res
= esp_xtensa_apptrace_data_normal_read(xtensa
, size
, buffer
, unal_bytes
);
177 LOG_DEBUG("Ack block %" PRIu32
" target (%s)!", block_id
, target_name(target
));
178 res
= xtensa_queue_dbg_reg_write(xtensa
, XTENSA_APPTRACE_CTRL_REG
, tmp
);
182 xtensa_dm_queue_tdi_idle(&xtensa
->dbg_mod
);
183 res
= xtensa_dm_queue_execute(&xtensa
->dbg_mod
);
184 if (res
!= ERROR_OK
) {
185 LOG_ERROR("Failed to exec JTAG queue!");
188 if (!IS_ALIGNED(size
, 4)) {
189 /* copy the last unaligned bytes */
190 memcpy(buffer
+ ALIGN_DOWN(size
, 4), unal_bytes
, size
& 0x3UL
);
195 int esp_xtensa_apptrace_ctrl_reg_write(struct target
*target
,
201 struct xtensa
*xtensa
= target_to_xtensa(target
);
202 uint32_t tmp
= (conn
? XTENSA_APPTRACE_HOST_CONNECT
: 0) |
203 (data
? XTENSA_APPTRACE_HOST_DATA
: 0) | XTENSA_APPTRACE_BLOCK_ID(block_id
) |
204 XTENSA_APPTRACE_BLOCK_LEN(len
);
206 xtensa_queue_dbg_reg_write(xtensa
, XTENSA_APPTRACE_CTRL_REG
, tmp
);
207 xtensa_dm_queue_tdi_idle(&xtensa
->dbg_mod
);
208 int res
= xtensa_dm_queue_execute(&xtensa
->dbg_mod
);
209 if (res
!= ERROR_OK
) {
210 LOG_ERROR("Failed to exec JTAG queue!");
217 int esp_xtensa_apptrace_ctrl_reg_read(struct target
*target
,
222 struct xtensa
*xtensa
= target_to_xtensa(target
);
225 xtensa_queue_dbg_reg_read(xtensa
, XTENSA_APPTRACE_CTRL_REG
, tmp
);
226 xtensa_dm_queue_tdi_idle(&xtensa
->dbg_mod
);
227 int res
= xtensa_dm_queue_execute(&xtensa
->dbg_mod
);
230 uint32_t val
= target_buffer_get_u32(target
, tmp
);
232 *block_id
= XTENSA_APPTRACE_BLOCK_ID_GET(val
);
234 *len
= XTENSA_APPTRACE_BLOCK_LEN_GET(val
);
236 *conn
= val
& XTENSA_APPTRACE_HOST_CONNECT
;
240 int esp_xtensa_apptrace_status_reg_read(struct target
*target
, uint32_t *stat
)
242 struct xtensa
*xtensa
= target_to_xtensa(target
);
245 int res
= xtensa_queue_dbg_reg_read(xtensa
, XTENSA_APPTRACE_STAT_REG
, tmp
);
248 xtensa_dm_queue_tdi_idle(&xtensa
->dbg_mod
);
249 res
= xtensa_dm_queue_execute(&xtensa
->dbg_mod
);
250 if (res
!= ERROR_OK
) {
251 LOG_ERROR("Failed to exec JTAG queue!");
254 *stat
= buf_get_u32(tmp
, 0, 32);
258 int esp_xtensa_apptrace_status_reg_write(struct target
*target
, uint32_t stat
)
260 struct xtensa
*xtensa
= target_to_xtensa(target
);
262 xtensa_queue_dbg_reg_write(xtensa
, XTENSA_APPTRACE_STAT_REG
, stat
);
263 xtensa_dm_queue_tdi_idle(&xtensa
->dbg_mod
);
264 int res
= xtensa_dm_queue_execute(&xtensa
->dbg_mod
);
265 if (res
!= ERROR_OK
) {
266 LOG_ERROR("Failed to exec JTAG queue!");
272 static int esp_xtensa_swdbg_activate(struct target
*target
, int enab
)
274 struct xtensa
*xtensa
= target_to_xtensa(target
);
276 xtensa_queue_dbg_reg_write(xtensa
, enab
? XDMREG_DCRSET
: XDMREG_DCRCLR
, OCDDCR_DEBUGSWACTIVE
);
277 xtensa_dm_queue_tdi_idle(&xtensa
->dbg_mod
);
278 int res
= xtensa_dm_queue_execute(&xtensa
->dbg_mod
);
279 if (res
!= ERROR_OK
) {
280 LOG_ERROR("%s: writing DCR failed!", target
->cmd_name
);
287 static int esp_xtensa_apptrace_leave_crit_section_start(struct target
*target
)
289 /* TODO: not sure that we need this, but it seems that we fail to leave tracing critical
291 int res
= esp_xtensa_swdbg_activate(target
, 1 /*enable*/);
292 if (res
!= ERROR_OK
) {
293 LOG_ERROR("Failed to activate SW debug (%d)!", res
);
299 static int esp_xtensa_apptrace_leave_crit_section_stop(struct target
*target
)
301 int res
= esp_xtensa_swdbg_activate(target
, 0 /*disable*/);
302 if (res
!= ERROR_OK
) {
303 LOG_ERROR("Failed to activate SW debug (%d)!", res
);
309 static int esp_xtensa_apptrace_queue_reverse_write(struct target
*target
, uint32_t bufs_num
,
310 uint32_t buf_sz
[], const uint8_t *bufs
[])
313 uint32_t cached_bytes
= 0, total_sz
= 0;
314 uint8_t cached_data8
[sizeof(uint32_t)] = { 0 };
315 uint32_t cached_data32
= 0;
317 struct xtensa
*xtensa
= target_to_xtensa(target
);
319 for (uint32_t i
= 0; i
< bufs_num
; i
++)
320 total_sz
+= buf_sz
[i
];
321 if (!IS_ALIGNED(total_sz
, 4)) {
322 cached_bytes
= sizeof(uint32_t) - (total_sz
& 0x3UL
);
323 total_sz
= ALIGN_UP(total_sz
, 4);
325 xtensa_queue_dbg_reg_write(xtensa
, XDMREG_TRAXADDR
, (xtensa
->core_config
->trace
.mem_sz
- total_sz
) / 4);
326 for (uint32_t i
= bufs_num
; i
> 0; i
--) {
327 uint32_t bsz
= buf_sz
[i
- 1];
328 const uint8_t *cur_buf
= &bufs
[i
- 1][bsz
];
329 uint32_t bytes_to_cache
;
330 /* if there are cached bytes from the previous buffer, combine them with the last
331 * from the current buffer */
333 if ((cached_bytes
+ bsz
) < sizeof(uint32_t))
334 bytes_to_cache
= bsz
;
336 bytes_to_cache
= sizeof(uint32_t) - cached_bytes
;
337 memcpy(&cached_data8
[sizeof(uint32_t) - cached_bytes
- bytes_to_cache
],
338 cur_buf
- bytes_to_cache
,
340 cached_data32
= target_buffer_get_u32(target
, cached_data8
);
341 cached_bytes
+= bytes_to_cache
;
342 if (cached_bytes
< sizeof(uint32_t))
344 res
= xtensa_queue_dbg_reg_write(xtensa
, XDMREG_TRAXDATA
, cached_data32
);
347 bsz
-= bytes_to_cache
;
348 cur_buf
-= bytes_to_cache
;
349 memset(cached_data8
, 0x00, sizeof(cached_data8
));
352 /* write full dwords */
353 for (unsigned int k
= bsz
; k
>= sizeof(uint32_t); k
-= sizeof(uint32_t)) {
354 uint32_t temp
= target_buffer_get_u32(target
, cur_buf
- sizeof(uint32_t));
355 res
= xtensa_queue_dbg_reg_write(xtensa
, XDMREG_TRAXDATA
, temp
);
358 cur_buf
-= sizeof(uint32_t);
360 /* if there are bytes to be cached (1..3) */
361 bytes_to_cache
= bsz
& 0x3UL
;
362 if (bytes_to_cache
> 0) {
363 if (bytes_to_cache
+ cached_bytes
>= sizeof(uint32_t)) {
364 /* filling the cache buffer from the end to beginning */
365 uint32_t to_copy
= sizeof(uint32_t) - cached_bytes
;
366 memcpy(&cached_data8
[0], cur_buf
- to_copy
, to_copy
);
367 cached_data32
= target_buffer_get_u32(target
, cached_data8
);
368 /* write full word of cached bytes */
369 res
= xtensa_queue_dbg_reg_write(xtensa
, XDMREG_TRAXDATA
, cached_data32
);
372 /* cache remaining bytes */
373 memset(cached_data8
, 0x00, sizeof(cached_data8
));
375 to_copy
= bytes_to_cache
+ cached_bytes
- sizeof(uint32_t);
376 memcpy(&cached_data8
[sizeof(uint32_t) - to_copy
], cur_buf
- to_copy
, to_copy
);
377 cached_bytes
= to_copy
;
379 /* filling the cache buffer from the end to beginning */
380 memcpy(&cached_data8
[sizeof(uint32_t) - cached_bytes
- bytes_to_cache
],
381 cur_buf
- bytes_to_cache
,
383 cached_bytes
+= bytes_to_cache
;
390 static int esp_xtensa_apptrace_queue_normal_write(struct target
*target
, uint32_t bufs_num
,
391 uint32_t buf_sz
[], const uint8_t *bufs
[])
394 uint32_t cached_bytes
= 0;
395 uint8_t cached_data8
[4] = { 0 };
396 uint32_t cached_data32
= 0;
398 struct xtensa
*xtensa
= target_to_xtensa(target
);
400 /* | 1 | 2 | 1 | 2 | 4 |.......|
402 xtensa_queue_dbg_reg_write(xtensa
, XDMREG_TRAXADDR
, 0);
403 for (unsigned int i
= 0; i
< bufs_num
; i
++) {
404 uint32_t bsz
= buf_sz
[i
];
405 const uint8_t *cur_buf
= bufs
[i
];
406 uint32_t bytes_to_cache
;
407 /* if there are cached bytes from the previous buffer, combine them with the last
408 * from the current buffer */
410 if ((cached_bytes
+ bsz
) < sizeof(uint32_t))
411 bytes_to_cache
= bsz
;
413 bytes_to_cache
= sizeof(uint32_t) - cached_bytes
;
414 memcpy(&cached_data8
[cached_bytes
], cur_buf
, bytes_to_cache
);
415 cached_bytes
+= bytes_to_cache
;
416 if (cached_bytes
< sizeof(uint32_t))
418 cached_data32
= target_buffer_get_u32(target
, cached_data8
);
419 res
= xtensa_queue_dbg_reg_write(xtensa
, XDMREG_TRAXDATA
, cached_data32
);
422 bsz
-= bytes_to_cache
;
423 cur_buf
+= bytes_to_cache
;
424 memset(cached_data8
, 0x00, sizeof(cached_data8
));
427 /* write full dwords */
428 for (unsigned int k
= 0; (k
+ sizeof(uint32_t)) <= bsz
; k
+= sizeof(uint32_t)) {
429 uint32_t temp
= target_buffer_get_u32(target
, cur_buf
);
430 res
= xtensa_queue_dbg_reg_write(xtensa
, XDMREG_TRAXDATA
, temp
);
433 cur_buf
+= sizeof(uint32_t);
435 /* if there are bytes to be cached (1..3) */
436 bytes_to_cache
= bsz
& 0x3UL
;
437 if (bytes_to_cache
> 0) {
438 if (bytes_to_cache
+ cached_bytes
>= sizeof(uint32_t)) {
439 memcpy(&cached_data8
[0], cur_buf
, sizeof(uint32_t) - cached_bytes
);
440 cached_data32
= target_buffer_get_u32(target
, cached_data8
);
441 /* write full word of cached bytes */
442 res
= xtensa_queue_dbg_reg_write(xtensa
, XDMREG_TRAXDATA
, cached_data32
);
445 /* cache remaining bytes */
446 memset(cached_data8
, 0x00, sizeof(cached_data8
));
447 cur_buf
+= sizeof(uint32_t) - cached_bytes
;
448 cached_bytes
= bytes_to_cache
+ cached_bytes
- sizeof(uint32_t);
449 memcpy(&cached_data8
[0], cur_buf
, cached_bytes
);
451 memcpy(&cached_data8
[cached_bytes
], cur_buf
, bytes_to_cache
);
452 cached_bytes
+= bytes_to_cache
;
457 /* write remaining cached bytes */
458 cached_data32
= target_buffer_get_u32(target
, cached_data8
);
459 res
= xtensa_queue_dbg_reg_write(xtensa
, XDMREG_TRAXDATA
, cached_data32
);
466 static int esp_xtensa_apptrace_buffs_write(struct target
*target
,
469 const uint8_t *bufs
[],
474 struct xtensa
*xtensa
= target_to_xtensa(target
);
476 uint32_t tmp
= XTENSA_APPTRACE_HOST_CONNECT
|
477 (data
? XTENSA_APPTRACE_HOST_DATA
: 0) | XTENSA_APPTRACE_BLOCK_ID(block_id
) |
478 XTENSA_APPTRACE_BLOCK_LEN(0);
480 if (xtensa
->core_config
->trace
.reversed_mem_access
)
481 res
= esp_xtensa_apptrace_queue_reverse_write(target
, bufs_num
, buf_sz
, bufs
);
483 res
= esp_xtensa_apptrace_queue_normal_write(target
, bufs_num
, buf_sz
, bufs
);
487 LOG_DEBUG("Ack block %" PRId32
" on target (%s)!", block_id
, target_name(target
));
488 res
= xtensa_queue_dbg_reg_write(xtensa
, XTENSA_APPTRACE_CTRL_REG
, tmp
);
492 xtensa_dm_queue_tdi_idle(&xtensa
->dbg_mod
);
493 res
= xtensa_dm_queue_execute(&xtensa
->dbg_mod
);
494 if (res
!= ERROR_OK
) {
495 LOG_ERROR("Failed to exec JTAG queue!");
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)