{"id":8618,"date":"2023-12-13T08:31:51","date_gmt":"2023-12-13T16:31:51","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=8618"},"modified":"2023-12-13T08:31:51","modified_gmt":"2023-12-13T16:31:51","slug":"troubleshooting-contact-bounce-timing-with-software-tracing","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/tracing\/embedded\/bounce\/","title":{"rendered":"Troubleshooting Contact Bounce Timing with Software Tracing"},"content":{"rendered":"<p>This tutorial shows how to use <a href=\"https:\/\/visualgdb.com\/documentation\/tracing\/\">Software Tracing<\/a> to troubleshoot hardware glitches that happen sporadically and are too fast to analyze with conventional debugging techniques.<\/p>\n<p>We will create a basic program that toggles the on-board LED each time a button is pressed, will show that it doesn&#8217;t work as expected due to <a href=\"https:\/\/en.wikipedia.org\/wiki\/Switch#Contact_bounce\">contact bounce<\/a>, and will use Software Tracing to find the root cause and test a mitigation.<\/p>\n<ol>\n<li>Open Visual Studio and locate the VisualGDB Embedded Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/01-emb.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8619\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/01-emb.png\" alt=\"\" width=\"890\" height=\"625\" \/><\/a><\/li>\n<li>Enter the name and location of your project: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/02-name.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8620\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/02-name.png\" alt=\"\" width=\"890\" height=\"625\" \/><\/a><\/li>\n<li>Select <strong>Create a new project -&gt; Embedded Application -&gt; Advanced CMake<\/strong>: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/03-app.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8621\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/03-app.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Proceed with the ARM toolchain and pick the device you are trying to target: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/04-device.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8622\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/04-device.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Proceed with cloning the default &#8220;LEDBlink&#8221; example. As we will rely on the LEDs to demonstrate the contact bounce problem, make sure the LED port and pin match the actual LED location on your board: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/05-blink.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8623\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/05-blink.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Finally, choose the debugging settings that work with your board and click &#8220;Finish&#8221; to generate the project: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/06-debug.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8624\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/06-debug.png\" alt=\"\" width=\"917\" height=\"693\" \/><\/a><\/li>\n<li>Press F5 to build the project and begin debugging it. Make sure the on-board LED blinks every second as expected: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/07-blink.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8625\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/07-blink.png\" alt=\"\" width=\"1249\" height=\"843\" \/><\/a><\/li>\n<li>Now we will change the code to toggle the LED state each time the on-board button is pressed using a GPIO interrupt.<br \/>\nFirst of all, initialize the GPIO pin connected to the button (PA0 for STM32F4Discovery) and configure it as an falling edge input:<\/p>\n<pre class=\"\">\u00a0   GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;\r\n    GPIO_InitStructure.Pull = GPIO_NOPULL;\r\n    GPIO_InitStructure.Pin = GPIO_PIN_0;\r\n    HAL_GPIO_Init(GPIOA, &amp;GPIO_InitStructure);<\/pre>\n<p>Then, enable the external interrupt corresponding to the button pin number (e.g. EXTI0 for PA0, PB0, PC0, etc):<\/p>\n<pre class=\"\">\u00a0   HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0);\r\n    HAL_NVIC_EnableIRQ(EXTI0_IRQn);<\/pre>\n<p>Each time there is a falling edge on the PA0 signal, it will raise the EXTI0 interrupt, invoking <strong>EXTI0_IRQHandler()<\/strong>, that will in turn call <strong>HAL_GPIO_EXTI_IRQHandler() <\/strong>to clear the relevant interrupt flag and will finally pass control to the <strong>HAL_GPIO_EXTI_Callback()<\/strong> callback, that will actually toggle the LED. Add the following functions to the main file:<\/p>\n<pre class=\"\">extern \"C\" void EXTI0_IRQHandler(void)\r\n{\r\n    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);\r\n}\r\n\r\nextern \"C\" void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)\r\n{\r\n\tHAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);\r\n}<\/pre>\n<p>Note that VisualGDB can automatically lookup functions accepting GPIOx as the first argument as if it was a C++ class and the functions were methods. Try typing &#8220;GPIOD&#8221;, pressing &#8220;.&#8221; and selecting &#8220;<strong>HAL_GPIO_TogglePin<\/strong>&#8221; and VisualGDB will automatically generate a call to it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/08-toggle.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8626\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/08-toggle.png\" alt=\"\" width=\"1279\" height=\"843\" \/><\/a><\/li>\n<li>Build the program and run it again. Try pressing the button a few times. Note that sometimes the LED is toggled as expected, and sometimes it doesn&#8217;t. You can double-check the state of the <strong>GPIOA-&gt;IDR[0]<\/strong> bit via the Hardware Registers window, or setting a breakpoint in <strong>HAL_GPIO_EXTI_Callback()<\/strong>, but it won&#8217;t show anything unexpected:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/09-sporadic.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8627\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/09-sporadic.png\" alt=\"\" width=\"1279\" height=\"843\" \/><\/a><\/li>\n<li>The problem is caused by a phenomenon known as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Switch#Contact_bounce\">contact bounce<\/a> &#8211; the physical contacts inside the button can bounce back and forth, causing several extra transitions between 1 and 0, each of them toggling the LED: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/glitch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8636\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/glitch.png\" alt=\"\" width=\"567\" height=\"347\" \/><\/a><\/li>\n<li>Normal debugging techniques won&#8217;t reveal the problem because by the time a breakpoint event is processed, all bouncing inside the button will stop. Software tracing, on the other hand, works much faster, and cap easily capture such effects, and will give you a detailed timing as well. Click on the tracepoint bar (to the left of the breakpoint bar) and create a tracepoint on the LED toggling line, capturing the Cortex-M cycle counter:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/10-cycles.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8628\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/10-cycles.png\" alt=\"\" width=\"1279\" height=\"843\" \/><\/a><\/li>\n<li>Run the program and press the button several times until the problem is reproduced. Check the Tracepoints window for the list of trace events, each corresponding to a single invocation of the LED toggling line. Note that trace recording happens directly on the target, so it is fast enough to capture contact bounce and other fast hardware events:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/11-events.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8629\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/11-events.png\" alt=\"\" width=\"1279\" height=\"843\" \/><\/a><\/li>\n<li>Create a new table view via the Trace Data window, drag the <strong>Cortex-M Cycle Counter<\/strong> to the column list, and export the table into a CSV file: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/12-data.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8630\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/12-data.png\" alt=\"\" width=\"1279\" height=\"843\" \/><\/a><\/li>\n<li>Open the CSV file in Excel and create 2 additional columns: delta (difference between the previous line) and msec (delta divided by the clock frequency). It will very easily pinpoint the cases where the contact bounce happened, and will even show the exact timing: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/13-duplicate.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8631\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/13-duplicate.png\" alt=\"\" width=\"970\" height=\"672\" \/><\/a><\/li>\n<li>In this example, all bouncing happened in less than 0.1ms timeframe, so we can safely filter it out by simply ignoring interrupts happening within 1 ms from the previous interrupt. This can be easily done by utilizing a hardware timer:\n<pre class=\"\">static TIM_HandleTypeDef s_Timer = { TIM1 };\r\n\r\n\/\/...\r\n\r\n\u00a0   __TIM1_CLK_ENABLE();\r\n    s_Timer.Init.Period = 0xFFFF;\r\n    HAL_TIM_Base_Init(&amp;s_Timer);\r\n    HAL_TIM_Base_Start(&amp;s_Timer);    \r\n\r\n\/\/...\r\n\r\nextern \"C\" void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)\r\n{\r\n    if (__HAL_TIM_GET_FLAG(&amp;s_Timer, TIM_FLAG_UPDATE) != RESET || TIM1-&gt;CNT &gt;= 10000)\r\n    {\r\n        HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);\r\n    }\r\n    else\r\n    {\r\n        asm(\"nop\");\r\n    }\r\n    \r\n    TIM1-&gt;CNT = 0;\r\n    __HAL_TIM_CLEAR_FLAG(&amp;s_Timer, TIM_FLAG_UPDATE);\r\n}<\/pre>\n<p>Now we will only toggle the LED if the timer has counted more than 10K cycles since the last event, or had overflown at least once (i.e. raised the <strong>TIM_FLAG_UPDATE<\/strong> flag).<\/li>\n<li>You can verify the filter by setting tracepoints and both <strong>HAL_GPIO_TogglePin()<\/strong> and <strong>asm(&#8220;nop&#8221;)<\/strong> lines, and recording <strong>TIM1-&gt;CNT<\/strong> together with the cycle counter:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/14-newtp.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8632\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/14-newtp.png\" alt=\"\" width=\"1279\" height=\"843\" \/><\/a><\/li>\n<li>For convenience, you can give the created tracepoints more meaningful names via the Tracepoints window: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/15-rename.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8633\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/15-rename.png\" alt=\"\" width=\"1279\" height=\"843\" \/><\/a><\/li>\n<li>Press the button several times again until both valid and filtered out events are traced. You can double-check that the timer counter value roughly matches the difference in clock cycles since the last event:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/16-events.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8634\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/16-events.png\" alt=\"\" width=\"1279\" height=\"843\" \/><\/a><\/li>\n<li>All tracing data collected during debugging is saved into the <strong>.vgdbtrace<\/strong> files. You can review them via the <strong>Profiling\/Tracing Reports<\/strong> window, replay them, stepping through the events in the debugger, or create more tables or graphs, and export more data:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/summary-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8638\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/12\/summary-1.png\" alt=\"\" width=\"1279\" height=\"839\" \/><\/a>You can also collect tracing data in the field by running <a href=\"https:\/\/visualgdb.com\/documentation\/tracing\/#cmdline\">VisualGDB.exe \/trace<\/a>, and then analyze it on your development machine, or compare multiple recordings side-by-side.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use Software Tracing to troubleshoot hardware glitches that happen sporadically and are too fast to<\/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":[61,249],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8618"}],"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=8618"}],"version-history":[{"count":4,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8618\/revisions"}],"predecessor-version":[{"id":8641,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8618\/revisions\/8641"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=8618"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=8618"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=8618"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}