{"id":649,"date":"2024-03-01T13:12:50","date_gmt":"2024-03-01T12:12:50","guid":{"rendered":"https:\/\/redero.fr\/?p=649"},"modified":"2026-02-11T17:43:29","modified_gmt":"2026-02-11T16:43:29","slug":"tracing-with-no-money-no-hardware-no-skills","status":"publish","type":"post","link":"https:\/\/redero.fr\/?p=649&lang=en","title":{"rendered":"Tracing with no money, no hardware, no skills"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I needed some debug and tracing information on Zephyr RTOS. It was a bit of a struggle, but I did retrieve some useful information, so here is a compilation of my findings about tracing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Disclaimer: First version for this was written on Zephyr V3.6. I updated the scripts for V4.1. If you are me from the future, check your software version first.<\/p>\n\n\n\n\n\n<h2 class=\"wp-block-heading\">What does it do<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Traces only export data from the kernel itself, namely threads, semaphores, and interrupts. It won\u2019t trace functions, so it will mostly be useful for timing debugging, typically getting a view on how much time is spent in idle thread versus work threads.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There is a very useful blog post explaining how to add custom traces to functions, but it is quite heavy work:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/jonathan.rico.live\/blog\/2023-11-13\/\">https:\/\/jonathan.rico.live\/blog\/2023-11-13\/<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to set it up<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In my case, I have an ST-Link debugger. There are some more advanced trace options with Segger chips, but I will have to use the most basic features:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CTF format is Common Trace Files format, a quite crude but efficient way to pack up trace data in a binary file.<\/li>\n\n\n\n<li>Backend RAM means that the trace will not be sent through UART, or USB, but will be recorded into a RAM buffer. The total size is set by CONFIG_RAM_TRACING_BUFFER_SIZE. I chose the max value I could, 65536. And since we are writing directly to RAM, it should be fast enough to avoid disrupting the program execution.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Tracing is activated in prj.conf:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CONFIG_TRACING=y\nCONFIG_TRACING_CTF=y\nCONFIG_TRACING_BACKEND_RAM=y\nCONFIG_TRACING_BUFFER_SIZE=2048\nCONFIG_RAM_TRACING_BUFFER_SIZE=65536\nCONFIG_TRACING_SYNC=y<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You can also toggle trace types on or off:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CONFIG_TRACING_ISR=n\nCONFIG_TRACING_SEMAPHORE=y<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After building, you can check the ram buffer was indeed created in build\/zephyr\/zephyr.map:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> .bss.ram_tracing\n    0x0000000020001964     0x1000 zephyr\/libzephyr.a \n    0x0000000020001964                ram_tracing<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">How to retrieve your RAM buffer<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Well, you will need GDB, and dump the trace with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>(gdb) dump binary memory data\/mytrace.ctf ram_tracing ram_tracing+65536<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">But wait, is this buffer circular, how do I know where I am? The answer is: this buffer just records everything since the start of program and stops when the buffer is full. If you need startup data, it\u2019s perfect&#8230; but if you don\u2019t, keep reading.<\/p>\n\n\n\n<div class=\"wp-block-group has-global-padding is-layout-constrained wp-container-core-group-is-layout-18c100bf wp-block-group-is-layout-constrained\">\n<div class=\"tenor-gif-embed\" data-postid=\"21287956\" data-share-method=\"host\" data-aspect-ratio=\"1\" data-width=\"100%\"><a href=\"https:\/\/tenor.com\/view\/funny-christine-is-very-humorous-gif-21287956\">Funny Christine GIF<\/a>from <a href=\"https:\/\/tenor.com\/search\/funny-gifs\">Funny GIFs<\/a><\/div> <script type=\"text\/javascript\" async src=\"https:\/\/tenor.com\/embed.js\"><\/script>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">How to choose what to trace<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The \u00ab\u00a0buffer full\u00a0\u00bb event is handled in tracing_backend_ram.c:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>zephyr\/subsys\/tracing\/tracing_backend_ram.c<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">At this point, the pos cursor reach its max value and we set buffer full to true.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We can use GDB to force those variables back to pristine state:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>(gdb) set variable pos=0\n(gdb) set variable buffer_full=0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For instance, to get an infinite buffer retrieval, it is possible to break when buffer is full, download, and reset variables. You need to have a folder called \u00ab\u00a0data\u00a0\u00bb in the  path from where you are calling gdb.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>(gdb) break tracing_backend_ram.c:27\n(gdb) continue\n(gdb) dump binary memory data\/mytrace.ctf ram_tracing ram_tracing+65536\n(gdb) set variable pos=0\n(gdb) set variable buffer_full=0\n(gdb) continue<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Or, it is also possible to break before something interesting happens, reset variables, and break again after the something.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And, since I am ashamed of nothing, I wrote a script for that:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/everedero\/misc_scripts\/blob\/main\/script.gdb\">https:\/\/github.com\/everedero\/misc_scripts\/blob\/main\/script.gdb<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>(gdb) source script.gdb<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For complete download:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>(gdb) dltrace<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For tracing between two points:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>(gdb) tracebetween main.c:331 main.c:333<\/code><\/pre>\n\n\n\n<div class=\"wp-block-group has-global-padding is-layout-constrained wp-container-core-group-is-layout-18c100bf wp-block-group-is-layout-constrained\">\n<div class=\"tenor-gif-embed\" data-postid=\"3807241812430059413\" data-share-method=\"host\" data-aspect-ratio=\"0.9\" data-width=\"100%\"><a href=\"https:\/\/tenor.com\/view\/qeliameow-cat-paw-cats-paw-dance-gif-3807241812430059413\">Qeliameow Cat GIF<\/a>from <a href=\"https:\/\/tenor.com\/search\/qeliameow-gifs\">Qeliameow GIFs<\/a><\/div> <script type=\"text\/javascript\" async src=\"https:\/\/tenor.com\/embed.js\"><\/script>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Update:<\/strong> In upcoming versions (&gt; 3.6.0) it will be possible to reset the RAM content by calling init().<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to convert traces<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">CTF to text with babeltrace2<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You got yourself a bunch of bytes, awesome. But how to convert it to something useful?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, fun fact, CTF format is not complete without a \u00ab\u00a0metadata\u00a0\u00bb file which describes the CTF packets formats. In order to decypher the CTF file, it is necessary to put it in the same folder as its metadata file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>data\n\u251c\u2500\u2500 mytrace.ctf\n\u251c\u2500\u2500 metadata<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Zephyr provides its metadata file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cp ~\/zephyrproject\/zephyr\/subsys\/tracing\/ctf\/tsdl\/metadata .\/data<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now, a parser is required. I chose babeltrace2 to simply convert ctf files to text.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To install babeltrace2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-add-repository ppa:lttng\/ppa\nsudo apt-get update\nsudo apt-get install babeltrace2 libbabeltrace2-dev<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To convert the CTF to text:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>babeltrace2 convert --component=ctf:source.ctf.fs --params='inputs=&#091;\"data\"]' --component=muxer:filter.utils.muxer --component=pretty:sink.text.pretty &gt; trace.txt<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This takes the data folder as input, and converts it from \u00ab\u00a0ctf.fs\u00a0\u00bb to \u00ab\u00a0text.pretty\u00a0\u00bb. Syntax looks like GStreamer CLI, and I have always been scared of GStreamer CLI.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Since we downloaded the full buffer with potential 0-padding or remaining data from previous iteration, babeltrace2 will complain that it cannot parse the end of the file.<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>02-26 13:36:46.555 24379 24379 E PLUGIN\/CTF\/MSG-ITER set_current_event_class@msg-iter.c:1276 &#091;ctf] No event class with ID of event class ID to use in stream class: msg-it-addr=0x55bd46d4e850, stream-class-id=0, event-class-id=0, trace-cla\nss-addr=0x55bd46cd1af0\n02-26 13:36:46.555 24379 24379 E PLUGIN\/CTF\/MSG-ITER ctf_msg_iter_get_next_message@msg-iter.c:2897 &#091;ctf] Cannot handle state: msg-it-addr=0x55bd46d4e850, state=AFTER_EVENT_HEADER\n02-26 13:36:46.555 24379 24379 E PLUGIN\/SRC.CTF.FS ctf_fs_iterator_next_one@fs.c:108 &#091;ctf] Failed to get next message from CTF message iterator.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is what happens with 0-paddings: stream-class-id=0 and event-class-id=0 suggests that it could only find zeros instead of valid classes defined by the metadata file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But it works all right, it&rsquo;s just like me on roller skates: I don&rsquo;t know how to brake, so I crash into lamp posts instead.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Result<\/h4>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>&#091;01:00:02.724926184] (+0.000004238) semaphore_give_enter: { id = 536871028 }\n&#091;01:00:02.724930250] (+0.000004066) semaphore_give_exit: { id = 536871028 }\n&#091;01:00:02.724935964] (+0.000005714) semaphore_take_enter: { id = 536871028, timeout = 4294967196 }\n&#091;01:00:02.724940398] (+0.000004434) semaphore_take_exit: { id = 536871028, timeout = 4294967196, ret = 0 }\n&#091;01:00:02.724948363] (+0.000007965) semaphore_take_enter: { id = 536871048, timeout = 200000 }\n&#091;01:00:02.724952809] (+0.000004446) semaphore_take_blocking: { id = 536871048, timeout = 200000 }\n&#091;01:00:02.724963767] (+0.000010958) isr_enter: \n&#091;01:00:02.724971285] (+0.000007518) isr_exit: \n&#091;01:00:02.724975517] (+0.000004232) isr_enter: \n&#091;01:00:02.724982285] (+0.000006768) isr_exit: \n&#091;01:00:02.724986523] (+0.000004238) isr_enter: \n&#091;01:00:02.724993285] (+0.000006762) isr_exit: \n&#091;01:00:02.724997523] (+0.000004238) isr_enter: \n&#091;01:00:02.725006386] (+0.000008863) semaphore_give_enter: { id = 536871048 }\n&#091;01:00:02.725014005] (+0.000007619) semaphore_give_exit: { id = 536871048 }\n&#091;01:00:02.725018375] (+0.000004370) isr_exit: \n&#091;01:00:02.725021857] (+0.000003482) isr_enter: \n&#091;01:00:02.725028363] (+0.000006506) semaphore_give_enter: { id = 536871048 }\n&#091;01:00:02.725033166] (+0.000004803) semaphore_give_exit: { id = 536871048 }\n&#091;01:00:02.725036809] (+0.000003643) isr_exit: \n&#091;01:00:02.725042505] (+0.000005696) thread_switched_out: { thread_id = 536871360, name = \"main\" }\n&#091;01:00:02.725052303] (+0.000009798) thread_switched_in: { thread_id = 536871360, name = \"main\" }\n&#091;01:00:02.725057720] (+0.000005417) semaphore_take_exit: { id = 536871048, timeout = 200000, ret = 0 }\n&#091;01:00:02.725061952] (+0.000004232) semaphore_give_enter: { id = 536871028 }\n&#091;01:00:02.725066005] (+0.000004053) semaphore_give_exit: { id = 536871028 }\n&#091;01:00:02.725072910] (+0.000006905) semaphore_take_enter: { id = 536871028, timeout = 4294967196 }\n&#091;01:00:02.725077351] (+0.000004441) semaphore_take_exit: { id = 536871028, timeout = 4294967196, ret = 0 }\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u00ab\u00a0id\u00a0\u00bb gives you a RAM address, you can use the GDB session to find what lives here:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>(gdb) x \/1x 536871012\n0x20000064 &lt;spi_stm32_dev_data_0+16&gt;:   0x20000064<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>(gdb) print spi_stm32_dev_data_0 \n$1 = {ctx = {config = 0x8007d40 &lt;ili9xxx_config_0+8&gt;, owner = 0x0, cs_gpios = 0x8008028 &lt;__compound_literal.0&gt;, num_cs_gpios = 1, <strong>lock = {wait_q = {waitq = {{head = 0x20000064<\/strong> &lt;spi_stm32_dev_data_0+16&gt;, next = 0x20000064 &lt;spi_stm32_dev_data_0+16&gt;}, {tail = 0x20000064 &lt;spi_stm32_dev_data_0+16&gt;, prev = 0x20000064 &lt;spi_stm32_dev_data_0+16&gt;}}}, count = 1, limit = 1, _obj_track_next = 0x0}, sync = {wait_q = {waitq = {{head = 0x20000078 &lt;spi_stm32_dev_data_0+36&gt;, next = 0x20000078 &lt;spi_stm32_dev_data_0+36&gt;}, {tail = 0x20000078 &lt;spi_stm32_dev_data_0+36&gt;, prev = 0x20000078 &lt;spi_stm32_dev_data_0+36&gt;}}}, count = 0, limit = 1, _obj_track_next = 0x0}, sync_status = 0, current_tx = 0x200119b8 &lt;z_main_stack+888&gt;, tx_count = 0, current_rx = 0x0, rx_count = 0, tx_buf = 0x0, tx_len = 0, rx_buf = 0x0, rx_len = 0}}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Some of those addresses can also be recovered from the zephyr.map file, here with a semaphore with id=536936612=0x200100a4: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -rnw .\/build\/zephyr\/zephyr.map -e \"0x.*200100a4\"<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>2706:k_sem_area 0x00000000200100a4 0x28 load address 0x0000000008004cfc\n2707: 0x00000000200100a4 _k_sem_list_start = .\n2710: 0x00000000200100a4 0x14 app\/libapp.a(main.c.obj)\n2711: 0x00000000200100a4 threadA_sem<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">In-tree CTF parsing script<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">There is a parsing script in Zephyr directory:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/scripts\/tracing\/parse_ctf.py<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">It is calling BabelTrace2 via its Python bindings. It also has the same \u00ab\u00a0there\u2019s an error, just ignore it\u00a0\u00bb issue. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/everedero\/zephyr\/tree\/eve\/trace_experiments\">https:\/\/github.com\/everedero\/zephyr\/tree\/eve\/trace_experiments<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python3 ..\/scripts\/tracing\/parse_ctf.py -t data &gt; trace.txt<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Result<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Example trace with the sample\/subsys\/tracing directory, using a custom RAM trace config (prj_ram.conf). It is slightly more readable, but does not show all the fields.<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>1970-01-01 01:00:00.005947 (+0.000000 s): thread_create: thread_a\n1970-01-01 01:00:00.005954 (+0.000007 s): thread_info (Stack size: 2048)\n1970-01-01 01:00:00.005977 (+0.000023 s): thread_switched_out: main\n1970-01-01 01:00:00.005991 (+0.000013 s): thread_switched_in: thread_a\n1970-01-01 01:00:00.006003 (+0.000012 s): thread_create: unknown\n1970-01-01 01:00:00.006010 (+0.000007 s): thread_info (Stack size: 2048)\n1970-01-01 01:00:00.006024 (+0.000014 s): thread_name_set\n1970-01-01 01:00:00.006032 (+0.000008 s): semaphore_take_enter\n1970-01-01 01:00:00.006038 (+0.000006 s): semaphore_take_exit\n1970-01-01 01:00:00.009628 (+0.003590 s): thread_switched_out: thread_a\n1970-01-01 01:00:00.009641 (+0.000013 s): thread_switched_in: thread_b\n1970-01-01 01:00:00.009649 (+0.000008 s): semaphore_take_enter\n1970-01-01 01:00:00.009656 (+0.000006 s): semaphore_take_blocking\n1970-01-01 01:00:00.009668 (+0.000013 s): thread_switched_out: thread_b\n1970-01-01 01:00:00.009682 (+0.000013 s): thread_switched_in: idle\n1970-01-01 01:00:00.009690 (+0.000008 s): idle\n1970-01-01 01:00:00.087132 (+0.077442 s): idle\n1970-01-01 01:00:00.164637 (+0.077505 s): idle\n&#091;...]<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">CTF to Google Perfetto CTF<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In order to be displayed in Perfetto, traces have to be converted to a specific JSON format.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The ctf2ctf.py converter exists in an <a href=\"https:\/\/github.com\/everedero\/zephyr\/tree\/ctf2ctf_4.1\">unmerged branch here<\/a> and is also described in the same blog post: <a href=\"https:\/\/jonathan.rico.live\/blog\/2023-11-13\/\">https:\/\/jonathan.rico.live\/blog\/2023-11-13\/<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python3 ctf2ctf.py -t .\/data\/<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">It ends with a \u00ab\u00a0Trace does not terminate cleanly\u00a0\u00bb message, because of the exact same issue as before, but still outputs an out.json file.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Result<\/h4>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>\"traceEvents\": &#091;{\"pid\": 0, \"tid\": 0, \"name\": \"thread_create\", \"ph\": \"i\", \"ts\": 5946.912, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 0, \"name\": \"thread_info\", \"ph\": \"i\", \"ts\": 5954.342, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 536937200, \"name\": \"running\", \"ph\": \"E\", \"ts\": 5977.495, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 536936656, \"name\": \"running\", \"ph\": \"B\", \"ts\": 5990.782, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 0, \"name\": \"thread_create\", \"ph\": \"i\", \"ts\": 6003.111, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 0, \"name\": \"thread_info\", \"ph\": \"i\", \"ts\": 6009.976, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 0, \"name\": \"thread_name_set\", \"ph\": \"i\", \"ts\": 6024.296, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 3, \"name\": \"semaphore_take_enter\", \"ph\": \"i\", \"ts\": 6032.236, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 3, \"name\": \"semaphore_take_exit\", \"ph\": \"i\", \"ts\": 6038.069, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 536936656, \"name\": \"running\", \"ph\": \"E\", \"ts\": 9628.083, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 536936832, \"name\": \"running\", \"ph\": \"B\", \"ts\": 9641.314, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 3, \"name\": \"semaphore_take_enter\", \"ph\": \"i\", \"ts\": 9649.462, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 3, \"name\": \"semaphore_take_blocking\", \"ph\": \"i\", \"ts\": 9655.773, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 536936832, \"name\": \"running\", \"ph\": \"E\", \"ts\": 9668.462, \"args\": {\"dummy\": 0}},\n{\"pid\": 0, \"tid\": 536937024, \"name\": \"running\", \"ph\": \"B\", \"ts\": 9681.745, \"args\": {\"dummy\": 0}},\n&#091;...]<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Trace GUI<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You can also download and use a GUI to visualize the trace.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I tried two options:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tracecompass<\/li>\n\n\n\n<li>Perfetto<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Tracecompass<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Tracecompass is open-source (EPL V2 license), it is based on Eclipse, hence on Java, except I don\u2019t have the right Java version, oh well.<\/p>\n\n\n\n<div class=\"wp-block-group has-global-padding is-layout-constrained wp-container-core-group-is-layout-18c100bf wp-block-group-is-layout-constrained\">\n<div class=\"tenor-gif-embed\" data-postid=\"8523870683176515378\" data-share-method=\"host\" data-aspect-ratio=\"1\" data-width=\"100%\"><a href=\"https:\/\/tenor.com\/view\/sad-cat-black-gif-8523870683176515378\">Sad Cat GIF<\/a>from <a href=\"https:\/\/tenor.com\/search\/sad-gifs\">Sad GIFs<\/a><\/div> <script type=\"text\/javascript\" async src=\"https:\/\/tenor.com\/embed.js\"><\/script>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">After a bit of fiddling around, I found a suitable Java for it, and I cannot remember how.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Result<\/h4>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6a1413900c86b&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6a1413900c86b\" class=\"wp-block-image size-full wp-duotone-unset-1 wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"797\" height=\"971\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/redero.fr\/wp-content\/uploads\/2024\/02\/tracecompass.png\" alt=\"\" class=\"wp-image-656\" srcset=\"https:\/\/redero.fr\/wp-content\/uploads\/2024\/02\/tracecompass.png 797w, https:\/\/redero.fr\/wp-content\/uploads\/2024\/02\/tracecompass-246x300.png 246w, https:\/\/redero.fr\/wp-content\/uploads\/2024\/02\/tracecompass-768x936.png 768w\" sizes=\"auto, (max-width: 797px) 100vw, 797px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Now, it would need a plugin to display the start and end of an event and create advanced visualizations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">An example of such scripts for FreeRTOS: <a href=\"https:\/\/github.com\/gpollo\/freertos-barectf\/tree\/master\/scripts\">https:\/\/github.com\/gpollo\/freertos-barectf\/tree\/master\/scripts<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The excellent Guillaume Redero made an update to the parser, you can find it here: <a href=\"https:\/\/github.com\/ostrodivski\/zephyr-tracecompass-parser\" target=\"_blank\" rel=\"noreferrer noopener\">Zephyr Tracecompass parser project<\/a>. This is what it looks like:<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6a1413900cff2&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6a1413900cff2\" class=\"wp-block-image size-large wp-duotone-unset-2 wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"167\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/redero.fr\/wp-content\/uploads\/2024\/03\/tracecompass_new-1024x167.png\" alt=\"\" class=\"wp-image-1334\" srcset=\"https:\/\/redero.fr\/wp-content\/uploads\/2024\/03\/tracecompass_new-1024x167.png 1024w, https:\/\/redero.fr\/wp-content\/uploads\/2024\/03\/tracecompass_new-300x49.png 300w, https:\/\/redero.fr\/wp-content\/uploads\/2024\/03\/tracecompass_new-768x125.png 768w, https:\/\/redero.fr\/wp-content\/uploads\/2024\/03\/tracecompass_new.png 1139w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Some additional resource about Tracecompass scripting:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/tuxology\/tracevizlab\/tree\/master\/labs\/204-scripted-analysis-for-custom-instrumentation\" target=\"_blank\" rel=\"noreferrer noopener\">Scripted Tracecompass analysis by Tuxology<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/dorsal-lab\/EclipseTrainingSlides\/blob\/master\/tracecompass\/slides.md\" target=\"_blank\" rel=\"noreferrer noopener\">Tracecompass training by Dorsal Lab<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Perfetto<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Perfetto is a web-based UI from Google, and it is open-source, with Apache 2.0 license.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The output json file generated by ctf2ctf.py can be opened in <a href=\"https:\/\/ui.perfetto.dev\">https:\/\/ui.perfetto.dev<\/a>:<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6a1413900d77c&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6a1413900d77c\" class=\"wp-block-image size-full wp-duotone-unset-3 wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1003\" height=\"314\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/redero.fr\/wp-content\/uploads\/2024\/05\/perfetto.png\" alt=\"\" class=\"wp-image-774\" srcset=\"https:\/\/redero.fr\/wp-content\/uploads\/2024\/05\/perfetto.png 1003w, https:\/\/redero.fr\/wp-content\/uploads\/2024\/05\/perfetto-300x94.png 300w, https:\/\/redero.fr\/wp-content\/uploads\/2024\/05\/perfetto-768x240.png 768w\" sizes=\"auto, (max-width: 1003px) 100vw, 1003px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">GDB scripting, binary file formats, GStreamer-like CLIs, Java version issues&#8230; there are lots of things I struggled with. But I am glad I made it this far and I can now use some tracing when needed!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And if you have any updates or projects, come find me on zephyrproject Discord channel #tracing.<\/p>\n\n\n\n<div class=\"wp-block-group has-global-padding is-layout-constrained wp-container-core-group-is-layout-18c100bf wp-block-group-is-layout-constrained\">\n<div class=\"tenor-gif-embed\" data-postid=\"17569677\" data-share-method=\"host\" data-aspect-ratio=\"1.07407\" data-width=\"100%\"><a href=\"https:\/\/tenor.com\/view\/cat-disapear-cat-snow-cat-jump-fail-cat-fun-jump-cats-gif-17569677\">Cat Disapear Cat Snow GIF<\/a>from <a href=\"https:\/\/tenor.com\/search\/cat+disapear-gifs\">Cat Disapear GIFs<\/a><\/div> <script type=\"text\/javascript\" async src=\"https:\/\/tenor.com\/embed.js\"><\/script>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>An unsettling adventure in the realm of tracing. Including frequent cat gif breaks, for relaxation purposes.<\/p>\n","protected":false},"author":1,"featured_media":659,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49],"tags":[64,47],"class_list":["post-649","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog_en","tag-trace-en","tag-zephyr-en"],"_links":{"self":[{"href":"https:\/\/redero.fr\/index.php?rest_route=\/wp\/v2\/posts\/649","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/redero.fr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/redero.fr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/redero.fr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/redero.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=649"}],"version-history":[{"count":52,"href":"https:\/\/redero.fr\/index.php?rest_route=\/wp\/v2\/posts\/649\/revisions"}],"predecessor-version":[{"id":1883,"href":"https:\/\/redero.fr\/index.php?rest_route=\/wp\/v2\/posts\/649\/revisions\/1883"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/redero.fr\/index.php?rest_route=\/wp\/v2\/media\/659"}],"wp:attachment":[{"href":"https:\/\/redero.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=649"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/redero.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=649"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/redero.fr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=649"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}