1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * ESP32 sysview tracing module *
5 * Copyright (C) 2020 Espressif Systems Ltd. *
6 ***************************************************************************/
12 #include <helper/log.h>
13 #include "esp32_apptrace.h"
14 #include "esp32_sysview.h"
15 #include "segger_sysview.h"
17 /* in SystemView mode core ID is passed in event ID field */
18 #define ESP32_SYSVIEW_USER_BLOCK_CORE(_v_) (0) /* not used */
19 #define ESP32_SYSVIEW_USER_BLOCK_LEN(_v_) (_v_)
20 #define ESP32_SYSVIEW_USER_BLOCK_HDR_SZ 2
22 struct esp_sysview_target2host_hdr
{
26 #define SYSVIEW_BLOCK_SIZE_OFFSET 0
27 #define SYSVIEW_WR_SIZE_OFFSET 1
29 static int esp_sysview_trace_header_write(struct esp32_apptrace_cmd_ctx
*ctx
, bool mcore_format
);
30 static int esp32_sysview_core_id_get(struct target
*target
, uint8_t *hdr_buf
);
31 static uint32_t esp32_sysview_usr_block_len_get(struct target
*target
, uint8_t *hdr_buf
, uint32_t *wr_len
);
33 int esp32_sysview_cmd_init(struct esp32_apptrace_cmd_ctx
*cmd_ctx
,
34 struct command_invocation
*cmd
,
40 struct esp32_sysview_cmd_data
*cmd_data
;
43 command_print(cmd
, "Not enough args! Need trace data destination!");
47 int res
= esp32_apptrace_cmd_ctx_init(cmd_ctx
, cmd
, mode
);
51 int core_num
= cmd_ctx
->cores_num
;
53 if (!mcore_format
&& argc
< core_num
) {
54 command_print(cmd
, "Not enough args! Need %d trace data destinations!", core_num
);
59 cmd_data
= calloc(1, sizeof(*cmd_data
));
61 command_print(cmd
, "No memory for command data!");
65 cmd_ctx
->cmd_priv
= cmd_data
;
66 cmd_data
->mcore_format
= mcore_format
;
68 /*outfile1 [outfile2] [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]] */
69 int dests_num
= esp32_apptrace_dest_init(cmd_data
->data_dests
, argv
, !mcore_format
? core_num
: 1);
70 if (!mcore_format
&& dests_num
< core_num
) {
71 command_print(cmd
, "Not enough args! Need %d trace data destinations!", core_num
);
76 cmd_data
->apptrace
.max_len
= UINT32_MAX
;
77 cmd_data
->apptrace
.poll_period
= 0 /*ms*/;
78 cmd_ctx
->stop_tmo
= -1.0; /* infinite */
79 if (argc
> dests_num
) {
80 /* parse remaining args */
81 esp32_apptrace_cmd_args_parse(cmd_ctx
,
86 LOG_USER("App trace params: from %d cores, size %u bytes, stop_tmo %g s, "
87 "poll period %u ms, wait_rst %d, skip %u bytes",
89 cmd_data
->apptrace
.max_len
,
91 cmd_data
->apptrace
.poll_period
,
92 cmd_data
->apptrace
.wait4halt
,
93 cmd_data
->apptrace
.skip_len
);
95 cmd_ctx
->trace_format
.hdr_sz
= ESP32_SYSVIEW_USER_BLOCK_HDR_SZ
;
96 cmd_ctx
->trace_format
.core_id_get
= esp32_sysview_core_id_get
;
97 cmd_ctx
->trace_format
.usr_block_len_get
= esp32_sysview_usr_block_len_get
;
99 res
= esp_sysview_trace_header_write(cmd_ctx
, mcore_format
);
100 if (res
!= ERROR_OK
) {
101 command_print(cmd
, "Failed to write trace header (%d)!", res
);
102 esp32_apptrace_dest_cleanup(cmd_data
->data_dests
, core_num
);
108 cmd_ctx
->running
= 0;
109 esp32_apptrace_cmd_ctx_cleanup(cmd_ctx
);
113 int esp32_sysview_cmd_cleanup(struct esp32_apptrace_cmd_ctx
*cmd_ctx
)
115 struct esp32_sysview_cmd_data
*cmd_data
= cmd_ctx
->cmd_priv
;
117 esp32_apptrace_dest_cleanup(cmd_data
->data_dests
, cmd_ctx
->cores_num
);
119 cmd_ctx
->cmd_priv
= NULL
;
120 esp32_apptrace_cmd_ctx_cleanup(cmd_ctx
);
124 static int esp32_sysview_core_id_get(struct target
*target
, uint8_t *hdr_buf
)
126 /* for sysview compressed apptrace header is used, so core id is encoded in sysview packet */
130 static uint32_t esp32_sysview_usr_block_len_get(struct target
*target
, uint8_t *hdr_buf
, uint32_t *wr_len
)
132 *wr_len
= ESP32_SYSVIEW_USER_BLOCK_LEN(hdr_buf
[SYSVIEW_WR_SIZE_OFFSET
]);
133 return ESP32_SYSVIEW_USER_BLOCK_LEN(hdr_buf
[SYSVIEW_BLOCK_SIZE_OFFSET
]);
136 static int esp_sysview_trace_header_write(struct esp32_apptrace_cmd_ctx
*ctx
, bool mcore_format
)
138 struct esp32_sysview_cmd_data
*cmd_data
= ctx
->cmd_priv
;
144 "; Version " SYSVIEW_MIN_VER_STRING
"\n"
145 "; Author Espressif Inc\n"
147 dests_num
= ctx
->cores_num
;
150 "; Version " SYSVIEW_MIN_VER_STRING
"\n"
151 "; Author Espressif Inc\n"
157 int hdr_len
= strlen(hdr_str
);
158 for (int i
= 0; i
< dests_num
; i
++) {
159 int res
= cmd_data
->data_dests
[i
].write(cmd_data
->data_dests
[i
].priv
,
162 if (res
!= ERROR_OK
) {
163 LOG_ERROR("sysview: Failed to write %u bytes to dest %d!", hdr_len
, i
);
170 static void sysview_encode_u32(uint8_t **dest
, uint32_t val
)
172 uint8_t *sv_ptr
= *dest
;
174 *sv_ptr
++ = (uint8_t)(val
| 0x80);
177 *sv_ptr
++ = (uint8_t)val
;
181 static uint32_t esp_sysview_decode_u32(uint8_t **ptr
)
184 for (int k
= 0;; k
++, (*ptr
)++) {
186 val
|= (uint32_t)(**ptr
& ~0x80) << 7 * k
;
188 val
|= (uint32_t)**ptr
<< 7 * k
;
196 static uint16_t esp_sysview_decode_plen(uint8_t **ptr
)
198 uint16_t payload_len
= 0;
200 /* here pkt points to encoded payload length */
202 payload_len
= *(p
+ 1); /* higher part */
203 payload_len
= (payload_len
<< 7) | (*p
& ~0x80);/* lower 7 bits */
204 p
+= 2; /* payload len (2 bytes) */
207 p
++; /* payload len (1 byte) */
214 static uint16_t esp_sysview_get_predef_payload_len(uint16_t id
, uint8_t *pkt
)
220 case SYSVIEW_EVTID_OVERFLOW
:
221 case SYSVIEW_EVTID_ISR_ENTER
:
222 case SYSVIEW_EVTID_TASK_START_EXEC
:
223 case SYSVIEW_EVTID_TASK_START_READY
:
224 case SYSVIEW_EVTID_TASK_CREATE
:
225 case SYSVIEW_EVTID_SYSTIME_CYCLES
:
226 case SYSVIEW_EVTID_USER_START
:
227 case SYSVIEW_EVTID_USER_STOP
:
228 case SYSVIEW_EVTID_TIMER_ENTER
:
230 esp_sysview_decode_u32(&ptr
);
233 case SYSVIEW_EVTID_TASK_STOP_READY
:
234 case SYSVIEW_EVTID_SYSTIME_US
:
236 esp_sysview_decode_u32(&ptr
);
237 esp_sysview_decode_u32(&ptr
);
240 case SYSVIEW_EVTID_SYSDESC
:
244 case SYSVIEW_EVTID_TASK_INFO
:
245 case SYSVIEW_EVTID_MODULEDESC
:
246 /*2*ENCODE_U32 + str */
247 esp_sysview_decode_u32(&ptr
);
248 esp_sysview_decode_u32(&ptr
);
249 /* TODO: add support for strings longer then 255 bytes */
250 len
= ptr
- pkt
+ *ptr
+ 1;
252 case SYSVIEW_EVTID_STACK_INFO
:
254 esp_sysview_decode_u32(&ptr
);
255 esp_sysview_decode_u32(&ptr
);
256 esp_sysview_decode_u32(&ptr
);
257 esp_sysview_decode_u32(&ptr
);
260 case SYSVIEW_EVTID_ISR_EXIT
:
261 case SYSVIEW_EVTID_TASK_STOP_EXEC
:
262 case SYSVIEW_EVTID_TRACE_START
:
263 case SYSVIEW_EVTID_TRACE_STOP
:
264 case SYSVIEW_EVTID_IDLE
:
265 case SYSVIEW_EVTID_ISR_TO_SCHEDULER
:
266 case SYSVIEW_EVTID_TIMER_EXIT
:
270 /*case SYSVIEW_EVTID_NOP: */
272 LOG_ERROR("sysview: Unsupported predef event %d!", id
);
278 static uint16_t esp_sysview_parse_packet(uint8_t *pkt_buf
,
280 unsigned int *pkt_core_id
,
285 uint8_t *pkt
= pkt_buf
;
286 uint16_t event_id
= 0, payload_len
= 0;
290 /* 1-2 byte of message type, 0-2 byte of payload length, payload, 1-5 bytes of timestamp. */
292 if (*(pkt
+ 1) & (1 << 6)) {
294 *(pkt
+ 1) &= ~(1 << 6); /* clear core_id bit */
297 event_id
= *(pkt
+ 1) & ~(1 << 6); /* higher part */
298 event_id
= (event_id
<< 7) | (*pkt
& ~0x80); /* lower 7 bits */
299 pkt
+= 2; /* event_id (2 bytes) */
300 /* here pkt points to encoded payload length */
301 payload_len
= esp_sysview_decode_plen(&pkt
);
303 if (*pkt
& (1 << 6)) {
305 *pkt
&= ~(1 << 6); /* clear core_id bit */
308 /* event_id (1 byte) */
309 event_id
= *pkt
& ~(1 << 6);
312 payload_len
= esp_sysview_get_predef_payload_len(event_id
, pkt
);
314 payload_len
= esp_sysview_decode_plen(&pkt
);
317 uint8_t *delta_start
= pkt
;
318 *delta
= esp_sysview_decode_u32(&pkt
);
319 *delta_len
= pkt
- delta_start
;
320 *pkt_len
= pkt
- pkt_buf
;
321 LOG_DEBUG("sysview: evt %d len %d plen %d dlen %d",
329 static int esp32_sysview_write_packet(struct esp32_sysview_cmd_data
*cmd_data
,
330 int pkt_core_id
, uint32_t pkt_len
, uint8_t *pkt_buf
, uint32_t delta_len
, uint8_t *delta_buf
)
332 if (!cmd_data
->data_dests
[pkt_core_id
].write
)
335 int res
= cmd_data
->data_dests
[pkt_core_id
].write(cmd_data
->data_dests
[pkt_core_id
].priv
, pkt_buf
, pkt_len
);
337 if (res
!= ERROR_OK
) {
338 LOG_ERROR("sysview: Failed to write %u bytes to dest %d!", pkt_len
, pkt_core_id
);
342 /* write packet with modified delta */
343 res
= cmd_data
->data_dests
[pkt_core_id
].write(cmd_data
->data_dests
[pkt_core_id
].priv
, delta_buf
, delta_len
);
344 if (res
!= ERROR_OK
) {
345 LOG_ERROR("sysview: Failed to write %u bytes of delta to dest %d!", delta_len
, pkt_core_id
);
352 static int esp32_sysview_process_packet(struct esp32_apptrace_cmd_ctx
*ctx
,
353 unsigned int pkt_core_id
, uint16_t event_id
, uint32_t delta
, uint32_t delta_len
,
354 uint32_t pkt_len
, uint8_t *pkt_buf
)
356 struct esp32_sysview_cmd_data
*cmd_data
= ctx
->cmd_priv
;
357 int pkt_core_changed
= 0;
358 uint32_t new_delta_len
= 0;
359 uint8_t new_delta_buf
[10];
360 uint32_t wr_len
= pkt_len
;
362 if (ctx
->cores_num
> 1) {
363 if (cmd_data
->sv_last_core_id
== pkt_core_id
) {
364 /* if this packet is for the same core as the prev one acc delta and write packet unmodified */
365 cmd_data
->sv_acc_time_delta
+= delta
;
367 /* if this packet is for another core then prev one set acc delta to the packet's delta */
368 uint8_t *delta_ptr
= new_delta_buf
;
369 sysview_encode_u32(&delta_ptr
, delta
+ cmd_data
->sv_acc_time_delta
);
370 cmd_data
->sv_acc_time_delta
= delta
;
372 new_delta_len
= delta_ptr
- new_delta_buf
;
373 pkt_core_changed
= 1;
375 cmd_data
->sv_last_core_id
= pkt_core_id
;
377 if (pkt_core_id
>= ctx
->cores_num
) {
378 LOG_WARNING("sysview: invalid core ID in packet %d, must be less then %d! Event id %d",
384 int res
= esp32_sysview_write_packet(cmd_data
,
392 for (unsigned int i
= 0; i
< ctx
->cores_num
; i
++) {
393 if (pkt_core_id
== i
)
396 /* messages below should be sent to trace destinations for all cores */
397 case SYSVIEW_EVTID_TRACE_START
:
398 case SYSVIEW_EVTID_TRACE_STOP
:
399 case SYSVIEW_EVTID_SYSTIME_CYCLES
:
400 case SYSVIEW_EVTID_SYSTIME_US
:
401 case SYSVIEW_EVTID_SYSDESC
:
402 case SYSVIEW_EVTID_TASK_INFO
:
403 case SYSVIEW_EVTID_STACK_INFO
:
404 case SYSVIEW_EVTID_MODULEDESC
:
405 case SYSVIEW_EVTID_INIT
:
406 case SYSVIEW_EVTID_NUMMODULES
:
407 case SYSVIEW_EVTID_OVERFLOW
:
408 case SYSVIEW_EVTID_TASK_START_READY
:
409 /* if packet's source core has changed */
411 if (pkt_core_changed
) {
412 /* clone packet with unmodified delta */
415 /* clone packet with modified delta */
416 uint8_t *delta_ptr
= new_delta_buf
;
417 sysview_encode_u32(&delta_ptr
, cmd_data
->sv_acc_time_delta
/*delta has been accumulated above*/);
419 new_delta_len
= delta_ptr
- new_delta_buf
;
421 LOG_DEBUG("sysview: Redirect %d bytes of event %d to dest %d", wr_len
, event_id
, i
);
422 res
= esp32_sysview_write_packet(cmd_data
,
430 /* messages above are cloned to trace files for both cores,
431 * so reset acc time delta, both files have actual delta
433 cmd_data
->sv_acc_time_delta
= 0;
442 int esp32_sysview_process_data(struct esp32_apptrace_cmd_ctx
*ctx
,
443 unsigned int core_id
,
447 struct esp32_sysview_cmd_data
*cmd_data
= ctx
->cmd_priv
;
449 LOG_DEBUG("sysview: Read from target %d bytes [%x %x %x %x]",
456 uint32_t processed
= 0;
457 if (core_id
>= ctx
->cores_num
) {
458 LOG_ERROR("sysview: Invalid core id %d in user block!", core_id
);
461 if (cmd_data
->mcore_format
)
463 if (ctx
->tot_len
== 0) {
464 /* handle sync seq */
465 if (data_len
< SYSVIEW_SYNC_LEN
) {
466 LOG_ERROR("sysview: Invalid init seq len %d!", data_len
);
469 LOG_DEBUG("sysview: Process %d sync bytes", SYSVIEW_SYNC_LEN
);
470 uint8_t sync_seq
[SYSVIEW_SYNC_LEN
] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
471 if (memcmp(data
, sync_seq
, SYSVIEW_SYNC_LEN
) != 0) {
472 LOG_ERROR("sysview: Invalid init seq [%x %x %x %x %x %x %x %x %x %x]",
473 data
[0], data
[1], data
[2], data
[3], data
[4], data
[5], data
[6],
474 data
[7], data
[8], data
[9]);
477 res
= cmd_data
->data_dests
[core_id
].write(cmd_data
->data_dests
[core_id
].priv
,
480 if (res
!= ERROR_OK
) {
481 LOG_ERROR("sysview: Failed to write %u sync bytes to dest %d!",
486 if (!cmd_data
->mcore_format
) {
487 for (unsigned int i
= 0; i
< ctx
->cores_num
; i
++) {
491 cmd_data
->data_dests
[i
].write(cmd_data
->data_dests
[i
].priv
,
494 if (res
!= ERROR_OK
) {
495 LOG_ERROR("sysview: Failed to write %u sync bytes to dest %d!", SYSVIEW_SYNC_LEN
, core_id
? 0 : 1);
500 ctx
->tot_len
+= SYSVIEW_SYNC_LEN
;
501 processed
+= SYSVIEW_SYNC_LEN
;
503 while (processed
< data_len
) {
504 unsigned int pkt_core_id
;
505 uint32_t delta_len
= 0;
506 uint32_t pkt_len
= 0, delta
= 0;
507 uint16_t event_id
= esp_sysview_parse_packet(data
+ processed
,
512 !cmd_data
->mcore_format
);
513 LOG_DEBUG("sysview: Process packet: core %d, %d id, %d bytes [%x %x %x %x]",
520 data
[processed
+ 3]);
521 if (!cmd_data
->mcore_format
) {
522 res
= esp32_sysview_process_packet(ctx
,
532 res
= cmd_data
->data_dests
[0].write(cmd_data
->data_dests
[0].priv
, data
+ processed
, pkt_len
);
533 if (res
!= ERROR_OK
) {
534 LOG_ERROR("sysview: Failed to write %u bytes to dest %d!", pkt_len
, 0);
538 if (event_id
== SYSVIEW_EVTID_TRACE_STOP
)
539 cmd_data
->sv_trace_running
= 0;
540 ctx
->tot_len
+= pkt_len
;
541 processed
+= pkt_len
;
543 LOG_USER("%u ", ctx
->tot_len
);
544 /* check for stop condition */
545 if (ctx
->tot_len
> cmd_data
->apptrace
.skip_len
&&
546 (ctx
->tot_len
- cmd_data
->apptrace
.skip_len
>= cmd_data
->apptrace
.max_len
)) {
548 if (duration_measure(&ctx
->read_time
) != 0) {
549 LOG_ERROR("Failed to stop trace read time measure!");
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)