{"id":3178,"date":"2017-09-07T11:47:18","date_gmt":"2017-09-07T18:47:18","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=3178"},"modified":"2020-06-26T10:08:09","modified_gmt":"2020-06-26T17:08:09","slug":"attaching-to-embedded-code-to-diagnose-delayed-problems","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/arm\/attach\/","title":{"rendered":"Attaching to Embedded Code to Diagnose Delayed Problems"},"content":{"rendered":"<p>This tutorial shows how to use the &#8220;Attach to Running Embedded Firmware&#8221; feature of VisualGDB to diagnose rarely occurring problems in your code that don&#8217;t get easily triggered. We will create a simple program causing the &#8220;division by zero&#8221; error with a 1\/1000 chance, run it without debugger and one the problem happens, will attach VisualGDB and show how to diagnose it.<\/p>\n<p>Before you begin, install VisualGDB 5.3 or later.<\/p>\n<ol>\n<li>Start Visual Studio and open VisualGDB Embedded Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/01-prjname1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3179\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/01-prjname1.png\" alt=\"01-prjname\" width=\"912\" height=\"588\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/01-prjname1.png 912w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/01-prjname1-300x193.png 300w\" sizes=\"(max-width: 912px) 100vw, 912px\" \/><\/a><\/li>\n<li>Proceed with the default selection on the first page:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/02-newmsb.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3180\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/02-newmsb.png\" alt=\"02-newmsb\" width=\"822\" height=\"642\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/02-newmsb.png 822w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/02-newmsb-300x234.png 300w\" sizes=\"(max-width: 822px) 100vw, 822px\" \/><\/a><\/li>\n<li>Select your toolchain and the device. In this tutorial we will use the Nucleo-F410RB board featuring the STM32F410RB device:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/03-device3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3182\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/03-device3.png\" alt=\"03-device\" width=\"822\" height=\"642\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/03-device3.png 822w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/03-device3-300x234.png 300w\" sizes=\"(max-width: 822px) 100vw, 822px\" \/><\/a><\/li>\n<li>We will use the UART_Printf example from ST SDK as a starting point for our demonstration. Select &#8220;Show STM32CubeMX Samples&#8221; and find the UART_Printf example for your board. VisualGDB will automatically filter the examples based on the selected MCU type:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/03a-printf.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3181\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/03a-printf.png\" alt=\"03a-printf\" width=\"822\" height=\"642\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/03a-printf.png 822w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/03a-printf-300x234.png 300w\" sizes=\"(max-width: 822px) 100vw, 822px\" \/><\/a><\/li>\n<li>Connect your board via USB and VisualGDB will automatically recognize it and select the best debug method:\u00a0 <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/04-debug.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3183\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/04-debug.png\" alt=\"04-debug\" width=\"822\" height=\"642\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/04-debug.png 822w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/04-debug-300x234.png 300w\" sizes=\"(max-width: 822px) 100vw, 822px\" \/><\/a><\/li>\n<li>Press &#8220;Finish&#8221; to create the project. Now we will modify the sample program to trigger the error. First, disable the UART parity bit:\n<pre class=\"\">\u00a0\u00a0\u00a0 UartHandle.Init.Parity\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 = UART_PARITY_NONE;<\/pre>\n<p>Then replace the main loop in main() with this:<\/p>\n<pre class=\"\">  \u00a0 SCB-&gt;CCR |= SCB_CCR_DIV_0_TRP_Msk;\r\n\u00a0\u00a0\u00a0 for (int i = 0;;i++)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int value = rand();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int divided = INT32_MAX \/ (value % 1000);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 printf(\"%d =&gt; %d\\r\\n\", i, divided);\r\n\u00a0\u00a0\u00a0 }<\/pre>\n<p>Finally add an implementation of _write() that will direct printf() output to HAL_UART_Transmit():<\/p>\n<pre class=\"\">int _write(int fd, char *pBuffer, int size)\r\n{\r\n\u00a0\u00a0\u00a0 HAL_UART_Transmit(&amp;UartHandle, (uint8_t *)pBuffer, size, 0xFFFF); \r\n\u00a0\u00a0\u00a0 return size;\r\n}<\/pre>\n<p>Note that if it is defined in a C++ file (not Plain C), it would need to be declared with extern &#8220;C&#8221; so that the linker can use it to replace the default implementation.<br \/>\nFinally build the project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/05-build.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3184\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/05-build.png\" alt=\"05-build\" width=\"1313\" height=\"802\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/05-build.png 1313w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/05-build-300x183.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/05-build-1024x625.png 1024w\" sizes=\"(max-width: 1313px) 100vw, 1313px\" \/><\/a><\/li>\n<li>Connect a terminal program (e.g. <a href=\"http:\/\/smartty.sysprogs.com\/\">SmarTTY<\/a>) to the ST-Link COM port and select Debug-&gt;Program and Start Without Debugging in Visual Studio:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/06-program.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3185\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/06-program.png\" alt=\"06-program\" width=\"1313\" height=\"802\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/06-program.png 1313w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/06-program-300x183.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/06-program-1024x625.png 1024w\" sizes=\"(max-width: 1313px) 100vw, 1313px\" \/><\/a><\/li>\n<li>Look in the terminal. It will show several lines of output and will eventually hang:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/07-crash.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3186\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/07-crash.png\" alt=\"07-crash\" width=\"674\" height=\"440\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/07-crash.png 674w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/07-crash-300x196.png 300w\" sizes=\"(max-width: 674px) 100vw, 674px\" \/><\/a>You can try unplugging\/re-plugging the board to the USB or resetting the microcontroller to ensure the problem is always reproduced. As long as the MCU is running the same build of the firmware that the project contains, the steps described below will work.<\/li>\n<li>Now we will attach to the hanging microcontroller and diagnose its state. Select Debug-&gt;Attach to Running Embedded Firmware:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/08-attach.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3187\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/08-attach.png\" alt=\"08-attach\" width=\"1313\" height=\"802\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/08-attach.png 1313w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/08-attach-300x183.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/08-attach-1024x625.png 1024w\" sizes=\"(max-width: 1313px) 100vw, 1313px\" \/><\/a><\/li>\n<li>VisualGDB will attach to it and show that it&#8217;s stuck in HardFault_Handler():<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/09-fault.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3188\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/09-fault.png\" alt=\"09-fault\" width=\"1313\" height=\"802\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/09-fault.png 1313w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/09-fault-300x183.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/09-fault-1024x625.png 1024w\" sizes=\"(max-width: 1313px) 100vw, 1313px\" \/><\/a>The &#8220;Attach to Running Embedded Firmware&#8221; command is supported for ARM, ESP8266 and ESP32 devices and it automatically suppresses FLASH reprogramming and device resetting so that you can see the exact state of the processor the moment you attached to it.<\/li>\n<li>Hard fault could be triggered by several different causes, so you can use the CFSR register in Hardware Registers to see what exactly caused it. In this example the DIVBYZERO field indicates that the error was triggered by attempting to divide by zero:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/10-divbyzero.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3189\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/10-divbyzero.png\" alt=\"10-divbyzero\" width=\"1313\" height=\"802\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/10-divbyzero.png 1313w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/10-divbyzero-300x183.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/10-divbyzero-1024x625.png 1024w\" sizes=\"(max-width: 1313px) 100vw, 1313px\" \/><\/a>Note that normally it would not cause an exception. We had to explicitly enable the exception in the code by setting <strong>DIV_0_TRP <\/strong>in <strong>SCB_CCR<\/strong>.<\/li>\n<li>Click in the &#8220;main()&#8221; entry in Call Stack to go to the location of the error. Hover the mouse over &#8216;value&#8217; to see the value that triggered the error:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/11-value.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3190\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/11-value.png\" alt=\"11-value\" width=\"1313\" height=\"802\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/11-value.png 1313w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/11-value-300x183.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/11-value-1024x625.png 1024w\" sizes=\"(max-width: 1313px) 100vw, 1313px\" \/><\/a><\/li>\n<li>Press Shift-F5 to stop debugging and rewrite the code to fix the problem:\n<pre class=\"\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int value = rand();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int divisor = value % 1000;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (!divisor)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 continue;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 int divided = INT32_MAX \/ divisor;<\/pre>\n<p>Build the program again, but don&#8217;t program it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/12-fix.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3191\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/12-fix.png\" alt=\"12-fix\" width=\"1313\" height=\"802\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/12-fix.png 1313w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/12-fix-300x183.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/12-fix-1024x625.png 1024w\" sizes=\"(max-width: 1313px) 100vw, 1313px\" \/><\/a><\/li>\n<li>Attach to the running firmware again without reprogramming it. See how now VisualGDB displays that the program is stopped in NMI_Handler() that should normally just immediately return:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/13-nmi.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3192\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/13-nmi.png\" alt=\"13-nmi\" width=\"1313\" height=\"802\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/13-nmi.png 1313w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/13-nmi-300x183.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/13-nmi-1024x625.png 1024w\" sizes=\"(max-width: 1313px) 100vw, 1313px\" \/><\/a>This happens because the debugger is using the new build of the program to interpret the contents of the device memory that has the old build. As we have added extra checking code in main(), its size got increased and several other functions got shifted, so the old address of HardFault_Handler() matches the new address of NMI_Handler().<\/li>\n<li>VisualGDB provides a convenient way to diagnose this type of errors. Click &#8220;Verify FLASH memory contents&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/14-verify.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3193\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/14-verify.png\" alt=\"14-verify\" width=\"1313\" height=\"802\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/14-verify.png 1313w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/14-verify-300x183.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/14-verify-1024x625.png 1024w\" sizes=\"(max-width: 1313px) 100vw, 1313px\" \/><\/a><\/li>\n<li>VisualGDB will read the FLASH memory on the device, compare it with the current build and will display a detailed list of differences if there are any:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/15-diffs.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3194\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/15-diffs.png\" alt=\"15-diffs\" width=\"786\" height=\"593\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/15-diffs.png 786w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/15-diffs-300x226.png 300w\" sizes=\"(max-width: 786px) 100vw, 786px\" \/><\/a>The pattern of differences could explain the reason behind the mismatch. E.g. having the FLASH memory filled with 0xFFs would mean that the memory was erased, but not programmed; having zero bits in place of one bits (as if contents of the FLASH was bitwise ANDed with something else) would indicate that FLASH erase was not performed; multiple random differences all across the code typically mean that a wrong version was programmed.<\/li>\n<li>Simply re-program the new firmware to the device to ensure the FLASH memory is updated and it will run without any exceptions:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/16-run.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3195\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/16-run.png\" alt=\"16-run\" width=\"674\" height=\"440\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/16-run.png 674w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/09\/16-run-300x196.png 300w\" sizes=\"(max-width: 674px) 100vw, 674px\" \/><\/a><\/li>\n<li>Starting from VisualGDB 5.5, you can distinguish between starting a new embedded debug session and attaching to running firmware via the <strong>$(DebugMode)<\/strong> variable. VisualGDB will set it to &#8220;Attach&#8221; when attaching and to &#8220;NewInstance&#8221; otherwise. You can use it to run different sets of startup commands, depending on the way the debug session is started. E.g. you can add the following line to VisualGDB Project Properties -&gt; Additional GDB Commands:\n<pre class=\"\">source $(ProjectDir.forwardslashes)\/Startup-$(DebugMode).gdb<\/pre>\n<p>It will run commands from <strong>Startup-NewInstance.gdb<\/strong> file when starting a regular debug session, and commands from <strong>Startup-Attach.gdb<\/strong> otherwise.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use the &#8220;Attach to Running Embedded Firmware&#8221; feature of VisualGDB to diagnose rarely occurring problems<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27],"tags":[53],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3178"}],"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=3178"}],"version-history":[{"count":4,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3178\/revisions"}],"predecessor-version":[{"id":6383,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3178\/revisions\/6383"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=3178"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=3178"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=3178"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}