{"id":8530,"date":"2023-10-18T08:43:51","date_gmt":"2023-10-18T15:43:51","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=8530"},"modified":"2023-10-18T08:43:51","modified_gmt":"2023-10-18T15:43:51","slug":"using-backtrack-tracing-to-debug-intermittent-problems","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/tracing\/embedded\/traceback\/","title":{"rendered":"Using Backtrack Tracing to Debug Intermittent Problems"},"content":{"rendered":"<p>This tutorial shows how to use <a href=\"https:\/\/visualgdb.com\/documentation\/tracing\/\">Live Tracing<\/a> in the the circular buffer (backtrack) mode to record what happened just before a rarely occurring problem without having to slow down the target and capture its entire program flow.<\/p>\n<p>We will create a basic application using 2 FreeRTOS threads to trigger a race condition, will create tracepoints in the relevant parts of the code, and then once the problem triggers, will use the recorded data to step back in time and see what happened just before the crash.<\/p>\n<ol>\n<li>Start Visual Studio and open the VisualGDB Embedded Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/01-emb-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8531\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/01-emb-1.png\" alt=\"\" width=\"890\" height=\"625\" \/><\/a><\/li>\n<li>Enter the name for the new project and the directory where you would like to create it: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/02-circular.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8532\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/02-circular.png\" alt=\"\" width=\"890\" height=\"625\" \/><\/a><\/li>\n<li>Proceed with the default project type (Embedded Application -&gt; Advanced CMake): <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/03-cmake-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8533\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/03-cmake-1.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Select the device you would like to target: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/04-dev-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8534\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/04-dev-1.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Pick the<strong> &#8220;LEDBlink (FreeRTOS)&#8221;<\/strong> template and click &#8220;Next&#8221; to go to the debug settings page: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/05-rtos.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8535\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/05-rtos.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Select the debug settings matching your setup, make sure the software tracing is enabled and click &#8220;Finish&#8221; to generate the project: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/06-debug-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8536\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/06-debug-2.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Once the project is created, replace the contents of <strong>LED_Thread1()<\/strong> and <strong>LED_Thread2()<\/strong> functions with the following code:\n<pre class=\"\">volatile int g_Counter1, g_Counter2, g_Sum;\r\n\r\nstatic void LED_Thread1(void const *argument)\r\n{\r\n    for (;;)\r\n    {\r\n    \tint tmp = g_Counter1;\r\n    \tg_Counter1 = tmp + 1;\r\n    \ttmp = g_Sum;\r\n    \tg_Sum = tmp + 1;\r\n    }\r\n}\r\n\r\nstatic void LED_Thread2(void const *argument)\r\n{\r\n    for (;;)\r\n    {\r\n        int tmp = g_Counter2;\r\n    \tg_Counter2 = tmp + 1;\r\n    \ttmp = g_Sum;\r\n    \tg_Sum = tmp + 1;\r\n    }\r\n}<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/07-build.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8537\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/07-build.png\" alt=\"\" width=\"1258\" height=\"837\" \/><\/a><\/li>\n<li>Each thread increments its own counter (<strong>g_Counter1<\/strong>\/<strong>g_Counter2<\/strong>) and a shared counter called <strong>g_Sum<\/strong>. Because of the race condition, the value of <strong>g_Sum<\/strong> will be drifting below the sum of <strong>g_Counter1<\/strong> + <strong>g_Counter2. <\/strong>Try running the program for some time and checking the difference expression: <strong>g_Counter 1 + g_Counter2 &#8211; g_Sum<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/08-values.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8538\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/08-values.png\" alt=\"\" width=\"1258\" height=\"837\" \/><\/a>Note that it would happen even when using the &#8220;<strong>g_CounterX++<\/strong>&#8221; syntax, but we used explicit reading and writing for clarity.<\/li>\n<li>Set tracepoints on each of the 4 lines in each thread and configure them to capture the values read in each line. VisualGDB will manage to capture them, however most of the events will be dropped to avoid slowing down the target:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/09-dropped-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8546\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/09-dropped-1.png\" alt=\"\" width=\"1258\" height=\"837\" \/><\/a><\/li>\n<li>Add a check to both threads that will trigger a breakpoint if the values of <strong>g_Sum<\/strong> and the counters drift away too far:\n<pre class=\"\">    \tif (((g_Counter1 + g_Counter2) - g_Sum) &gt; 1)\r\n        \tasm(\"bkpt 255\");<\/pre>\n<p>Note how the last event recorded via regular tracing will contain an outdated value of <strong>g_Sum<\/strong>. This happens because tracing every line of a tight loop creates a lot of tracing data (megabytes per second) and the SWD debugger would not keep up with reading it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/10-mismatch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8540\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/10-mismatch.png\" alt=\"\" width=\"1258\" height=\"837\" \/><\/a><\/li>\n<li>Go to the VisualGDB project Properties and switch the software tracing mode to &#8220;Overwrite oldest events&#8221;: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/11-overwrite.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8541\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/11-overwrite.png\" alt=\"\" width=\"1054\" height=\"693\" \/><\/a>This way, VisualGDB will keep writing the trace into a circular buffer inside the target and will never wait for the debugger to read it.<\/li>\n<li>Once a breakpoint triggers, VisualGDB will read the data backwards and recover the last events recorded in it. The data in the last recorded event will match the variable values observed via Watch:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/12-match-3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8549\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/12-match-3.png\" alt=\"\" width=\"1258\" height=\"833\" \/><\/a><\/li>\n<li>Use the navigation buttons to walk back to the previous events and see what happened before the breakpoint got triggered:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/13-back.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8550\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/13-back.png\" alt=\"\" width=\"1258\" height=\"833\" \/><\/a>You will see that just before the failing check (when <strong>g_Sum<\/strong> was <strong>21<\/strong>), <strong>Thread2<\/strong> set it to <strong>40 + 1<\/strong>.<\/li>\n<li>Click on the &#8220;21 events&#8221; label near the <strong>g_Sum<\/strong> assignment in <strong>Thread1<\/strong>. VisualGDB will load the last event recorded there (#103), showing that <strong>tmp<\/strong> had a value of 20 back then:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/back.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8551\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/back.png\" alt=\"\" width=\"1258\" height=\"835\" \/><\/a>This explains what exactly happened before the crash:\n<ol>\n<li><strong>LED_Thread1<\/strong> started setting <strong>g_Sum<\/strong> to <strong>21 <\/strong>[event #103].<\/li>\n<li>FreeRTOS switched to <strong>LED_Thread2.<\/strong><\/li>\n<li><strong>LED_Thread2<\/strong> ran a few iterations, advancing sum all the way to 41 [event #207].<\/li>\n<li>FreeRTOS switched back to <strong>LED_Thread1<\/strong>.<\/li>\n<li><strong>LED_Thread1<\/strong> finished writing 21 to <strong>g_Sum<\/strong>, effectively rolling it back by 20.<\/li>\n<\/ol>\n<\/li>\n<li>You can easily collect the current thread value and thread switches via Live Tracing. Select all tracepoints in the Tracepoints window and check pxCurrentTCB inside the view to begin tracing it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/14-tcb-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8554\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/14-tcb-1.png\" alt=\"\" width=\"1258\" height=\"833\" \/><\/a><\/li>\n<li>Add another tracepoint in <strong>tasks.c<\/strong> on the <strong>traceTASK_SWITCHED_IN()<\/strong> line inside <strong>vTaskSwitchContext()<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/15-switch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8555\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/15-switch.png\" alt=\"\" width=\"1258\" height=\"833\" \/><\/a><\/li>\n<li>VisualGDB will now show how <strong>pxCurrentTCB<\/strong> got changed between the events, and will even capture the exact moment of the switch:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/16-switched.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8556\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/16-switched.png\" alt=\"\" width=\"1258\" height=\"835\" \/><\/a><\/li>\n<li>If you selected to trace additional fields of <strong>pxCurrentTCB<\/strong> in the task switch tracepoint, you can see the state of the thread that was just switching in (e.g. its stack pointer, number of held mutexes, etc): <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/stack-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8558\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/10\/stack-1.png\" alt=\"\" width=\"1258\" height=\"833\" \/><\/a>Live Tracing is very flexible &#8211; you can record the state of any object (e.g. custom mutex or some variables in your code) at any point in time (thread switches, interrupts, any other function calls or source lines being executed) and analyze it when you need it.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use Live Tracing in the the circular buffer (backtrack) mode to record what happened just<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[247],"tags":[67,248,204,61],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8530"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=8530"}],"version-history":[{"count":2,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8530\/revisions"}],"predecessor-version":[{"id":8560,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8530\/revisions\/8560"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=8530"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=8530"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=8530"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}