{"id":1235,"date":"2015-12-07T19:44:13","date_gmt":"2015-12-08T03:44:13","guid":{"rendered":"http:\/\/visualgdb.com\/w\/?p=1235"},"modified":"2015-12-07T19:52:57","modified_gmt":"2015-12-08T03:52:57","slug":"adding-support-for-more-platforms-to-the-embedded-profiler","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/profiler\/embedded\/sampling\/driver\/","title":{"rendered":"Adding support for more platforms to the Embedded Profiler"},"content":{"rendered":"<p>This tutorial shows how to add support for more platforms to the VisualGDB Embedded Profiler. We will create a project for the Freescale Kinetis FRDM-K64F board and modify the STM32 profiler driver to support the Kinetis board. As of VisualGDB 5.1 Preview 1, the profiler framework contains drivers for STM32, Freescale Kinetis and Nordic nRF51 devices. We use Freescale devices in this tutorial to explain the structure of a driver and explain how to create one.<\/p>\n<ol>\n<li>Create a normal LEDBlink project for your board using the VisualGDB Embedded Project Wizard:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/01-prj1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1236\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/01-prj1.png\" alt=\"01-prj\" width=\"786\" height=\"489\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/01-prj1.png 786w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/01-prj1-300x187.png 300w\" sizes=\"(max-width: 786px) 100vw, 786px\" \/><\/a><\/li>\n<li>Use the default &#8220;Embedded binary&#8221; setting:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/02-binary.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1237\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/02-binary.png\" alt=\"02-binary\" width=\"688\" height=\"565\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/02-binary.png 688w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/02-binary-300x246.png 300w\" sizes=\"(max-width: 688px) 100vw, 688px\" \/><\/a><\/li>\n<li>Select your device and proceed with the default settings for it:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/03-device1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1238\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/03-device1.png\" alt=\"03-device\" width=\"688\" height=\"565\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/03-device1.png 688w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/03-device1-300x246.png 300w\" sizes=\"(max-width: 688px) 100vw, 688px\" \/><\/a><\/li>\n<li>Select any sample, such as &#8220;LEDBlink&#8221;:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/04-sample1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1239\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/04-sample1.png\" alt=\"04-sample\" width=\"688\" height=\"565\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/04-sample1.png 688w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/04-sample1-300x246.png 300w\" sizes=\"(max-width: 688px) 100vw, 688px\" \/><\/a><\/li>\n<li>Select your usual debug method. Note that the profiler will only work with OpenOCD or Segger J-Link:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/05-jlink.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1240\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/05-jlink.png\" alt=\"05-jlink\" width=\"688\" height=\"601\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/05-jlink.png 688w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/05-jlink-300x262.png 300w\" sizes=\"(max-width: 688px) 100vw, 688px\" \/><\/a><\/li>\n<li>Press Finish to create your project. Then open VisualGDB Project Properties, go to the Embedded Frameworks page and reference the Fast Semihosting and Embedded Profiler framework. For Kinetis devices also reference the Kinetis Platform framework as it actually contains the drivers for the timers the profiler uses:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/06-frameworks.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1241\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/06-frameworks.png\" alt=\"06-frameworks\" width=\"729\" height=\"594\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/06-frameworks.png 729w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/06-frameworks-300x244.png 300w\" sizes=\"(max-width: 729px) 100vw, 729px\" \/><\/a><\/li>\n<li>The profiler framework already contains a driver for the Kinetis devices, however in this tutorial we will delete it and create one by modifying the STM32 driver to show all the necessary steps. Remove the SamplingProfiler_Kinetis.cpp file from your project:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/07-driver.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1242\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/07-driver.png\" alt=\"07-driver\" width=\"783\" height=\"619\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/07-driver.png 783w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/07-driver-300x237.png 300w\" sizes=\"(max-width: 783px) 100vw, 783px\" \/><\/a><\/li>\n<li>Then create a new source file and copy the contents of the %LOCALAPPDATA%\\VisualGDB\\EmbeddedEFPs\\Profiler\\SamplingProfiler_STM32_HAL.cpp file there. Replace the #include&lt;&gt; statements with the statements for your platform. For Kinetis devices we will need to include <strong>fsl_hwtimer.h<\/strong>, <strong>fsl_hwtimer_pit.h<\/strong> and <strong>fsl_pit_driver.h<\/strong>:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/08-includes.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1243\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/08-includes.png\" alt=\"08-includes\" width=\"783\" height=\"619\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/08-includes.png 783w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/08-includes-300x237.png 300w\" sizes=\"(max-width: 783px) 100vw, 783px\" \/><\/a><\/li>\n<li>The first step in creating the driver is providing an initialization function that configures a hardware timer to fire periodic interrupts. You should also provide a function to change the timer frequency during runtime, as the automatic rate logic uses it. In this example we will use the channel 0 of the periodic interrupt timer (PIT0):\n<pre class=\"\">static hwtimer_t hwtimer;\r\n\r\nstatic void UpdateProfilerTimerFrequency()\r\n{\r\n\u00a0\u00a0 \u00a0if (g_SamplingProfilerRate == 0)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return;\r\n\u00a0\u00a0 \u00a0SystemCoreClockUpdate();\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0HWTIMER_SYS_SetPeriod(&amp;hwtimer, 1000000 \/ g_SamplingProfilerRate);\r\n}\r\n\r\nvoid InitializeSamplingProfiler()\r\n{\r\n\u00a0\u00a0 \u00a0if (!g_EnableSamplingProfiler)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return;\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0HWTIMER_SYS_Init(&amp;hwtimer, &amp;kPitDevif, 0, NULL);\r\n\u00a0\u00a0 \u00a0UpdateProfilerTimerFrequency();\r\n\u00a0\u00a0 \u00a0HWTIMER_SYS_Start(&amp;hwtimer);\r\n}<\/pre>\n<p><a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/09-init.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1244\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/09-init.png\" alt=\"09-init\" width=\"783\" height=\"619\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/09-init.png 783w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/09-init-300x237.png 300w\" sizes=\"(max-width: 783px) 100vw, 783px\" \/><\/a><\/li>\n<li>The second step of writing a profiler driver is handling the interrupts fired by the timer and extracting the PC, SP, FP and LR register. Thankfully, all ARM Cortex cores share the same interrupt handling mechanism that stores those registers in a <a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.dui0552a\/Babefdjc.html\">common pattern<\/a>, so you can simply reuse the handler from the STM32 driver. Rename it accordingly and don&#8217;t forget to put extern &#8220;C&#8221; around it:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/10-handler.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1245\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/10-handler.png\" alt=\"10-handler\" width=\"783\" height=\"619\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/10-handler.png 783w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/10-handler-300x237.png 300w\" sizes=\"(max-width: 783px) 100vw, 783px\" \/><\/a><\/li>\n<li>The third and the final step is to tell the timer that the interrupt is being handled and invoke the SysprogsProfiler_ProcessSample() function with the PC, SP, FP and LR register values extracted from the stack:\n<pre class=\"\">\u00a0\u00a0\u00a0 void SysprogsProfiler_DoHandleTimerIRQ(void *PC, void *SP, void *FP, void *LR)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0PIT_Type * base = g_pitBase[0];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (PIT_HAL_IsIntPending(base, 0))\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0PIT_HAL_ClearIntFlag(base, 0);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0SysprogsProfiler_ProcessSample(PC, SP, FP, LR);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (g_SamplingProfilerRate != 0)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0UpdateProfilerTimerFrequency();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0g_SamplingProfilerRate = 0;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0}<\/pre>\n<p><a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/11-handle.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1246\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/11-handle.png\" alt=\"11-handle\" width=\"783\" height=\"619\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/11-handle.png 783w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/11-handle-300x237.png 300w\" sizes=\"(max-width: 783px) 100vw, 783px\" \/><\/a>Note the code checking the <strong>g_SamplingProfilerRate<\/strong> variable. If the automatic rate adjustment is enabled, the logic inside SysprogsProfiler_ProcessSample() may decide to adjust the timer frequency. If it does that, the <strong>g_SamplingProfilerRate<\/strong> will be set and your driver is responsible for applying it.<\/li>\n<li>Do not forget to call <strong>InitializeSamplingProfiler()<\/strong> from your main() function and you are good to go. Build your project and select Analyze-&gt;Analyzer Performance with VisualGDB to start profiling:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/12-start.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1247\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/12-start.png\" alt=\"12-start\" width=\"546\" height=\"394\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/12-start.png 546w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/12-start-300x216.png 300w\" sizes=\"(max-width: 546px) 100vw, 546px\" \/><\/a>In this example we will select a fixed rate of 100 samples\/second to check that the rate is set correctly.<\/li>\n<li>Observe the Live Profiling window to see that the samples are arriving and that the stack trace matches the expected one:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/13-stack.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1248\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/13-stack.png\" alt=\"13-stack\" width=\"783\" height=\"619\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/13-stack.png 783w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/13-stack-300x237.png 300w\" sizes=\"(max-width: 783px) 100vw, 783px\" \/><\/a><\/li>\n<li>You can switch the view to the Diagnostics mode to see various information about the profiling session. Verify that the speed matches the one selected when you started the session. If not, modify your driver to do the necessary adjustments to match the requested speed:<a href=\"http:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/14-diag.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1249\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/14-diag.png\" alt=\"14-diag\" width=\"783\" height=\"619\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/14-diag.png 783w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2015\/12\/14-diag-300x237.png 300w\" sizes=\"(max-width: 783px) 100vw, 783px\" \/><\/a><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to add support for more platforms to the VisualGDB Embedded Profiler. We will create a project<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[108,107],"tags":[57,109,110],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/1235"}],"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=1235"}],"version-history":[{"count":4,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/1235\/revisions"}],"predecessor-version":[{"id":1253,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/1235\/revisions\/1253"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=1235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=1235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=1235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}