{"id":8828,"date":"2016-08-18T04:51:05","date_gmt":"2016-08-18T03:51:05","guid":{"rendered":"https:\/\/sysprogs.com\/w\/?p=8828"},"modified":"2016-08-18T04:52:48","modified_gmt":"2016-08-18T03:52:48","slug":"extending-real-time-watch-with-custom-events","status":"publish","type":"post","link":"https:\/\/sysprogs.com\/w\/extending-real-time-watch-with-custom-events\/","title":{"rendered":"Extending Real-time Watch with Custom Events"},"content":{"rendered":"<p>The\u00a0new Visual Watch feature in VisualGDB 5.2 helps quickly\u00a0visualize the timings of RTOS threads and functions, but what should you\u00a0do if\u00a0you want to track something\u00a0more fine-grain? Thankfully the answer is really simple and\u00a0I will show you why in just a moment.<a href=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/customwatch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-8829\" src=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/customwatch-1024x239.png\" alt=\"customwatch\" width=\"474\" height=\"111\" srcset=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/customwatch-1024x239.png 1024w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/customwatch-300x70.png 300w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/customwatch-768x179.png 768w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/customwatch.png 1086w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><!--more--><\/p>\n<h2>The Test Project<\/h2>\n<p>As usual, let&#8217;s start with\u00a0something\u00a0really simple: a\u00a0simple program for creating\u00a0the &#8220;Breathing&#8221; effect on an LED &#8211; gradually\u00a0changing it from fully on to fully off\u00a0using pulse-width modulation. The code behind it is just one loop inside one function, so\u00a0we won&#8217;t get away with visualizing it via function run time watch:<\/p>\n<pre class=\"\">for (double arg = 0;; arg += 0.05)\r\n{\r\n    double value = 0.5 + sin(arg) * 1;\r\n    const int totalPeriod = 50000;\r\n    g_DutyCycle.ReportValue(value);\r\n    int period = totalPeriod * value;\r\n \r\n    ScopedRunTimeReporter reporter(g_FirstWaitPeriod);\r\n    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);\r\n    for (int i = 0; i &lt; period; i++)\r\n        asm(\"nop\");\r\n \r\n    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);\r\n    period = totalPeriod - period;\r\n    for (int i = 0; i &lt; period; i++)\r\n        asm(\"nop\");\r\n}<\/pre>\n<p>Let&#8217;s start visualizing with the active period of the LED. We could use the\u00a0<a href=\"http:\/\/visualgdb.com\/tutorials\/arm\/livevars\/\">Live Variables<\/a> for that, but Live Variables\u00a0won&#8217;t show the precise\u00a0time when things happen, as they just periodically read your program&#8217;s memory. Real-time watch instead allows you to\u00a0capture the exact time when events happen, so you can better understand\u00a0concurrency issues.<\/p>\n<p>Adding a custom real-time watch consists of 3 steps. First, add a reference to the <strong>Fast Semihosting and Profiler framework<\/strong> and\u00a0include the <strong>CustomRealTimeWatches.h<\/strong> file:<\/p>\n<pre class=\"\">#include &lt;CustomRealTimeWatches.h&gt;<\/pre>\n<p>Then call the\u00a0InitializeCustomRealTimeWatch() function from your main():<\/p>\n<pre class=\"\">InitializeCustomRealTimeWatch();<\/pre>\n<p>Finally add a global real-time\u00a0watch object:<\/p>\n<pre class=\"\">ScalarRealTimeWatch g_DutyCycle;<\/pre>\n<p>Now you can modify your program to report arbitrary data to this watch:<\/p>\n<pre class=\"\">g_DutyCycle.ReportValue(value);<\/pre>\n<p>If you are using Plain C, you can use the C API instead:<\/p>\n<pre class=\"\">ScalarRealTimeWatch_ReportFPValue(g_DutyCycle, value);<\/pre>\n<p>Now all you need to do is start debugging and add g_DutyCycle to the real-time watch window and run your program to view the collected data:<a href=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/period-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-8830\" src=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/period-1-1024x237.png\" alt=\"period\" width=\"474\" height=\"110\" srcset=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/period-1-1024x237.png 1024w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/period-1-300x69.png 300w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/period-1-768x178.png 768w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/period-1.png 1085w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<p>Each data point will be marked with the precise timestamp, so you can measure the precise\u00a0time between various events:<a href=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/measure.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-8833\" src=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/measure-1024x240.png\" alt=\"measure\" width=\"474\" height=\"111\" srcset=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/measure-1024x240.png 1024w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/measure-300x70.png 300w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/measure-768x180.png 768w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/measure.png 1085w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<p>If you\u00a0are not using the\u00a0normal profiling functionality, VisualGDB won&#8217;t auto-detect the\u00a0ratio between\u00a0the\u00a0debug timer ticks\u00a0and real milliseconds, but you can easily\u00a0calibrate it by clicking on &#8220;Time unit&#8221;:<a href=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/calibrate.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8834\" src=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/calibrate.png\" alt=\"calibrate\" width=\"325\" height=\"155\" srcset=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/calibrate.png 325w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/calibrate-300x143.png 300w\" sizes=\"(max-width: 325px) 100vw, 325px\" \/><\/a><\/p>\n<p>Custom real-time watches report the data to VisualGDB through\u00a0a circular buffer in your\u00a0device&#8217;s memory, so they don&#8217;t produce much overhead.\u00a0Even better, the actual values are only reported if the watch is present in the Visual Watch window and not paused, so you don&#8217;t need to recompile your program each time you want to watch something new.<\/p>\n<h2>More Watch Types<\/h2>\n<p>Apart from ScalarRealTimeWatch VisualGDB\u00a0supports two other types of custom real-time watches. Let&#8217;s summarize them in a table:<\/p>\n<table>\n<tbody>\n<tr>\n<td>Watch type<\/td>\n<td>How to declare<\/td>\n<td>How to report data<\/td>\n<\/tr>\n<tr>\n<td>Precise run time of arbitrary code blocks<\/td>\n<td>\n<pre class=\"\">RunTimeWatch &lt;name&gt;;<\/pre>\n<\/td>\n<td>\n<pre class=\"\">{\r\n    ScopedRunTimeReporter reporter(&lt;name&gt;);\r\n    &lt;code&gt;\r\n}<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td>Arbitrary\u00a0events<\/td>\n<td>\n<pre class=\"\">EventStreamWatch &lt;name&gt;;<\/pre>\n<\/td>\n<td>\n<pre class=\"\">&lt;name&gt;.ReportEvent(\"&lt;event text&gt;\");<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The run time watch will capture the exact start and stop\u00a0time of any\u00a0block of code,\u00a0so you can use it to compare execution times\u00a0of various parts of your function. The\u00a0event stream watch can show arbitrary events, so you can use it to display things like\u00a0buffer overflows or button presses. The simplest example would be\u00a0to use\u00a0the\u00a0execution time\u00a0reporter\u00a0to\u00a0track the times when the LED is on:<\/p>\n<pre class=\"\">{\r\n    ScopedRunTimeReporter reporter(g_FirstWaitPeriod);\r\n    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);\r\n    for (int i = 0; i &lt; period; i++)\r\n        asm(\"nop\");\r\n}<\/pre>\n<p><a href=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/zoom.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-8835\" src=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/zoom-1024x237.png\" alt=\"zoom\" width=\"474\" height=\"110\" srcset=\"https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/zoom-1024x237.png 1024w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/zoom-300x69.png 300w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/zoom-768x177.png 768w, https:\/\/sysprogs.com\/w\/wp-content\/uploads\/2016\/08\/zoom.png 1082w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<h2>Overhead<\/h2>\n<p>Reporting data via\u00a0real-time watch is just a matter of\u00a0storing it\u00a0inside RAM in a\u00a0format that VisualGDB can read, so it does not\u00a0slow down your program too much. However\u00a0if the enabled watches generate too much data, the program will be paused until VisualGDB can read the data and that could slow it down considerably.\u00a0<span style=\"line-height: 1.5;\">So if you want to use Real-time watch to record something very\u00a0intense, set a breakpoint before and after the intense block to\u00a0give VisualGDB enough time to empty the buffer before the heavy\u00a0action\u00a0starts.<\/span><\/p>\n<h2>Download<\/h2>\n<p>You can download VisualGDB 5.2 Preview 2 with the real-time watch feature on the <a href=\"http:\/\/visualgdb.com\/download\/\">download page<\/a>. We would appreciate any feedback on the new features and bugs, so don&#8217;t hesitate to drop us an email or contact us via the\u00a0<a href=\"http:\/\/sysprogs.com\/support\/\">support form<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The\u00a0new Visual Watch feature in VisualGDB 5.2 helps quickly\u00a0visualize the timings of RTOS threads and functions, but what should you\u00a0do if\u00a0you want to track something\u00a0more fine-grain? Thankfully the answer is really simple and\u00a0I will show you why in just a moment.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"footnotes":""},"categories":[1],"tags":[216],"_links":{"self":[{"href":"https:\/\/sysprogs.com\/w\/wp-json\/wp\/v2\/posts\/8828"}],"collection":[{"href":"https:\/\/sysprogs.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sysprogs.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sysprogs.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sysprogs.com\/w\/wp-json\/wp\/v2\/comments?post=8828"}],"version-history":[{"count":3,"href":"https:\/\/sysprogs.com\/w\/wp-json\/wp\/v2\/posts\/8828\/revisions"}],"predecessor-version":[{"id":8878,"href":"https:\/\/sysprogs.com\/w\/wp-json\/wp\/v2\/posts\/8828\/revisions\/8878"}],"wp:attachment":[{"href":"https:\/\/sysprogs.com\/w\/wp-json\/wp\/v2\/media?parent=8828"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sysprogs.com\/w\/wp-json\/wp\/v2\/categories?post=8828"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sysprogs.com\/w\/wp-json\/wp\/v2\/tags?post=8828"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}