rtos: add instructions and helper code to make FreeRTOS work again
[openocd.git] / contrib / itmdump.c
1 /*
2 * Copyright (C) 2010 by David Brownell
3 *
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 3 of the License, or (at
7 * your option) any later version.
8 *
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.
13 *
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 */
17
18 /*
19 * Simple utility to parse and dump ARM Cortex-M3 SWO trace output. Once the
20 * mechanisms work right, this information can be used for various purposes
21 * including profiling (particularly easy for flat PC-sample profiles) and
22 * for debugging.
23 *
24 * SWO is the Single Wire Output found on some ARM cores, most notably on the
25 * Cortex-M3. It combines data from several sources:
26 *
27 * - Software trace (ITM): so-called "printf-style" application messaging
28 * using "ITM stimulus ports"; and differential timestamps.
29 * - Hardware trace (DWT): for profiling counters and comparator matches.
30 * - TPIU may issue sync packets.
31 *
32 * The trace data format is defined in Appendix E, "Debug ITM and DWT packet
33 * protocol", of the ARMv7-M Architecture Reference Manual (DDI 0403C). It
34 * is a superset of the ITM data format from the Coresight TRM.
35 *
36 * The trace data has two encodings. The working assumption is that data
37 * gets into this program using the UART encoding.
38 */
39
40 #include <errno.h>
41 #include <libgen.h>
42 #include <stdio.h>
43 #include <stdbool.h>
44 #include <string.h>
45 #include <unistd.h>
46
47
48 /* Example ITM trace word (0xWWXXYYZZ) parsing for task events, sent
49 * on port 31 (Reserved for "the" RTOS in CMSIS v1.30)
50 * WWXX: event code (0..3 pre-assigned, 4..15 reserved)
51 * YY: task priority
52 * ZZ: task number
53 *
54 * NOTE that this specific encoding could be space-optimized; and that
55 * trace data streams could also be history-sensitive.
56 */
57 static void show_task(int port, unsigned data)
58 {
59 unsigned code = data >> 16;
60 char buf[16];
61
62 switch (code) {
63 case 0:
64 strcpy(buf, "run");
65 break;
66 case 1:
67 strcpy(buf, "block");
68 break;
69 case 2:
70 strcpy(buf, "create");
71 break;
72 case 3:
73 strcpy(buf, "destroy");
74 break;
75 /* 4..15 reserved for other infrastructure ops */
76 default:
77 sprintf(buf, "code %d", code);
78 break;
79 }
80 printf("TASK %d, pri %d: %s",
81 (data >> 0) & 0xff,
82 (data >> 8) & 0xff,
83 buf);
84 }
85
86 static void show_reserved(FILE *f, char *label, int c)
87 {
88 unsigned i;
89
90 printf("%s - %#02x", label, c);
91
92 for (i = 0; (c & 0x80) && i < 4; i++) {
93 c = fgetc(f);
94 if (c == EOF) {
95 printf("(ERROR %d - %s) ", errno, strerror(errno));
96 break;
97 }
98 printf(" %#02x", c);
99 }
100
101 printf("\n");
102 }
103
104 static bool read_varlen(FILE *f, int c, unsigned *value)
105 {
106 unsigned size;
107 unsigned char buf[4];
108
109 *value = 0;
110
111 switch (c & 3) {
112 case 3:
113 size = 4;
114 break;
115 case 2:
116 size = 2;
117 break;
118 case 1:
119 size = 1;
120 break;
121 default:
122 printf("INVALID SIZE\n");
123 return false;
124 }
125
126 memset(buf, 0, sizeof buf);
127 if (fread(buf, 1, size, f) != size)
128 goto err;
129
130 *value = (buf[3] << 24)
131 + (buf[2] << 16)
132 + (buf[1] << 8)
133 + (buf[0] << 0);
134 return true;
135
136 err:
137 printf("(ERROR %d - %s)\n", errno, strerror(errno));
138 return false;
139 }
140
141 static void show_hard(FILE *f, int c)
142 {
143 unsigned type = c >> 3;
144 unsigned value;
145 char *label;
146
147 printf("DWT - ");
148
149 if (!read_varlen(f, c, &value))
150 return;
151 printf("%#x", value);
152
153 switch (type) {
154 case 0: /* event counter wrapping */
155 printf("overflow %s%s%s%s%s%s",
156 (value & (1 << 5)) ? "cyc " : "",
157 (value & (1 << 4)) ? "fold " : "",
158 (value & (1 << 3)) ? "lsu " : "",
159 (value & (1 << 2)) ? "slp " : "",
160 (value & (1 << 1)) ? "exc " : "",
161 (value & (1 << 0)) ? "cpi " : "");
162 break;
163 case 1: /* exception tracing */
164 switch (value >> 12) {
165 case 1:
166 label = "entry to";
167 break;
168 case 2:
169 label = "exit from";
170 break;
171 case 3:
172 label = "return to";
173 break;
174 default:
175 label = "?";
176 break;
177 }
178 printf("%s exception %d", label, value & 0x1ff);
179 break;
180 case 2: /* PC sampling */
181 if (c == 0x15)
182 printf("PC - sleep");
183 else
184 printf("PC - %#08x", value);
185 break;
186 case 8: /* data tracing, pc value */
187 case 10:
188 case 12:
189 case 14:
190 printf("Data trace %d, PC %#08x", (c >> 4) & 3, value);
191 /* optionally followed by data value */
192 break;
193 case 9: /* data tracing, address offset */
194 case 11:
195 case 13:
196 case 15:
197 printf("Data trace %d, address offset %#04x",
198 (c >> 4) & 3, value);
199 /* always followed by data value */
200 break;
201 case 16 ... 23: /* data tracing, data value */
202 printf("Data trace %d, ", (c >> 4) & 3);
203 label = (c & 0x8) ? "write" : "read";
204 switch (c & 3) {
205 case 3:
206 printf("word %s, value %#08x", label, value);
207 break;
208 case 2:
209 printf("halfword %s, value %#04x", label, value);
210 break;
211 case 1:
212 printf("byte %s, value %#02x", label, value);
213 break;
214 }
215 break;
216 default:
217 printf("UNDEFINED, rawtype: %x", type);
218 break;
219 }
220
221 printf("\n");
222 return;
223 }
224
225 /*
226 * Table of SWIT (SoftWare InstrumentTation) message dump formats, for
227 * ITM port 0..31 application data.
228 *
229 * Eventually this should be customizable; all usage is application defined.
230 *
231 * REVISIT there can be up to 256 trace ports, via "ITM Extension" packets
232 */
233 struct {
234 int port;
235 void (*show)(int port, unsigned data);
236 } format[] = {
237 { .port = 31, .show = show_task, },
238 };
239
240 static void show_swit(FILE *f, int c)
241 {
242 unsigned port = c >> 3;
243 unsigned value = 0;
244 unsigned i;
245
246 printf("SWIT %u - ", port);
247
248 if (!read_varlen(f, c, &value))
249 return;
250 printf("%#08x", value);
251
252 for (i = 0; i < sizeof(format) / sizeof(format[0]); i++) {
253 if (format[i].port == port) {
254 printf(", ");
255 format[i].show(port, value);
256 break;
257 }
258 }
259
260 printf("\n");
261 return;
262 }
263
264 static void show_timestamp(FILE *f, int c)
265 {
266 unsigned counter = 0;
267 char *label = "";
268 bool delayed = false;
269
270 printf("TIMESTAMP - ");
271
272 /* Format 2: header only */
273 if (!(c & 0x80)) {
274 switch (c) {
275 case 0: /* sync packet -- coding error! */
276 case 0x70: /* overflow -- ditto! */
277 printf("ERROR - %#02x\n", c);
278 break;
279 default:
280 /* synchronous to ITM */
281 counter = c >> 4;
282 goto done;
283 }
284 return;
285 }
286
287 /* Format 1: one to four bytes of data too */
288 switch (c) {
289 default:
290 label = ", reserved control\n";
291 break;
292 case 0xc:
293 /* synchronous to ITM */
294 break;
295 case 0xd:
296 label = ", timestamp delayed";
297 delayed = true;
298 break;
299 case 0xe:
300 label = ", packet delayed";
301 delayed = true;
302 break;
303 case 0xf:
304 label = ", packet and timetamp delayed";
305 delayed = true;
306 break;
307 }
308
309 c = fgetc(f);
310 if (c == EOF)
311 goto err;
312 counter = c & 0x7f;
313 if (!(c & 0x80))
314 goto done;
315
316 c = fgetc(f);
317 if (c == EOF)
318 goto err;
319 counter |= (c & 0x7f) << 7;
320 if (!(c & 0x80))
321 goto done;
322
323 c = fgetc(f);
324 if (c == EOF)
325 goto err;
326 counter |= (c & 0x7f) << 14;
327 if (!(c & 0x80))
328 goto done;
329
330 c = fgetc(f);
331 if (c == EOF)
332 goto err;
333 counter |= (c & 0x7f) << 21;
334
335 done:
336 /* REVISIT should we try to convert from delta values? */
337 printf("+%u%s\n", counter, label);
338 return;
339
340 err:
341 printf("(ERROR %d - %s) ", errno, strerror(errno));
342 goto done;
343 }
344
345 int main(int argc, char **argv)
346 {
347 FILE *f = stdin;
348 int c;
349
350 /* parse arguments */
351 while ((c = getopt(argc, argv, "f:")) != EOF) {
352 switch (c) {
353 case 'f':
354 /* e.g. from UART connected to /dev/ttyUSB0 */
355 f = fopen(optarg, "r");
356 if (!f) {
357 perror(optarg);
358 return 1;
359 }
360 break;
361 default:
362 fprintf(stderr, "usage: %s [-f input]",
363 basename(argv[0]));
364 return 1;
365 }
366 }
367
368 /* Parse data ... records have a header then data bytes.
369 * NOTE: we assume getc() deals in 8-bit bytes.
370 */
371 bool overflow = false;
372
373 while ((c = getc(f)) != EOF) {
374
375 /* Sync packet ... 7 zeroes, 0x80 */
376 if (c == 0) {
377 int i;
378
379 for (i = 0; i < 6; i++) {
380 c = fgetc(f);
381 if (c == EOF)
382 break;
383 if (c != 0)
384 goto bad_sync;
385 }
386 c = fgetc(f);
387 if (c == 0x80) {
388 printf("SYNC\n");
389 continue;
390 }
391 bad_sync:
392 printf("BAD SYNC\n");
393 continue;
394 }
395
396 /* Overflow packet */
397 if (c == 0x70) {
398 /* REVISIT later, report just what overflowed!
399 * Timestamp and SWIT can happen. Non-ITM too?
400 */
401 overflow = true;
402 printf("OVERFLOW ...\n");
403 continue;
404 }
405 overflow = false;
406
407 switch (c & 0x0f) {
408 case 0x00: /* Timestamp */
409 show_timestamp(f, c);
410 break;
411 case 0x04: /* "Reserved" */
412 show_reserved(f, "RESERVED", c);
413 break;
414 case 0x08: /* ITM Extension */
415 /* FIXME someday, handle these ... */
416 show_reserved(f, "ITM EXT", c);
417 break;
418 case 0x0c: /* DWT Extension */
419 show_reserved(f, "DWT EXT", c);
420 break;
421 default:
422 if (c & 4)
423 show_hard(f, c);
424 else
425 show_swit(f, c);
426 break;
427 }
428
429 }
430
431 return 0;
432 }

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)