{"id":4398,"date":"2018-11-19T16:22:31","date_gmt":"2018-11-20T00:22:31","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=4398"},"modified":"2018-11-19T17:04:29","modified_gmt":"2018-11-20T01:04:29","slug":"tracing-the-real-time-events-in-rtx-based-projects-with-real-time-watch","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/arm\/keil\/rtx\/tracing\/","title":{"rendered":"Tracing the Real-Time Events in RTX-based Projects with Real-Time Watch"},"content":{"rendered":"<p>This tutorial shows how to use the real-time watch feature of VisualGDB to trace the thread and function run times as well as the mutex and queue use\u00a0for\u00a0projects based on the RTX operating system. We will\u00a0create a\u00a0basic project using the Keil compiler, add the RTX5 pack to it and will show how to\u00a0use real-time watch to trace various events in it.<\/p>\n<p>Before you begin, install VisualGDB 5.4 Preview 10 or later and create a basic &#8220;Blinking LED&#8221; project\u00a0using the RTX operating system by following <a href=\"https:\/\/visualgdb.com\/tutorials\/arm\/keil\/rtx\/\">this tutorial<\/a>.<\/p>\n<ol>\n<li>Open\u00a0VisualGDB Project Propertes for your project and go to the Embedded Frameworks page. Then reference the &#8220;Fast Semihosting and Embedded Profiler&#8221; framework:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/01-framework.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4399\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/01-framework.png\" alt=\"01-framework\" width=\"955\" height=\"656\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/01-framework.png 955w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/01-framework-300x206.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/01-framework-130x90.png 130w\" sizes=\"(max-width: 955px) 100vw, 955px\" \/><\/a>As configuring the sampling profiler under the Keil compiler requires extra steps,\u00a0select &#8220;Exclude sampling profiler code&#8221; in the framework configuration. Also set RTOS support to &#8220;Keil RTX&#8221;.<\/li>\n<li>Include the <strong>&lt;SysprogsProfiler.h&gt;<\/strong> file from your main() function and call InitializeInstrumentingProfiler() after you\u00a0set the system clock frequency:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/02-init.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4400\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/02-init.png\" alt=\"02-init\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/02-init.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/02-init-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/02-init-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<li>Open VisualGDB Project Properties again, go to the Dynamic\u00a0Analysis page and enable\u00a0tracing of RTOS events and function calls.\u00a0If the project is not configured to generate relocation records,\u00a0click on the link at the bottom of the page to automatically enable them:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/03-profile.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4401\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/03-profile.png\" alt=\"03-profile\" width=\"955\" height=\"656\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/03-profile.png 955w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/03-profile-300x206.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/03-profile-130x90.png 130w\" sizes=\"(max-width: 955px) 100vw, 955px\" \/><\/a><\/li>\n<li>Build the project and start debugging it. If\u00a0you are using a version of RTX that does not include a\u00a0low-level thread switch hook, the debugging will fail\u00a0complaining about the missing <strong>thread_switch_helper()<\/strong> function:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/04-fail.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4402\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/04-fail.png\" alt=\"04-fail\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/04-fail.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/04-fail-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/04-fail-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<li>In order to fix it, locate the\u00a0RTX interrupt handler file (e.g. irq_cm4f.s) and find the SVC_ContextSwitch label. Add the following code after the &#8220;STR R2,[R3]&#8221; instruction:\n<pre class=\"\">PUSH {R2,R3} ; Save registers\r\nbl thread_switch_helper\r\nPOP {R2,R3} ; Restore registers<\/pre>\n<p>Also add the &#8220;IMPORT thread_switch_helper&#8221; statement\u00a0after the &#8220;IMPORT osRtxInfo&#8221; statement in the beginning of the SVC_Handler call:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/05-helper.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4403\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/05-helper.png\" alt=\"05-helper\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/05-helper.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/05-helper-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/05-helper-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a>Finally, add an empty thread_switch_helper() function in one of your source files (don&#8217;t forget to mark it with extern &#8220;C&#8221; if you are using C++):<\/p>\n<pre class=\"\">void thread_switch_helper()\r\n{\r\n}<\/pre>\n<p>When you start\u00a0a profiling or real-time watch session with VisualGDB, the\u00a0it will hook the\u00a0<strong>thread_switch_helper()<\/strong> function\u00a0redirecting it to\u00a0<strong>SysprogsRTOSHooks_RTX_thread_switch_helper()<\/strong>, that will\u00a0allow the profiler\u00a0framework to\u00a0maintain separate contexts for each of the RTOS threads. Hooking the low-level <strong>thread_switch_helper()<\/strong> instead\u00a0using a higher-level\u00a0<strong>EvtRtxThreadSwitched()<\/strong> callback allows instrumenting not only the user-mode code, but the RTX functions\u00a0related to the high-level thread switching logic.<\/li>\n<li>Press F5 to begin debugging. Set a breakpoint in one of the threads and wait for it to trigger. Then open the real-time watch window and enable the &#8220;Show RTOS threads&#8221; checkbox. Once you resume the program, VisualGDB will visualize the run times of your threads.\u00a0In this example, thread #1 runs twice more frequently than thread #2 as it uses twice shorter sleep delays:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/06-rtw.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4404\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/06-rtw.png\" alt=\"06-rtw\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/06-rtw.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/06-rtw-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/06-rtw-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<li>Add the <strong>LED_On()<\/strong> and <strong>LED_Off()<\/strong> functions to the real-time watch:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/07-led.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4405\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/07-led.png\" alt=\"07-led\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/07-led.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/07-led-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/07-led-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<li>If you try resuming the session now, the program will fail with the &#8220;Stack underflow&#8221; condition:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/08-stack.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4406\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/08-stack.png\" alt=\"08-stack\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/08-stack.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/08-stack-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/08-stack-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<li>This happens because the default RTX stack size is too small for the VisualGDB&#8217;s\u00a0profiler framework functions\u00a0in the debug configuration (with no optimization). You can fix this by\u00a0adding &#8220;.stack_size = 4096&#8221; to the thread attributes of both threads.\u00a0However, if you try running this version of the program, you will observe that the 2 user threads were never created:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/09-nothread.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4407\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/09-nothread.png\" alt=\"09-nothread\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/09-nothread.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/09-nothread-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/09-nothread-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<li>This happens because the default RTX dynamic memory size it too small. You can increase it by adding &#8220;OS_DYNAMIC_MEM_SIZE=16384&#8221; to the preprocessor definitions:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/10-memsize.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4408\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/10-memsize.png\" alt=\"10-memsize\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/10-memsize.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/10-memsize-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/10-memsize-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<li>Note how this increases the size of the <strong>os_mem<\/strong> variable by 12KB:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/11-delta.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4409\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/11-delta.png\" alt=\"11-delta\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/11-delta.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/11-delta-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/11-delta-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<li>Now you can run the\u00a0program and see the timing diagram for the LED_On() and LED_Off() functions\u00a0along with the thread times:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/12-onoff.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4410\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/12-onoff.png\" alt=\"12-onoff\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/12-onoff.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/12-onoff-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/12-onoff-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<li>Now we will show how to track the ownership of RTX mutexes with real-time watch. Add the following code to your project:\n<pre class=\"\">osMutexId_t g_Mutex;\r\n\r\nvoid ExclusiveWait(int delay)\r\n{\r\n    osMutexAcquire(g_Mutex, osWaitForever);\r\n    osDelay(delay);\r\n    osMutexRelease(g_Mutex);\r\n}\r\n\r\n\/\/...\r\n\r\nint main(void)\r\n{\r\n    \/\/...\r\n    osMutexAttr_t mutexAttr = { .name = \"TestMutex\" };\r\n    g_Mutex = osMutexNew(&amp;mutexAttr);\r\n}\r\n\r\n<\/pre>\n<p>Then change the thread functions to call ExclusiveWait() instead of osDelay(). This will ensure that\u00a0only one thread at a time will be able to call ExclusiveWait(), so the wait times of the threads will be added.<\/li>\n<li>Start debugging and add g_Mutex to the real-time watch window:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/13-zoomin.png\"><br \/>\n<\/a> <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/14-mutex.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4412\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/14-mutex.png\" alt=\"14-mutex\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/14-mutex.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/14-mutex-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/14-mutex-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<li>Let the program run for a few\u00a0seconds and observe the real-time watch.\u00a0Note how the two threads take turns in owning the mutex:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/15-mutextimes.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4413\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/15-mutextimes.png\" alt=\"15-mutextimes\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/15-mutextimes.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/15-mutextimes-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/15-mutextimes-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<li>Finally, we will demonstrate\u00a0the use of a semaphore. Change the code in your main file as shown below:\n<pre class=\"\">osSemaphoreId_t g_Semaphore;\r\n\r\nvoid ExclusiveWait(int delay)\r\n{\r\n    osMutexAcquire(g_Mutex, osWaitForever);\r\n    osDelay(delay);\r\n    osMutexRelease(g_Mutex);\r\n}\r\n\r\nvoid Thread1Body(void *argument)\r\n{\r\n    for (;;)\r\n    {\r\n        osSemaphoreAcquire(g_Semaphore, osWaitForever);\r\n        osDelay(10);\r\n    }\r\n}\r\n\r\nvoid Thread2Body(void *argument)\r\n{\r\n    for (;;)\r\n    {\r\n        for (int i = 0; i &lt; 10; i++)\r\n            osSemaphoreRelease(g_Semaphore);\r\n        osDelay(200);\r\n    }\r\n}\r\n\r\nint main(void)\r\n{\r\n    osSemaphoreAttr_t semaphoreAttr = { .name = \"TestSemaphore\" };\r\n    g_Semaphore = osSemaphoreNew(1000, 0, &amp;semaphoreAttr);\r\n    \/\/..\r\n}\r\n<\/pre>\n<p>This will demonstrate a very basic producer\/consumer\u00a0scenario where thread #1 quickly produces 10 tokens and waits for a long time while thread #1 is consistently consuming the tokens at a slower rate.<\/li>\n<li>Start debugging and\u00a0add <strong>g_Semaphore<\/strong> to real-time watch. Observe how the semaphore value quickly reaches the maximum and then slowly decreases as thread #1 keeps on\u00a0consuming the tokens:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/16-semaphoretiming.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4414\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/16-semaphoretiming.png\" alt=\"16-semaphoretiming\" width=\"1097\" height=\"784\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/16-semaphoretiming.png 1097w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/16-semaphoretiming-300x214.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/11\/16-semaphoretiming-1024x732.png 1024w\" sizes=\"(max-width: 1097px) 100vw, 1097px\" \/><\/a><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use the real-time watch feature of VisualGDB to trace the thread and function run times<\/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,147,175],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/4398"}],"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=4398"}],"version-history":[{"count":2,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/4398\/revisions"}],"predecessor-version":[{"id":4416,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/4398\/revisions\/4416"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=4398"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=4398"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=4398"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}